From 1d02aa4b855aa851430c5db67e5af5c8cfa7379b Mon Sep 17 00:00:00 2001 From: Joshua Truscott Date: Mon, 20 Nov 2017 01:45:58 +1100 Subject: [PATCH] Deleted unrelated patterns --- .travis.yml | 39 -- CODE_COVERAGE.md | 13 - CONTRIBUTING.MD | 4 - LICENSE.md | 21 - README.md | 47 -- _scripts/postPumlsToServer.py | 67 -- abstract-document/README.md | 32 - .../etc/abstract-document-base.png | Bin 14973 -> 0 bytes .../etc/abstract-document-base.ucls | 58 -- abstract-document/etc/abstract-document.png | Bin 16712 -> 0 bytes abstract-document/etc/abstract-document.ucls | 96 --- .../etc/abstract-document.urm.puml | 59 -- abstract-document/pom.xml | 42 -- .../abstractdocument/AbstractDocument.java | 72 -- .../com/iluwatar/abstractdocument/App.java | 91 --- .../iluwatar/abstractdocument/Document.java | 59 -- .../iluwatar/abstractdocument/domain/Car.java | 38 - .../abstractdocument/domain/HasModel.java | 40 -- .../abstractdocument/domain/HasParts.java | 40 -- .../abstractdocument/domain/HasPrice.java | 40 -- .../abstractdocument/domain/HasType.java | 40 -- .../abstractdocument/domain/Part.java | 38 - .../AbstractDocumentTest.java | 88 --- .../iluwatar/abstractdocument/AppTest.java | 37 - .../iluwatar/abstractdocument/DomainTest.java | 77 -- abstract-factory/.gitignore | 1 - abstract-factory/README.md | 152 ---- abstract-factory/pom.xml | 42 -- .../com/iluwatar/abstractfactory/App.java | 120 ---- .../com/iluwatar/abstractfactory/Army.java | 33 - .../com/iluwatar/abstractfactory/Castle.java | 33 - .../com/iluwatar/abstractfactory/ElfArmy.java | 38 - .../iluwatar/abstractfactory/ElfCastle.java | 38 - .../com/iluwatar/abstractfactory/ElfKing.java | 38 - .../abstractfactory/ElfKingdomFactory.java | 44 -- .../com/iluwatar/abstractfactory/King.java | 33 - .../abstractfactory/KingdomFactory.java | 38 - .../com/iluwatar/abstractfactory/OrcArmy.java | 38 - .../iluwatar/abstractfactory/OrcCastle.java | 38 - .../com/iluwatar/abstractfactory/OrcKing.java | 38 - .../abstractfactory/OrcKingdomFactory.java | 43 -- .../abstractfactory/AbstractFactoryTest.java | 103 --- .../com/iluwatar/abstractfactory/AppTest.java | 38 - aggregator-microservices/README.md | 30 - .../aggregator-service/pom.xml | 88 --- .../aggregator/microservices/Aggregator.java | 58 -- .../aggregator/microservices/App.java | 42 -- .../aggregator/microservices/Product.java | 57 -- .../ProductInformationClient.java | 32 - .../ProductInformationClientImpl.java | 57 -- .../microservices/ProductInventoryClient.java | 31 - .../ProductInventoryClientImpl.java | 57 -- .../src/main/resources/application.properties | 24 - .../microservices/AggregatorTest.java | 70 -- .../etc/aggregator-microservice.png | Bin 41304 -> 0 bytes .../etc/aggregator-service.urm.puml | 43 -- .../etc/information-microservice.urm.puml | 12 - .../etc/inventory-microservice.urm.puml | 12 - .../information-microservice/pom.xml | 79 --- .../microservice/InformationApplication.java | 37 - .../microservice/InformationController.java | 44 -- .../src/main/resources/application.properties | 24 - .../InformationControllerTest.java | 42 -- .../inventory-microservice/pom.xml | 79 --- .../microservice/InventoryApplication.java | 38 - .../microservice/InventoryController.java | 45 -- .../src/main/resources/application.properties | 24 - .../microservice/InventoryControllerTest.java | 40 -- aggregator-microservices/pom.xml | 63 -- api-gateway/README.md | 31 - api-gateway/api-gateway-service/pom.xml | 87 --- .../com/iluwatar/api/gateway/ApiGateway.java | 64 -- .../java/com/iluwatar/api/gateway/App.java | 66 -- .../iluwatar/api/gateway/DesktopProduct.java | 54 -- .../com/iluwatar/api/gateway/ImageClient.java | 30 - .../iluwatar/api/gateway/ImageClientImpl.java | 56 -- .../iluwatar/api/gateway/MobileProduct.java | 41 -- .../com/iluwatar/api/gateway/PriceClient.java | 30 - .../iluwatar/api/gateway/PriceClientImpl.java | 56 -- .../src/main/resources/application.properties | 24 - .../iluwatar/api/gateway/ApiGatewayTest.java | 81 --- api-gateway/etc/api-gateway-service.urm.puml | 48 -- api-gateway/etc/api-gateway.png | Bin 18323 -> 0 bytes api-gateway/etc/api-gateway.ucls | 97 --- api-gateway/etc/image-microservice.urm.puml | 12 - api-gateway/etc/price-microservice.urm.puml | 12 - .../etc/image-microservice.png | Bin 2695 -> 0 bytes .../etc/image-microservice.ucls | 20 - api-gateway/image-microservice/pom.xml | 79 --- .../image/microservice/ImageApplication.java | 43 -- .../image/microservice/ImageController.java | 43 -- .../src/main/resources/application.properties | 24 - .../microservice/ImageControllerTest.java | 40 -- api-gateway/pom.xml | 63 -- .../etc/price-microservice.png | Bin 2572 -> 0 bytes .../etc/price-microservice.ucls | 20 - api-gateway/price-microservice/pom.xml | 79 --- .../price/microservice/PriceApplication.java | 43 -- .../price/microservice/PriceController.java | 43 -- .../src/main/resources/application.properties | 24 - .../microservice/PriceControllerTest.java | 41 -- async-method-invocation/README.md | 34 - .../etc/async-method-invocation.png | Bin 36923 -> 0 bytes .../etc/async-method-invocation.ucls | 85 --- .../etc/async-method-invocation.urm.puml | 51 -- async-method-invocation/pom.xml | 47 -- .../iluwatar/async/method/invocation/App.java | 130 ---- .../method/invocation/AsyncCallback.java | 43 -- .../method/invocation/AsyncExecutor.java | 63 -- .../async/method/invocation/AsyncResult.java | 55 -- .../invocation/ThreadAsyncExecutor.java | 148 ---- .../async/method/invocation/AppTest.java | 39 -- .../invocation/ThreadAsyncExecutorTest.java | 311 -------- balking/README.md | 27 - balking/etc/balking.png | Bin 21427 -> 0 bytes balking/etc/balking.ucls | 46 -- balking/etc/balking.urm.puml | 24 - balking/pom.xml | 46 -- .../main/java/com/iluwatar/balking/App.java | 65 -- .../com/iluwatar/balking/WashingMachine.java | 76 -- .../iluwatar/balking/WashingMachineState.java | 32 - .../java/com/iluwatar/balking/AppTest.java | 39 -- .../iluwatar/balking/WashingMachineTest.java | 65 -- bridge/README.md | 194 ----- bridge/pom.xml | 47 -- .../main/java/com/iluwatar/bridge/App.java | 63 -- .../java/com/iluwatar/bridge/Enchantment.java | 37 - .../iluwatar/bridge/FlyingEnchantment.java | 51 -- .../main/java/com/iluwatar/bridge/Hammer.java | 65 -- .../bridge/SoulEatingEnchantment.java | 51 -- .../main/java/com/iluwatar/bridge/Sword.java | 65 -- .../main/java/com/iluwatar/bridge/Weapon.java | 39 -- .../java/com/iluwatar/bridge/AppTest.java | 39 -- .../java/com/iluwatar/bridge/HammerTest.java | 45 -- .../java/com/iluwatar/bridge/SwordTest.java | 45 -- .../java/com/iluwatar/bridge/WeaponTest.java | 59 -- builder/.gitignore | 1 - builder/README.md | 134 ---- builder/pom.xml | 42 -- .../main/java/com/iluwatar/builder/App.java | 81 --- .../main/java/com/iluwatar/builder/Armor.java | 44 -- .../java/com/iluwatar/builder/HairColor.java | 39 -- .../java/com/iluwatar/builder/HairType.java | 45 -- .../main/java/com/iluwatar/builder/Hero.java | 149 ---- .../java/com/iluwatar/builder/Profession.java | 38 - .../java/com/iluwatar/builder/Weapon.java | 38 - .../java/com/iluwatar/builder/AppTest.java | 39 -- .../java/com/iluwatar/builder/HeroTest.java | 78 --- business-delegate/README.md | 30 - business-delegate/etc/business-delegate.png | Bin 24283 -> 0 bytes business-delegate/etc/business-delegate.ucls | 136 ---- .../etc/business-delegate.urm.puml | 57 -- business-delegate/pom.xml | 48 -- .../com/iluwatar/business/delegate/App.java | 62 -- .../business/delegate/BusinessDelegate.java | 46 -- .../business/delegate/BusinessLookup.java | 53 -- .../business/delegate/BusinessService.java | 33 - .../iluwatar/business/delegate/Client.java | 41 -- .../business/delegate/EjbService.java | 41 -- .../business/delegate/JmsService.java | 41 -- .../business/delegate/ServiceType.java | 33 - .../iluwatar/business/delegate/AppTest.java | 38 - .../delegate/BusinessDelegateTest.java | 100 --- caching/.gitignore | 1 - caching/README.md | 30 - caching/etc/caching.png | Bin 114847 -> 0 bytes caching/etc/caching.ucls | 90 --- caching/etc/caching.urm.puml | 110 --- caching/pom.xml | 75 -- .../main/java/com/iluwatar/caching/App.java | 169 ----- .../java/com/iluwatar/caching/AppManager.java | 133 ---- .../java/com/iluwatar/caching/CacheStore.java | 182 ----- .../com/iluwatar/caching/CachingPolicy.java | 42 -- .../java/com/iluwatar/caching/DbManager.java | 164 ----- .../java/com/iluwatar/caching/LruCache.java | 190 ----- .../com/iluwatar/caching/UserAccount.java | 70 -- .../java/com/iluwatar/caching/AppTest.java | 38 - .../com/iluwatar/caching/CachingTest.java | 68 -- callback/README.md | 29 - callback/etc/callback.png | Bin 8577 -> 0 bytes callback/etc/callback.ucls | 41 -- callback/etc/callback.urm.puml | 28 - callback/pom.xml | 42 -- .../main/java/com/iluwatar/callback/App.java | 52 -- .../java/com/iluwatar/callback/Callback.java | 33 - .../com/iluwatar/callback/LambdasApp.java | 46 -- .../com/iluwatar/callback/SimpleTask.java | 41 -- .../main/java/com/iluwatar/callback/Task.java | 43 -- .../java/com/iluwatar/callback/AppTest.java | 38 - .../com/iluwatar/callback/CallbackTest.java | 79 --- chain/README.md | 160 ----- chain/pom.xml | 42 -- .../src/main/java/com/iluwatar/chain/App.java | 53 -- .../java/com/iluwatar/chain/OrcCommander.java | 50 -- .../main/java/com/iluwatar/chain/OrcKing.java | 46 -- .../java/com/iluwatar/chain/OrcOfficer.java | 51 -- .../java/com/iluwatar/chain/OrcSoldier.java | 50 -- .../main/java/com/iluwatar/chain/Request.java | 100 --- .../com/iluwatar/chain/RequestHandler.java | 58 -- .../java/com/iluwatar/chain/RequestType.java | 34 - .../test/java/com/iluwatar/chain/AppTest.java | 39 -- .../java/com/iluwatar/chain/OrcKingTest.java | 59 -- checkstyle-suppressions.xml | 33 - checkstyle.xml | 197 ------ converter/README.md | 29 - converter/etc/Converter.png | Bin 19389 -> 0 bytes converter/etc/Converter.ucls | 51 -- converter/etc/converter.urm.puml | 49 -- converter/pom.xml | 49 -- .../main/java/com/iluwatar/converter/App.java | 60 -- .../com/iluwatar/converter/Converter.java | 86 --- .../java/com/iluwatar/converter/User.java | 86 --- .../com/iluwatar/converter/UserConverter.java | 40 -- .../java/com/iluwatar/converter/UserDto.java | 88 --- .../java/com/iluwatar/converter/AppTest.java | 38 - .../com/iluwatar/converter/ConverterTest.java | 84 --- cqrs/README.md | 29 - cqrs/etc/cqrs.png | Bin 105666 -> 0 bytes cqrs/etc/cqrs.ucls | 115 --- cqrs/etc/cqrs.urm.puml | 124 ---- cqrs/pom.xml | 42 -- .../main/java/com/iluwatar/cqrs/app/App.java | 95 --- .../cqrs/commandes/CommandServiceImpl.java | 145 ---- .../cqrs/commandes/ICommandService.java | 45 -- .../iluwatar/cqrs/domain/model/Author.java | 100 --- .../com/iluwatar/cqrs/domain/model/Book.java | 102 --- .../java/com/iluwatar/cqrs/dto/Author.java | 93 --- .../main/java/com/iluwatar/cqrs/dto/Book.java | 84 --- .../iluwatar/cqrs/queries/IQueryService.java | 48 -- .../cqrs/queries/QueryServiceImpl.java | 105 --- .../com/iluwatar/cqrs/util/HibernateUtil.java | 58 -- cqrs/src/main/resources/hibernate.cfg.xml | 39 -- cqrs/src/main/resources/logback.xml | 37 - .../com/iluwatar/cqrs/IntegrationTest.java | 120 ---- cqrs/src/test/resources/hibernate.cfg.xml | 39 -- cqrs/src/test/resources/logback.xml | 37 - dao/README.md | 27 - dao/etc/dao.png | Bin 39783 -> 0 bytes dao/etc/dao.ucls | 75 -- dao/etc/dao.urm.puml | 66 -- dao/pom.xml | 105 --- dao/src/main/java/com/iluwatar/dao/App.java | 135 ---- .../com/iluwatar/dao/CustomException.java | 43 -- .../main/java/com/iluwatar/dao/Customer.java | 93 --- .../java/com/iluwatar/dao/CustomerDao.java | 81 --- .../com/iluwatar/dao/CustomerSchemaSql.java | 37 - .../java/com/iluwatar/dao/DbCustomerDao.java | 196 ------ .../com/iluwatar/dao/InMemoryCustomerDao.java | 73 -- dao/src/main/resources/log4j.xml | 41 -- .../test/java/com/iluwatar/dao/AppTest.java | 37 - .../java/com/iluwatar/dao/CustomerTest.java | 100 --- .../com/iluwatar/dao/DbCustomerDaoTest.java | 269 ------- .../iluwatar/dao/InMemoryCustomerDaoTest.java | 164 ----- data-bus/.gitignore | 1 - data-bus/README.md | 33 - data-bus/etc/data-bus.urm.png | Bin 61121 -> 0 bytes data-bus/etc/data-bus.urm.puml | 77 -- data-bus/pom.xml | 51 -- .../iluwatar/databus/AbstractDataType.java | 67 -- .../main/java/com/iluwatar/databus/App.java | 79 --- .../java/com/iluwatar/databus/DataBus.java | 73 -- .../java/com/iluwatar/databus/DataType.java | 70 -- .../java/com/iluwatar/databus/Member.java | 59 -- .../iluwatar/databus/data/MessageData.java | 49 -- .../iluwatar/databus/data/StartingData.java | 51 -- .../iluwatar/databus/data/StoppingData.java | 51 -- .../members/MessageCollectorMember.java | 67 -- .../databus/members/StatusMember.java | 82 --- .../com/iluwatar/databus/DataBusTest.java | 74 -- .../members/MessageCollectorMemberTest.java | 62 -- .../databus/members/StatusMemberTest.java | 79 --- data-mapper/README.md | 26 - data-mapper/etc/data-mapper.png | Bin 40158 -> 0 bytes data-mapper/etc/data-mapper.ucls | 72 -- data-mapper/etc/data-mapper.urm.puml | 42 -- data-mapper/pom.xml | 45 -- .../java/com/iluwatar/datamapper/App.java | 77 -- .../datamapper/DataMapperException.java | 42 -- .../java/com/iluwatar/datamapper/Student.java | 142 ---- .../datamapper/StudentDataMapper.java | 35 - .../datamapper/StudentDataMapperImpl.java | 105 --- data-mapper/src/main/resources/log4j.xml | 41 -- .../java/com/iluwatar/datamapper/AppTest.java | 34 - .../iluwatar/datamapper/DataMapperTest.java | 73 -- .../com/iluwatar/datamapper/StudentTest.java | 55 -- data-transfer-object/README.md | 31 - .../etc/data-transfer-object.ucls | 48 -- .../etc/data-transfer-object.urm.png | Bin 19132 -> 0 bytes .../etc/data-transfer-object.urm.puml | 26 - data-transfer-object/pom.xml | 45 -- .../datatransfer/CustomerClientApp.java | 84 --- .../iluwatar/datatransfer/CustomerDto.java | 60 -- .../datatransfer/CustomerResource.java | 63 -- .../datatransfer/CustomerResourceTest.java | 81 --- delegation/README.md | 31 - delegation/etc/delegation.png | Bin 25260 -> 0 bytes delegation/etc/delegation.ucls | 83 --- delegation/etc/delegation.urm.puml | 39 -- delegation/pom.xml | 51 -- .../com/iluwatar/delegation/simple/App.java | 60 -- .../iluwatar/delegation/simple/Printer.java | 45 -- .../delegation/simple/PrinterController.java | 51 -- .../simple/printers/CanonPrinter.java | 47 -- .../simple/printers/EpsonPrinter.java | 47 -- .../delegation/simple/printers/HpPrinter.java | 47 -- .../iluwatar/delegation/simple/AppTest.java | 37 - .../delegation/simple/DelegateTest.java | 109 --- dependency-injection/README.md | 27 - .../etc/dependency-injection.png | Bin 22493 -> 0 bytes .../etc/dependency-injection.ucls | 141 ---- .../etc/dependency-injection.urm.puml | 49 -- dependency-injection/pom.xml | 51 -- .../injection/AdvancedSorceress.java | 65 -- .../dependency/injection/AdvancedWizard.java | 43 -- .../iluwatar/dependency/injection/App.java | 70 -- .../dependency/injection/GuiceWizard.java | 46 -- .../dependency/injection/OldTobyTobacco.java | 31 - .../injection/RivendellTobacco.java | 31 - .../injection/SecondBreakfastTobacco.java | 31 - .../dependency/injection/SimpleWizard.java | 38 - .../dependency/injection/Tobacco.java | 41 -- .../dependency/injection/TobaccoModule.java | 38 - .../iluwatar/dependency/injection/Wizard.java | 34 - .../injection/AdvancedSorceressTest.java | 76 -- .../injection/AdvancedWizardTest.java | 76 -- .../dependency/injection/AppTest.java | 39 -- .../dependency/injection/GuiceWizardTest.java | 110 --- .../injection/SimpleWizardTest.java | 63 -- .../injection/utils/InMemoryAppender.java | 58 -- double-checked-locking/README.md | 26 - .../etc/double-checked-locking.png | Bin 7011 -> 0 bytes .../etc/double-checked-locking.ucls | 42 -- .../etc/double-checked-locking.urm.puml | 22 - .../etc/double_checked_locking_1.png | Bin 11954 -> 0 bytes double-checked-locking/pom.xml | 45 -- .../iluwatar/doublechecked/locking/App.java | 69 -- .../doublechecked/locking/Inventory.java | 84 --- .../iluwatar/doublechecked/locking/Item.java | 31 - .../src/main/resources/logback.xml | 52 -- .../doublechecked/locking/AppTest.java | 39 -- .../doublechecked/locking/InventoryTest.java | 127 ---- double-dispatch/README.md | 27 - double-dispatch/etc/double-dispatch.png | Bin 32364 -> 0 bytes double-dispatch/etc/double-dispatch.ucls | 84 --- double-dispatch/etc/double-dispatch.urm.puml | 68 -- double-dispatch/pom.xml | 47 -- .../java/com/iluwatar/doubledispatch/App.java | 81 --- .../doubledispatch/FlamingAsteroid.java | 41 -- .../iluwatar/doubledispatch/GameObject.java | 70 -- .../iluwatar/doubledispatch/Meteoroid.java | 65 -- .../iluwatar/doubledispatch/Rectangle.java | 72 -- .../doubledispatch/SpaceStationIss.java | 40 -- .../doubledispatch/SpaceStationMir.java | 74 -- .../com/iluwatar/doubledispatch/AppTest.java | 39 -- .../doubledispatch/CollisionTest.java | 111 --- .../doubledispatch/FlamingAsteroidTest.java | 110 --- .../doubledispatch/MeteoroidTest.java | 109 --- .../doubledispatch/RectangleTest.java | 69 -- .../doubledispatch/SpaceStationIssTest.java | 109 --- .../doubledispatch/SpaceStationMirTest.java | 109 --- eip-splitter/README.md | 32 - eip-splitter/etc/sequencer.gif | Bin 2298 -> 0 bytes eip-splitter/pom.xml | 63 -- .../java/com/iluwatar/eip/splitter/App.java | 53 -- .../eip/splitter/routes/SplitterRoute.java | 29 - .../src/main/resources/application.properties | 2 - .../com/iluwatar/eip/splitter/AppTest.java | 15 - .../splitter/routes/SplitterRouteTest.java | 53 -- .../resources/application-test.properties | 2 - eip-wire-tap/README.md | 29 - eip-wire-tap/etc/wiretap.gif | Bin 3067 -> 0 bytes eip-wire-tap/pom.xml | 63 -- .../java/com/iluwatar/eip/wiretap/App.java | 51 -- .../eip/wiretap/routes/WireTapRoute.java | 32 - .../src/main/resources/application.properties | 3 - .../com/iluwatar/eip/wiretap/AppTest.java | 15 - .../eip/wiretap/routes/WireTapRouteTest.java | 62 -- .../resources/application-test.properties | 3 - event-aggregator/README.md | 35 - event-aggregator/etc/classes.png | Bin 45639 -> 0 bytes event-aggregator/etc/classes.ucls | 124 ---- .../etc/event-aggregator.urm.puml | 74 -- event-aggregator/pom.xml | 46 -- .../com/iluwatar/event/aggregator/App.java | 66 -- .../com/iluwatar/event/aggregator/Event.java | 44 -- .../event/aggregator/EventEmitter.java | 57 -- .../event/aggregator/EventObserver.java | 34 - .../event/aggregator/KingJoffrey.java | 41 -- .../iluwatar/event/aggregator/KingsHand.java | 49 -- .../event/aggregator/LordBaelish.java | 46 -- .../iluwatar/event/aggregator/LordVarys.java | 46 -- .../com/iluwatar/event/aggregator/Scout.java | 46 -- .../iluwatar/event/aggregator/Weekday.java | 44 -- .../iluwatar/event/aggregator/AppTest.java | 39 -- .../event/aggregator/EventEmitterTest.java | 155 ---- .../iluwatar/event/aggregator/EventTest.java | 49 -- .../event/aggregator/KingJoffreyTest.java | 98 --- .../event/aggregator/KingsHandTest.java | 70 -- .../event/aggregator/LordBaelishTest.java | 39 -- .../event/aggregator/LordVarysTest.java | 39 -- .../iluwatar/event/aggregator/ScoutTest.java | 39 -- .../event/aggregator/WeekdayTest.java | 46 -- event-asynchronous/README.md | 31 - event-asynchronous/etc/event-asynchronous.png | Bin 31413 -> 0 bytes .../etc/event-asynchronous.ucls | 118 ---- .../etc/event-asynchronous.urm.puml | 66 -- event-asynchronous/pom.xml | 42 -- .../com/iluwatar/event/asynchronous/App.java | 211 ------ .../iluwatar/event/asynchronous/Event.java | 106 --- .../EventDoesNotExistException.java | 29 - .../event/asynchronous/EventManager.java | 218 ------ .../iluwatar/event/asynchronous/IEvent.java | 31 - .../InvalidOperationException.java | 30 - .../LongRunningEventException.java | 29 - .../MaxNumOfEventsAllowedException.java | 29 - .../asynchronous/ThreadCompleteListener.java | 24 - .../src/main/resources/config.properties | 24 - .../iluwatar/event/asynchronous/AppTest.java | 32 - .../asynchronous/EventAsynchronousTest.java | 139 ---- event-driven-architecture/README.md | 38 - event-driven-architecture/etc/eda.png | Bin 58476 -> 0 bytes event-driven-architecture/etc/eda.ucls | 184 ----- .../etc/event-driven-architecture.urm.puml | 64 -- event-driven-architecture/pom.xml | 52 -- .../src/main/java/com/iluwatar/eda/App.java | 64 -- .../com/iluwatar/eda/event/AbstractEvent.java | 49 -- .../iluwatar/eda/event/UserCreatedEvent.java | 43 -- .../iluwatar/eda/event/UserUpdatedEvent.java | 43 -- .../com/iluwatar/eda/framework/Event.java | 37 - .../eda/framework/EventDispatcher.java | 64 -- .../com/iluwatar/eda/framework/Handler.java | 39 -- .../eda/handler/UserCreatedEventHandler.java | 42 -- .../eda/handler/UserUpdatedEventHandler.java | 41 -- .../java/com/iluwatar/eda/model/User.java | 43 -- .../test/java/com/iluwatar/eda/AppTest.java | 38 - .../eda/event/UserCreatedEventTest.java | 46 -- .../eda/framework/EventDispatcherTest.java | 70 -- event-queue/README.md | 29 - event-queue/etc/Bass-Drum-1.aif | Bin 220938 -> 0 bytes event-queue/etc/Bass-Drum-1.wav | Bin 221080 -> 0 bytes event-queue/etc/Closed-Hi-Hat-1.aif | Bin 13042 -> 0 bytes event-queue/etc/Closed-Hi-Hat-1.wav | Bin 13032 -> 0 bytes event-queue/etc/event-queue.urm.puml | 26 - event-queue/etc/model.png | Bin 17218 -> 0 bytes event-queue/etc/model.ucls | 36 - event-queue/pom.xml | 43 -- .../java/com/iluwatar/event/queue/App.java | 59 -- .../java/com/iluwatar/event/queue/Audio.java | 169 ----- .../com/iluwatar/event/queue/PlayMessage.java | 59 -- .../com/iluwatar/event/queue/AudioTest.java | 77 -- event-sourcing/README.md | 33 - event-sourcing/etc/event-sourcing.png | Bin 60339 -> 0 bytes event-sourcing/etc/event-sourcing.ucls | 123 ---- event-sourcing/etc/event-sourcing.urm.puml | 184 ----- event-sourcing/pom.xml | 50 -- .../com/iluwatar/event/sourcing/app/App.java | 115 --- .../event/sourcing/domain/Account.java | 186 ----- .../sourcing/event/AccountCreateEvent.java | 82 --- .../event/sourcing/event/DomainEvent.java | 101 --- .../sourcing/event/MoneyDepositEvent.java | 82 --- .../sourcing/event/MoneyTransferEvent.java | 101 --- .../processor/DomainEventProcessor.java | 69 -- .../sourcing/processor/JsonFileJournal.java | 144 ---- .../sourcing/state/AccountAggregate.java | 71 -- .../src/test/java/IntegrationTest.java | 99 --- exclude-pmd.properties | 26 - execute-around/README.md | 28 - execute-around/etc/execute-around.png | Bin 4588 -> 0 bytes execute-around/etc/execute-around.ucls | 28 - execute-around/etc/execute-around.urm.puml | 14 - execute-around/pom.xml | 42 -- .../java/com/iluwatar/execute/around/App.java | 55 -- .../execute/around/FileWriterAction.java | 37 - .../execute/around/SimpleFileWriter.java | 47 -- .../com/iluwatar/execute/around/AppTest.java | 51 -- .../execute/around/SimpleFileWriterTest.java | 96 --- extension-objects/README.md | 28 - .../etc/extension-objects.urm.puml | 2 - extension-objects/etc/extension_obj.png | Bin 38018 -> 0 bytes extension-objects/etc/extension_obj.ucls | 180 ----- extension-objects/pom.xml | 45 -- extension-objects/src/main/java/App.java | 84 --- .../CommanderExtension.java | 31 - .../abstractextensions/SergeantExtension.java | 31 - .../abstractextensions/SoldierExtension.java | 30 - .../abstractextensions/UnitExtension.java | 29 - .../java/concreteextensions/Commander.java | 47 -- .../java/concreteextensions/Sergeant.java | 47 -- .../main/java/concreteextensions/Soldier.java | 47 -- .../src/main/java/units/CommanderUnit.java | 49 -- .../src/main/java/units/SergeantUnit.java | 49 -- .../src/main/java/units/SoldierUnit.java | 49 -- .../src/main/java/units/Unit.java | 50 -- extension-objects/src/test/java/AppTest.java | 36 - .../concreteextensions/CommanderTest.java | 39 -- .../java/concreteextensions/SergeantTest.java | 39 -- .../java/concreteextensions/SoldierTest.java | 39 -- .../test/java/units/CommanderUnitTest.java | 45 -- .../src/test/java/units/SergeantUnitTest.java | 45 -- .../src/test/java/units/SoldierUnitTest.java | 47 -- .../src/test/java/units/UnitTest.java | 52 -- factory-kit/README.md | 29 - factory-kit/etc/factory-kit.png | Bin 37570 -> 0 bytes factory-kit/etc/factory-kit.ucls | 10 - factory-kit/etc/factory-kit.urm.puml | 46 -- factory-kit/pom.xml | 48 -- .../java/com/iluwatar/factorykit/App.java | 60 -- .../java/com/iluwatar/factorykit/Axe.java | 33 - .../java/com/iluwatar/factorykit/Bow.java | 33 - .../java/com/iluwatar/factorykit/Builder.java | 32 - .../java/com/iluwatar/factorykit/Spear.java | 32 - .../java/com/iluwatar/factorykit/Sword.java | 32 - .../java/com/iluwatar/factorykit/Weapon.java | 29 - .../iluwatar/factorykit/WeaponFactory.java | 56 -- .../com/iluwatar/factorykit/WeaponType.java | 30 - .../com/iluwatar/factorykit/app/AppTest.java | 39 -- .../factorykit/factorykit/FactoryKitTest.java | 88 --- factory-method/.gitignore | 1 - factory-method/README.md | 85 --- factory-method/pom.xml | 47 -- .../java/com/iluwatar/factory/method/App.java | 82 --- .../iluwatar/factory/method/Blacksmith.java | 34 - .../factory/method/ElfBlacksmith.java | 36 - .../iluwatar/factory/method/ElfWeapon.java | 45 -- .../factory/method/OrcBlacksmith.java | 35 - .../iluwatar/factory/method/OrcWeapon.java | 45 -- .../com/iluwatar/factory/method/Weapon.java | 32 - .../iluwatar/factory/method/WeaponType.java | 44 -- .../com/iluwatar/factory/method/AppTest.java | 38 - .../factory/method/FactoryMethodTest.java | 101 --- faq.md | 75 -- feature-toggle/README.md | 33 - feature-toggle/etc/feature-toggle.png | Bin 55425 -> 0 bytes feature-toggle/etc/feature-toggle.ucls | 111 --- feature-toggle/etc/feature-toggle.urm.puml | 48 -- feature-toggle/pom.xml | 48 -- .../java/com/iluwatar/featuretoggle/App.java | 103 --- .../featuretoggle/pattern/Service.java | 54 -- .../PropertiesFeatureToggleVersion.java | 100 --- .../TieredFeatureToggleVersion.java | 75 -- .../com/iluwatar/featuretoggle/user/User.java | 49 -- .../featuretoggle/user/UserGroup.java | 84 --- .../PropertiesFeatureToggleVersionTest.java | 71 -- .../TieredFeatureToggleVersionTest.java | 67 -- .../featuretoggle/user/UserGroupTest.java | 62 -- fluentinterface/README.md | 45 -- fluentinterface/etc/fluentinterface.png | Bin 83424 -> 0 bytes fluentinterface/etc/fluentinterface.ucls | 100 --- fluentinterface/etc/fluentinterface.urm.puml | 72 -- fluentinterface/pom.xml | 49 -- .../com/iluwatar/fluentinterface/app/App.java | 131 ---- .../fluentiterable/FluentIterable.java | 111 --- .../lazy/DecoratingIterator.java | 79 --- .../lazy/LazyFluentIterable.java | 249 ------- .../simple/SimpleFluentIterable.java | 224 ------ .../iluwatar/fluentinterface/app/AppTest.java | 36 - .../fluentiterable/FluentIterableTest.java | 192 ----- .../lazy/LazyFluentIterableTest.java | 40 -- .../simple/SimpleFluentIterableTest.java | 40 -- flux/README.md | 28 - flux/etc/flux.png | Bin 62348 -> 0 bytes flux/etc/flux.ucls | 232 ------ flux/etc/flux.urm.puml | 117 ---- flux/pom.xml | 47 -- .../java/com/iluwatar/flux/action/Action.java | 41 -- .../com/iluwatar/flux/action/ActionType.java | 34 - .../com/iluwatar/flux/action/Content.java | 45 -- .../iluwatar/flux/action/ContentAction.java | 42 -- .../com/iluwatar/flux/action/MenuAction.java | 43 -- .../com/iluwatar/flux/action/MenuItem.java | 44 -- .../main/java/com/iluwatar/flux/app/App.java | 75 -- .../iluwatar/flux/dispatcher/Dispatcher.java | 76 -- .../com/iluwatar/flux/store/ContentStore.java | 51 -- .../com/iluwatar/flux/store/MenuStore.java | 51 -- .../java/com/iluwatar/flux/store/Store.java | 49 -- .../com/iluwatar/flux/view/ContentView.java | 53 -- .../java/com/iluwatar/flux/view/MenuView.java | 64 -- .../java/com/iluwatar/flux/view/View.java | 37 - .../com/iluwatar/flux/action/ContentTest.java | 46 -- .../iluwatar/flux/action/MenuItemTest.java | 46 -- .../java/com/iluwatar/flux/app/AppTest.java | 39 -- .../flux/dispatcher/DispatcherTest.java | 113 --- .../iluwatar/flux/store/ContentStoreTest.java | 68 -- .../iluwatar/flux/store/MenuStoreTest.java | 68 -- .../iluwatar/flux/view/ContentViewTest.java | 54 -- .../com/iluwatar/flux/view/MenuViewTest.java | 71 -- flyweight/README.md | 131 ---- flyweight/pom.xml | 42 -- .../com/iluwatar/flyweight/AlchemistShop.java | 108 --- .../main/java/com/iluwatar/flyweight/App.java | 50 -- .../com/iluwatar/flyweight/HealingPotion.java | 41 -- .../iluwatar/flyweight/HolyWaterPotion.java | 41 -- .../flyweight/InvisibilityPotion.java | 41 -- .../com/iluwatar/flyweight/PoisonPotion.java | 41 -- .../java/com/iluwatar/flyweight/Potion.java | 33 - .../com/iluwatar/flyweight/PotionFactory.java | 73 -- .../com/iluwatar/flyweight/PotionType.java | 33 - .../iluwatar/flyweight/StrengthPotion.java | 41 -- .../iluwatar/flyweight/AlchemistShopTest.java | 62 -- .../java/com/iluwatar/flyweight/AppTest.java | 39 -- front-controller/README.md | 35 - front-controller/etc/front-controller.png | Bin 27672 -> 0 bytes front-controller/etc/front-controller.ucls | 143 ---- .../etc/front-controller.urm.puml | 53 -- front-controller/pom.xml | 48 -- .../com/iluwatar/front/controller/App.java | 57 -- .../controller/ApplicationException.java | 37 - .../front/controller/ArcherCommand.java | 36 - .../iluwatar/front/controller/ArcherView.java | 41 -- .../front/controller/CatapultCommand.java | 36 - .../front/controller/CatapultView.java | 41 -- .../iluwatar/front/controller/Command.java | 33 - .../iluwatar/front/controller/ErrorView.java | 41 -- .../front/controller/FrontController.java | 56 -- .../front/controller/UnknownCommand.java | 36 - .../com/iluwatar/front/controller/View.java | 33 - .../iluwatar/front/controller/AppTest.java | 39 -- .../controller/ApplicationExceptionTest.java | 42 -- .../front/controller/CommandTest.java | 97 --- .../front/controller/FrontControllerTest.java | 96 --- .../iluwatar/front/controller/ViewTest.java | 96 --- .../controller/utils/InMemoryAppender.java | 57 -- guarded-suspension/README.md | 22 - guarded-suspension/etc/guarded-suspension.png | Bin 10318 -> 0 bytes .../etc/guarded-suspension.ucls | 22 - .../etc/guarded-suspension.urm.puml | 15 - guarded-suspension/pom.xml | 44 -- .../com/iluwatar/guarded/suspension/App.java | 76 -- .../guarded/suspension/GuardedQueue.java | 70 -- .../guarded/suspension/GuardedQueueTest.java | 61 -- half-sync-half-async/README.md | 38 - .../etc/half-sync-half-async.png | Bin 32866 -> 0 bytes .../etc/half-sync-half-async.ucls | 77 -- .../etc/half-sync-half-async.urm.puml | 31 - half-sync-half-async/pom.xml | 47 -- .../com/iluwatar/halfsynchalfasync/App.java | 153 ---- .../iluwatar/halfsynchalfasync/AsyncTask.java | 66 -- .../AsynchronousService.java | 98 --- .../iluwatar/halfsynchalfasync/AppTest.java | 40 -- .../AsynchronousServiceTest.java | 94 --- hexagonal/README.md | 42 -- hexagonal/etc/hexagonal.png | Bin 148602 -> 0 bytes hexagonal/etc/hexagonal.ucls | 280 -------- hexagonal/etc/hexagonal.urm.puml | 279 -------- hexagonal/etc/layers.png | Bin 15887 -> 0 bytes hexagonal/etc/ports_and_adapters.png | Bin 34860 -> 0 bytes hexagonal/etc/ports_and_adapters.xml | 25 - hexagonal/etc/presentation.html | 127 ---- hexagonal/pom.xml | 51 -- .../main/java/com/iluwatar/hexagonal/App.java | 83 --- .../administration/ConsoleAdministration.java | 90 --- .../hexagonal/banking/InMemoryBank.java | 63 -- .../iluwatar/hexagonal/banking/MongoBank.java | 134 ---- .../hexagonal/banking/WireTransfers.java | 47 -- .../database/InMemoryTicketRepository.java | 67 -- .../database/LotteryTicketRepository.java | 58 -- .../database/MongoTicketRepository.java | 195 ------ .../domain/LotteryAdministration.java | 90 --- .../hexagonal/domain/LotteryConstants.java | 41 -- .../hexagonal/domain/LotteryNumbers.java | 175 ----- .../hexagonal/domain/LotteryService.java | 77 -- .../hexagonal/domain/LotteryTicket.java | 115 --- .../domain/LotteryTicketCheckResult.java | 93 --- .../hexagonal/domain/LotteryTicketId.java | 70 -- .../hexagonal/domain/LotteryUtils.java | 53 -- .../hexagonal/domain/PlayerDetails.java | 118 ---- .../hexagonal/eventlog/LotteryEventLog.java | 59 -- .../hexagonal/eventlog/MongoEventLog.java | 154 ---- .../hexagonal/eventlog/StdOutEventLog.java | 64 -- .../hexagonal/module/LotteryModule.java | 43 -- .../module/LotteryTestingModule.java | 43 -- .../MongoConnectionPropertiesLoader.java | 58 -- .../hexagonal/sampledata/SampleData.java | 109 --- .../hexagonal/service/ConsoleLottery.java | 164 ----- .../java/com/iluwatar/hexagonal/AppTest.java | 37 - .../hexagonal/banking/InMemoryBankTest.java | 50 -- .../hexagonal/banking/MongoBankTest.java | 69 -- .../InMemoryTicketRepositoryTest.java | 62 -- .../database/MongoTicketRepositoryTest.java | 97 --- .../hexagonal/domain/LotteryNumbersTest.java | 76 -- .../hexagonal/domain/LotteryTest.java | 114 --- .../domain/LotteryTicketCheckResultTest.java | 47 -- .../hexagonal/domain/LotteryTicketIdTest.java | 45 -- .../hexagonal/domain/LotteryTicketTest.java | 52 -- .../hexagonal/domain/PlayerDetailsTest.java | 45 -- .../hexagonal/eventlog/MongoEventLogTest.java | 84 --- .../hexagonal/test/LotteryTestUtils.java | 57 -- intercepting-filter/README.md | 34 - .../etc/intercepting-filter.png | Bin 75351 -> 0 bytes .../etc/intercepting-filter.ucls | 228 ------ .../etc/intercepting-filter.urm.puml | 89 --- intercepting-filter/pom.xml | 47 -- .../intercepting/filter/AbstractFilter.java | 66 -- .../intercepting/filter/AddressFilter.java | 43 -- .../com/iluwatar/intercepting/filter/App.java | 69 -- .../iluwatar/intercepting/filter/Client.java | 126 ---- .../intercepting/filter/ContactFilter.java | 46 -- .../intercepting/filter/DepositFilter.java | 42 -- .../iluwatar/intercepting/filter/Filter.java | 53 -- .../intercepting/filter/FilterChain.java | 57 -- .../intercepting/filter/FilterManager.java | 46 -- .../intercepting/filter/NameFilter.java | 44 -- .../iluwatar/intercepting/filter/Order.java | 89 --- .../intercepting/filter/OrderFilter.java | 42 -- .../iluwatar/intercepting/filter/Target.java | 104 --- .../iluwatar/intercepting/filter/AppTest.java | 39 -- .../filter/FilterManagerTest.java | 68 -- .../intercepting/filter/FilterTest.java | 120 ---- .../intercepting/filter/OrderTest.java | 73 -- interpreter/README.md | 38 - interpreter/etc/interpreter.png | Bin 27047 -> 0 bytes interpreter/etc/interpreter.ucls | 121 ---- interpreter/etc/interpreter.urm.puml | 52 -- interpreter/etc/interpreter_1.png | Bin 46272 -> 0 bytes interpreter/pom.xml | 42 -- .../java/com/iluwatar/interpreter/App.java | 100 --- .../com/iluwatar/interpreter/Expression.java | 36 - .../iluwatar/interpreter/MinusExpression.java | 50 -- .../interpreter/MultiplyExpression.java | 50 -- .../interpreter/NumberExpression.java | 51 -- .../iluwatar/interpreter/PlusExpression.java | 49 -- .../com/iluwatar/interpreter/AppTest.java | 39 -- .../iluwatar/interpreter/ExpressionTest.java | 136 ---- .../interpreter/MinusExpressionTest.java | 60 -- .../interpreter/MultiplyExpressionTest.java | 60 -- .../interpreter/NumberExpressionTest.java | 74 -- .../interpreter/PlusExpressionTest.java | 60 -- layers/README.md | 30 - layers/etc/layers.png | Bin 97428 -> 0 bytes layers/etc/layers.ucls | 256 ------- layers/etc/layers.urm.puml | 126 ---- layers/pom.xml | 65 -- .../main/java/com/iluwatar/layers/App.java | 118 ---- .../main/java/com/iluwatar/layers/Cake.java | 90 --- .../iluwatar/layers/CakeBakingException.java | 39 -- .../iluwatar/layers/CakeBakingService.java | 63 -- .../layers/CakeBakingServiceImpl.java | 175 ----- .../java/com/iluwatar/layers/CakeDao.java | 36 - .../java/com/iluwatar/layers/CakeInfo.java | 71 -- .../java/com/iluwatar/layers/CakeLayer.java | 93 --- .../com/iluwatar/layers/CakeLayerDao.java | 36 - .../com/iluwatar/layers/CakeLayerInfo.java | 60 -- .../java/com/iluwatar/layers/CakeTopping.java | 93 --- .../com/iluwatar/layers/CakeToppingDao.java | 36 - .../com/iluwatar/layers/CakeToppingInfo.java | 60 -- .../com/iluwatar/layers/CakeViewImpl.java | 46 -- .../main/java/com/iluwatar/layers/View.java | 34 - .../main/resources/META-INF/persistence.xml | 32 - .../src/main/resources/applicationContext.xml | 63 -- layers/src/main/resources/logback.xml | 57 -- .../java/com/iluwatar/layers/AppTest.java | 39 -- .../layers/CakeBakingExceptionTest.java | 52 -- .../layers/CakeBakingServiceImplTest.java | 181 ----- .../java/com/iluwatar/layers/CakeTest.java | 119 ---- .../com/iluwatar/layers/CakeViewImplTest.java | 109 --- lazy-loading/README.md | 34 - lazy-loading/etc/lazy-loading.png | Bin 11671 -> 0 bytes lazy-loading/etc/lazy-loading.ucls | 66 -- lazy-loading/etc/lazy-loading.urm.puml | 40 -- lazy-loading/pom.xml | 42 -- .../java/com/iluwatar/lazy/loading/App.java | 64 -- .../java/com/iluwatar/lazy/loading/Heavy.java | 49 -- .../iluwatar/lazy/loading/HolderNaive.java | 55 -- .../lazy/loading/HolderThreadSafe.java | 56 -- .../iluwatar/lazy/loading/Java8Holder.java | 64 -- .../lazy/loading/AbstractHolderTest.java | 63 -- .../com/iluwatar/lazy/loading/AppTest.java | 39 -- .../lazy/loading/HolderNaiveTest.java | 48 -- .../lazy/loading/HolderThreadSafeTest.java | 48 -- .../lazy/loading/Java8HolderTest.java | 62 -- marker/.gitignore | 1 - marker/README.md | 30 - marker/etc/MarkerDiagram.png | Bin 6461 -> 0 bytes marker/etc/MarkerDiagram.ucls | 41 -- marker/etc/marker.urm.puml | 2 - marker/pom.xml | 41 -- marker/src/main/java/App.java | 70 -- marker/src/main/java/Guard.java | 37 - marker/src/main/java/Permission.java | 28 - marker/src/main/java/Thief.java | 40 -- marker/src/test/java/AppTest.java | 35 - marker/src/test/java/GuardTest.java | 38 - marker/src/test/java/ThiefTest.java | 36 - mediator/README.md | 38 - mediator/etc/mediator.png | Bin 36948 -> 0 bytes mediator/etc/mediator.ucls | 131 ---- mediator/etc/mediator.urm.puml | 69 -- mediator/etc/mediator_1.png | Bin 59727 -> 0 bytes mediator/pom.xml | 47 -- .../java/com/iluwatar/mediator/Action.java | 51 -- .../main/java/com/iluwatar/mediator/App.java | 76 -- .../java/com/iluwatar/mediator/Hobbit.java | 37 - .../java/com/iluwatar/mediator/Hunter.java | 36 - .../java/com/iluwatar/mediator/Party.java | 36 - .../java/com/iluwatar/mediator/PartyImpl.java | 55 -- .../com/iluwatar/mediator/PartyMember.java | 37 - .../iluwatar/mediator/PartyMemberBase.java | 61 -- .../java/com/iluwatar/mediator/Rogue.java | 37 - .../java/com/iluwatar/mediator/Wizard.java | 37 - .../java/com/iluwatar/mediator/AppTest.java | 39 -- .../com/iluwatar/mediator/PartyImplTest.java | 63 -- .../iluwatar/mediator/PartyMemberTest.java | 160 ----- memento/README.md | 35 - memento/etc/memento.png | Bin 22492 -> 0 bytes memento/etc/memento.ucls | 70 -- memento/etc/memento.urm.puml | 49 -- memento/pom.xml | 42 -- .../main/java/com/iluwatar/memento/App.java | 78 --- .../main/java/com/iluwatar/memento/Star.java | 132 ---- .../com/iluwatar/memento/StarMemento.java | 32 - .../java/com/iluwatar/memento/StarType.java | 45 -- .../java/com/iluwatar/memento/AppTest.java | 39 -- .../java/com/iluwatar/memento/StarTest.java | 97 --- message-channel/.gitignore | 1 - message-channel/README.md | 26 - message-channel/etc/message-channel.png | Bin 47216 -> 0 bytes message-channel/etc/message-channel.ucls | 320 --------- message-channel/etc/message-channel.urm.puml | 9 - message-channel/pom.xml | 51 -- .../com/iluwatar/message/channel/App.java | 76 -- .../com/iluwatar/message/channel/AppTest.java | 39 -- model-view-controller/README.md | 30 - .../etc/model-view-controller.png | Bin 18130 -> 0 bytes .../etc/model-view-controller.ucls | 53 -- .../etc/model-view-controller.urm.puml | 70 -- model-view-controller/pom.xml | 47 -- .../iluwatar/model/view/controller/App.java | 63 -- .../model/view/controller/Fatigue.java | 44 -- .../view/controller/GiantController.java | 67 -- .../model/view/controller/GiantModel.java | 70 -- .../model/view/controller/GiantView.java | 40 -- .../model/view/controller/Health.java | 44 -- .../model/view/controller/Nourishment.java | 44 -- .../model/view/controller/AppTest.java | 39 -- .../view/controller/GiantControllerTest.java | 122 ---- .../model/view/controller/GiantModelTest.java | 78 --- .../model/view/controller/GiantViewTest.java | 96 --- model-view-presenter/README.md | 28 - model-view-presenter/etc/data/test.txt | 25 - .../etc/model-view-presenter.png | Bin 41786 -> 0 bytes .../etc/model-view-presenter.ucls | 121 ---- .../etc/model-view-presenter.urm.puml | 87 --- .../etc/model-view-presenter_1.png | Bin 103398 -> 0 bytes model-view-presenter/pom.xml | 49 -- .../iluwatar/model/view/presenter/App.java | 54 -- .../model/view/presenter/FileLoader.java | 110 --- .../view/presenter/FileSelectorJFrame.java | 218 ------ .../view/presenter/FileSelectorPresenter.java | 106 --- .../view/presenter/FileSelectorStub.java | 131 ---- .../view/presenter/FileSelectorView.java | 85 --- .../model/view/presenter/AppTest.java | 40 -- .../model/view/presenter/FileLoaderTest.java | 43 -- .../presenter/FileSelectorPresenterTest.java | 145 ---- module/README.md | 25 - module/error.txt | 23 - module/etc/module.png | Bin 18027 -> 0 bytes module/etc/module.ucls | 69 -- module/etc/module.urm.puml | 43 -- module/output.txt | 23 - module/pom.xml | 45 -- .../main/java/com/iluwatar/module/App.java | 92 --- .../iluwatar/module/ConsoleLoggerModule.java | 106 --- .../com/iluwatar/module/FileLoggerModule.java | 114 --- module/src/main/resources/log4j.xml | 41 -- .../java/com/iluwatar/module/AppTest.java | 37 - .../iluwatar/module/FileLoggerModuleTest.java | 182 ----- monad/README.md | 36 - monad/etc/monad.png | Bin 32962 -> 0 bytes monad/etc/monad.ucls | 54 -- monad/etc/monad.urm.puml | 36 - monad/pom.xml | 43 -- .../src/main/java/com/iluwatar/monad/App.java | 62 -- .../src/main/java/com/iluwatar/monad/Sex.java | 30 - .../main/java/com/iluwatar/monad/User.java | 63 -- .../java/com/iluwatar/monad/Validator.java | 113 --- .../test/java/com/iluwatar/monad/AppTest.java | 38 - .../java/com/iluwatar/monad/MonadTest.java | 67 -- monostate/README.md | 36 - monostate/etc/MonoState.ucls | 53 -- monostate/etc/monostate.png | Bin 16526 -> 0 bytes monostate/etc/monostate.urm.puml | 33 - monostate/pom.xml | 47 -- .../main/java/com/iluwatar/monostate/App.java | 57 -- .../com/iluwatar/monostate/LoadBalancer.java | 80 --- .../java/com/iluwatar/monostate/Request.java | 37 - .../java/com/iluwatar/monostate/Server.java | 63 -- .../java/com/iluwatar/monostate/AppTest.java | 38 - .../iluwatar/monostate/LoadBalancerTest.java | 71 -- multiton/README.md | 25 - multiton/etc/multiton.png | Bin 10637 -> 0 bytes multiton/etc/multiton.ucls | 44 -- multiton/etc/multiton.urm.puml | 30 - multiton/pom.xml | 42 -- .../main/java/com/iluwatar/multiton/App.java | 59 -- .../java/com/iluwatar/multiton/Nazgul.java | 63 -- .../com/iluwatar/multiton/NazgulName.java | 34 - .../java/com/iluwatar/multiton/AppTest.java | 39 -- .../com/iluwatar/multiton/NazgulTest.java | 51 -- mute-idiom/README.md | 29 - mute-idiom/etc/mute-idiom.png | Bin 18505 -> 0 bytes mute-idiom/etc/mute-idiom.ucls | 71 -- mute-idiom/etc/mute-idiom.urm.puml | 24 - mute-idiom/pom.xml | 34 - .../src/main/java/com/iluwatar/mute/App.java | 108 --- .../com/iluwatar/mute/CheckedRunnable.java | 37 - .../src/main/java/com/iluwatar/mute/Mute.java | 68 -- .../main/java/com/iluwatar/mute/Resource.java | 35 - .../test/java/com/iluwatar/mute/AppTest.java | 38 - .../test/java/com/iluwatar/mute/MuteTest.java | 85 --- mutex/README.md | 31 - mutex/etc/mutex.png | Bin 12737 -> 0 bytes mutex/etc/mutex.urm.puml | 27 - mutex/pom.xml | 42 -- .../src/main/java/com/iluwatar/mutex/App.java | 50 -- .../src/main/java/com/iluwatar/mutex/Jar.java | 67 -- .../main/java/com/iluwatar/mutex/Lock.java | 34 - .../main/java/com/iluwatar/mutex/Mutex.java | 67 -- .../main/java/com/iluwatar/mutex/Thief.java | 67 -- .../test/java/com/iluwatar/mutex/AppTest.java | 37 - .../test/java/com/iluwatar/mutex/JarTest.java | 43 -- .../java/com/iluwatar/mutex/MutexTest.java | 47 -- naked-objects/.gitattributes | 51 -- naked-objects/.gitignore | 42 -- naked-objects/README | 1 - naked-objects/README.md | 32 - naked-objects/dom/pom.xml | 186 ----- .../src/main/java/META-INF/persistence.xml | 26 - .../dom/app/homepage/HomePageService.java | 48 -- .../dom/app/homepage/HomePageViewModel.java | 54 -- .../homepage/HomePageViewModel.layout.json | 43 -- .../dom/app/homepage/HomePageViewModel.png | Bin 456 -> 0 bytes .../dom/modules/simple/SimpleObject.java | 132 ---- .../modules/simple/SimpleObject.layout.json | 56 -- .../dom/modules/simple/SimpleObject.png | Bin 653 -> 0 bytes .../dom/modules/simple/SimpleObjects.java | 98 --- .../dom/modules/simple/SimpleObjectTest.java | 53 -- .../dom/modules/simple/SimpleObjectsTest.java | 108 --- naked-objects/etc/naked-objects-dom.urm.puml | 39 -- .../etc/naked-objects-fixture.urm.puml | 93 --- .../etc/naked-objects-integtests.urm.puml | 93 --- naked-objects/etc/naked-objects.png | Bin 75022 -> 0 bytes naked-objects/etc/naked-objects.ucls | 162 ----- naked-objects/fixture/pom.xml | 31 - .../fixture/DomainAppFixturesProvider.java | 38 - .../modules/simple/SimpleObjectCreate.java | 72 -- .../modules/simple/SimpleObjectsTearDown.java | 34 - .../scenarios/RecreateSimpleObjects.java | 95 --- naked-objects/integtests/.gitignore | 1 - naked-objects/integtests/pom.xml | 121 ---- .../bootstrap/SimpleAppSystemInitializer.java | 60 -- .../specglue/BootstrappingGlue.java | 42 -- .../specglue/CatalogOfFixturesGlue.java | 31 - .../modules/simple/SimpleObjectGlue.java | 50 -- .../domainapp/integtests/specs/RunSpecs.java | 32 - .../SimpleObjectSpec_listAllAndCreate.feature | 26 - .../integtests/tests/SimpleAppIntegTest.java | 41 -- .../modules/simple/SimpleObjectIntegTest.java | 130 ---- .../simple/SimpleObjectsIntegTest.java | 149 ---- naked-objects/pom.xml | 407 ----------- .../webapp/ide/eclipse/launch/.gitignore | 8 - .../webapp/ide/intellij/launch/README.txt | 25 - .../intellij/launch/SimpleApp_PROTOTYPE.xml | 52 -- .../launch/SimpleApp__enhance_only_.xml | 46 -- naked-objects/webapp/lib/.gitignore | 5 - naked-objects/webapp/pom.xml | 321 --------- .../domainapp/webapp/SimpleApplication.java | 158 ----- .../src/main/jettyconsole/isis-banner.pdn | Bin 69658 -> 0 bytes .../src/main/jettyconsole/isis-banner.png | Bin 30776 -> 0 bytes .../resources/domainapp/webapp/welcome.html | 35 - .../src/main/webapp/WEB-INF/isis.properties | 300 -------- .../main/webapp/WEB-INF/persistor.properties | 128 ---- .../WEB-INF/persistor_datanucleus.properties | 93 --- .../webapp/src/main/webapp/WEB-INF/shiro.ini | 93 --- .../main/webapp/WEB-INF/translations-en.po | 213 ------ .../main/webapp/WEB-INF/translations-es.po | 208 ------ .../main/webapp/WEB-INF/translations-nl.po | 208 ------ .../src/main/webapp/WEB-INF/translations.po | 213 ------ .../WEB-INF/viewer_restfulobjects.properties | 66 -- .../webapp/WEB-INF/viewer_wicket.properties | 91 --- .../webapp/src/main/webapp/WEB-INF/web.xml | 309 -------- .../main/webapp/about/images/isis-logo.png | Bin 14160 -> 0 bytes .../webapp/src/main/webapp/about/index.html | 126 ---- .../src/main/webapp/css/application.css | 19 - .../src/main/webapp/images/spinning-icon.gif | Bin 5266 -> 0 bytes .../src/main/webapp/scripts/application.js | 25 - null-object/README.md | 31 - null-object/etc/null-object.png | Bin 14069 -> 0 bytes null-object/etc/null-object.ucls | 69 -- null-object/etc/null-object.urm.puml | 41 -- null-object/pom.xml | 47 -- .../java/com/iluwatar/nullobject/App.java | 50 -- .../java/com/iluwatar/nullobject/Node.java | 41 -- .../com/iluwatar/nullobject/NodeImpl.java | 80 --- .../com/iluwatar/nullobject/NullNode.java | 66 -- .../java/com/iluwatar/nullobject/AppTest.java | 39 -- .../com/iluwatar/nullobject/NullNodeTest.java | 60 -- .../com/iluwatar/nullobject/TreeTest.java | 161 ----- object-mother/README.md | 31 - object-mother/etc/object-mother.png | Bin 19705 -> 0 bytes object-mother/etc/object-mother.ucls | 56 -- object-mother/etc/object-mother.urm.puml | 45 -- object-mother/pom.xml | 48 -- .../java/com/iluwatar/objectmother/King.java | 69 -- .../java/com/iluwatar/objectmother/Queen.java | 72 -- .../com/iluwatar/objectmother/Royalty.java | 36 - .../objectmother/RoyaltyObjectMother.java | 86 --- .../test/RoyaltyObjectMotherTest.java | 92 --- object-pool/README.md | 26 - object-pool/etc/object-pool.png | Bin 8877 -> 0 bytes object-pool/etc/object-pool.ucls | 41 -- object-pool/etc/object-pool.urm.puml | 30 - object-pool/pom.xml | 42 -- .../java/com/iluwatar/object/pool/App.java | 79 --- .../com/iluwatar/object/pool/ObjectPool.java | 61 -- .../com/iluwatar/object/pool/Oliphaunt.java | 56 -- .../iluwatar/object/pool/OliphauntPool.java | 36 - .../com/iluwatar/object/pool/AppTest.java | 39 -- .../object/pool/OliphauntPoolTest.java | 121 ---- page-object/README.md | 30 - page-object/etc/page-object.png | Bin 49696 -> 0 bytes page-object/etc/page-object.ucls | 10 - page-object/etc/page-object.urm.puml | 8 - page-object/pom.xml | 46 -- .../java/com/iluwatar/pageobject/App.java | 89 --- .../main/resources/sample-ui/album-list.html | 60 -- .../main/resources/sample-ui/album-page.html | 74 -- .../resources/sample-ui/css/album-list.css | 68 -- .../main/resources/sample-ui/css/style.css | 49 -- .../src/main/resources/sample-ui/login.html | 48 -- .../pageobject/AlbumListPageTest.java | 53 -- .../iluwatar/pageobject/AlbumPageTest.java | 67 -- .../iluwatar/pageobject/LoginPageTest.java | 55 -- .../pageobject/pages/AlbumListPage.java | 96 --- .../iluwatar/pageobject/pages/AlbumPage.java | 174 ----- .../iluwatar/pageobject/pages/LoginPage.java | 116 --- .../com/iluwatar/pageobject/pages/Page.java | 57 -- partial-response/README.md | 29 - partial-response/etc/partial-response.ucls | 65 -- partial-response/etc/partial-response.urm.png | Bin 27781 -> 0 bytes .../etc/partial-response.urm.puml | 31 - partial-response/pom.xml | 49 -- .../com/iluwatar/partialresponse/App.java | 74 -- .../partialresponse/FieldJsonMapper.java | 60 -- .../com/iluwatar/partialresponse/Video.java | 70 -- .../partialresponse/VideoResource.java | 57 -- .../com/iluwatar/partialresponse/AppTest.java | 40 -- .../partialresponse/FieldJsonMapperTest.java | 53 -- .../partialresponse/VideoResourceTest.java | 80 --- poison-pill/README.md | 27 - poison-pill/etc/poison-pill.png | Bin 15833 -> 0 bytes poison-pill/etc/poison-pill.ucls | 92 --- poison-pill/etc/poison-pill.urm.puml | 71 -- poison-pill/pom.xml | 47 -- .../java/com/iluwatar/poison/pill/App.java | 67 -- .../com/iluwatar/poison/pill/Consumer.java | 67 -- .../com/iluwatar/poison/pill/Message.java | 82 --- .../iluwatar/poison/pill/MessageQueue.java | 30 - .../iluwatar/poison/pill/MqPublishPoint.java | 31 - .../poison/pill/MqSubscribePoint.java | 31 - .../com/iluwatar/poison/pill/Producer.java | 85 --- .../iluwatar/poison/pill/SimpleMessage.java | 61 -- .../poison/pill/SimpleMessageQueue.java | 48 -- .../com/iluwatar/poison/pill/AppTest.java | 39 -- .../iluwatar/poison/pill/ConsumerTest.java | 112 --- .../poison/pill/PoisonMessageTest.java | 62 -- .../iluwatar/poison/pill/ProducerTest.java | 86 --- .../poison/pill/SimpleMessageTest.java | 62 -- pom.xml | 497 ------------- private-class-data/README.md | 24 - private-class-data/etc/private-class-data.png | Bin 10791 -> 0 bytes .../etc/private-class-data.ucls | 45 -- .../etc/private-class-data.urm.puml | 36 - private-class-data/pom.xml | 47 -- .../com/iluwatar/privateclassdata/App.java | 59 -- .../privateclassdata/ImmutableStew.java | 50 -- .../com/iluwatar/privateclassdata/Stew.java | 78 --- .../iluwatar/privateclassdata/StewData.java | 62 -- .../iluwatar/privateclassdata/AppTest.java | 39 -- .../privateclassdata/ImmutableStewTest.java | 83 --- .../iluwatar/privateclassdata/StewTest.java | 68 -- .../utils/InMemoryAppender.java | 56 -- producer-consumer/README.md | 26 - producer-consumer/etc/producer-consumer.png | Bin 27122 -> 0 bytes producer-consumer/etc/producer-consumer.ucls | 74 -- .../etc/producer-consumer.urm.puml | 39 -- producer-consumer/pom.xml | 47 -- .../com/iluwatar/producer/consumer/App.java | 83 --- .../iluwatar/producer/consumer/Consumer.java | 53 -- .../com/iluwatar/producer/consumer/Item.java | 49 -- .../iluwatar/producer/consumer/ItemQueue.java | 50 -- .../iluwatar/producer/consumer/Producer.java | 54 -- .../iluwatar/producer/consumer/AppTest.java | 40 -- .../producer/consumer/ConsumerTest.java | 55 -- .../producer/consumer/ProducerTest.java | 50 -- promise/README.md | 47 -- promise/etc/promise.png | Bin 59210 -> 0 bytes promise/etc/promise.ucls | 111 --- promise/etc/promise.urm.puml | 79 --- promise/pom.xml | 47 -- .../main/java/com/iluwatar/promise/App.java | 181 ----- .../java/com/iluwatar/promise/Promise.java | 193 ----- .../com/iluwatar/promise/PromiseSupport.java | 118 ---- .../java/com/iluwatar/promise/Utility.java | 131 ---- .../java/com/iluwatar/promise/AppTest.java | 39 -- .../com/iluwatar/promise/PromiseTest.java | 263 ------- property/README.md | 26 - property/etc/property.png | Bin 20016 -> 0 bytes property/etc/property.ucls | 70 -- property/etc/property.urm.puml | 54 -- property/pom.xml | 42 -- .../main/java/com/iluwatar/property/App.java | 86 --- .../java/com/iluwatar/property/Character.java | 138 ---- .../java/com/iluwatar/property/Prototype.java | 37 - .../java/com/iluwatar/property/Stats.java | 31 - .../java/com/iluwatar/property/AppTest.java | 39 -- .../com/iluwatar/property/CharacterTest.java | 125 ---- prototype/README.md | 76 -- prototype/pom.xml | 47 -- .../main/java/com/iluwatar/prototype/App.java | 71 -- .../java/com/iluwatar/prototype/Beast.java | 35 - .../java/com/iluwatar/prototype/ElfBeast.java | 44 -- .../java/com/iluwatar/prototype/ElfMage.java | 44 -- .../com/iluwatar/prototype/ElfWarlord.java | 44 -- .../com/iluwatar/prototype/HeroFactory.java | 38 - .../iluwatar/prototype/HeroFactoryImpl.java | 78 --- .../java/com/iluwatar/prototype/Mage.java | 35 - .../java/com/iluwatar/prototype/OrcBeast.java | 44 -- .../java/com/iluwatar/prototype/OrcMage.java | 44 -- .../com/iluwatar/prototype/OrcWarlord.java | 44 -- .../com/iluwatar/prototype/Prototype.java | 35 - .../java/com/iluwatar/prototype/Warlord.java | 35 - .../java/com/iluwatar/prototype/AppTest.java | 39 -- .../prototype/HeroFactoryImplTest.java | 61 -- .../com/iluwatar/prototype/PrototypeTest.java | 87 --- proxy/README.md | 144 ---- proxy/etc/presentation.html | 92 --- proxy/etc/proxy-concept.png | Bin 24957 -> 0 bytes proxy/etc/proxy-concept.xml | 25 - proxy/pom.xml | 47 -- .../src/main/java/com/iluwatar/proxy/App.java | 56 -- .../java/com/iluwatar/proxy/IvoryTower.java | 41 -- .../main/java/com/iluwatar/proxy/Wizard.java | 43 -- .../java/com/iluwatar/proxy/WizardTower.java | 31 - .../com/iluwatar/proxy/WizardTowerProxy.java | 56 -- .../test/java/com/iluwatar/proxy/AppTest.java | 39 -- .../com/iluwatar/proxy/IvoryTowerTest.java | 72 -- .../java/com/iluwatar/proxy/WizardTest.java | 41 -- .../iluwatar/proxy/WizardTowerProxyTest.java | 70 -- .../proxy/utils/InMemoryAppender.java | 62 -- publish-subscribe/.gitignore | 1 - publish-subscribe/README.md | 25 - publish-subscribe/etc/publish-subscribe.png | Bin 27741 -> 0 bytes publish-subscribe/etc/publish-subscribe.ucls | 218 ------ .../etc/publish-subscribe.urm.puml | 9 - publish-subscribe/pom.xml | 48 -- .../com/iluwatar/publish/subscribe/App.java | 72 -- .../src/main/resources/logback.xml | 52 -- .../iluwatar/publish/subscribe/AppTest.java | 39 -- queue-load-leveling/README.md | 37 - .../etc/queue-load-leveling.gif | Bin 15062 -> 0 bytes .../etc/queue-load-leveling.ucls | 86 --- .../etc/queue-load-leveling.urm.puml | 44 -- queue-load-leveling/pom.xml | 42 -- .../com/iluwatar/queue/load/leveling/App.java | 119 ---- .../iluwatar/queue/load/leveling/Message.java | 47 -- .../queue/load/leveling/MessageQueue.java | 77 -- .../queue/load/leveling/ServiceExecutor.java | 67 -- .../iluwatar/queue/load/leveling/Task.java | 30 - .../queue/load/leveling/TaskGenerator.java | 89 --- .../iluwatar/queue/load/leveling/AppTest.java | 38 - .../queue/load/leveling/MessageQueueTest.java | 48 -- .../queue/load/leveling/MessageTest.java | 43 -- .../load/leveling/TaskGenSrvExeTest.java | 50 -- reactor/README.md | 36 - reactor/etc/reactor.png | Bin 125804 -> 0 bytes reactor/etc/reactor.ucls | 235 ------- reactor/etc/reactor.urm.puml | 156 ----- reactor/pom.xml | 42 -- .../java/com/iluwatar/reactor/app/App.java | 163 ----- .../com/iluwatar/reactor/app/AppClient.java | 194 ----- .../iluwatar/reactor/app/LoggingHandler.java | 85 --- .../reactor/framework/AbstractNioChannel.java | 175 ----- .../reactor/framework/ChannelHandler.java | 45 -- .../reactor/framework/Dispatcher.java | 63 -- .../reactor/framework/NioDatagramChannel.java | 186 ----- .../reactor/framework/NioReactor.java | 267 ------- .../framework/NioServerSocketChannel.java | 116 --- .../framework/SameThreadDispatcher.java | 60 -- .../framework/ThreadPoolDispatcher.java | 69 -- .../com/iluwatar/reactor/app/ReactorTest.java | 99 --- reader-writer-lock/README.md | 33 - reader-writer-lock/etc/reader-writer-lock.png | Bin 39623 -> 0 bytes .../etc/reader-writer-lock.ucls | 86 --- .../etc/reader-writer-lock.urm.puml | 61 -- reader-writer-lock/pom.xml | 49 -- .../com/iluwatar/reader/writer/lock/App.java | 106 --- .../iluwatar/reader/writer/lock/Reader.java | 88 --- .../reader/writer/lock/ReaderWriterLock.java | 221 ------ .../iluwatar/reader/writer/lock/Writer.java | 88 --- .../iluwatar/reader/writer/lock/AppTest.java | 38 - .../writer/lock/ReaderAndWriterTest.java | 118 ---- .../reader/writer/lock/ReaderTest.java | 88 --- .../reader/writer/lock/WriterTest.java | 89 --- .../writer/lock/utils/InMemoryAppender.java | 57 -- repository/README.md | 38 - repository/etc/repository.png | Bin 55254 -> 0 bytes repository/etc/repository.ucls | 70 -- repository/etc/repository.urm.puml | 56 -- repository/pom.xml | 66 -- .../java/com/iluwatar/repository/App.java | 112 --- .../com/iluwatar/repository/AppConfig.java | 161 ----- .../java/com/iluwatar/repository/Person.java | 145 ---- .../iluwatar/repository/PersonRepository.java | 39 -- .../repository/PersonSpecifications.java | 82 --- .../main/resources/META-INF/persistence.xml | 32 - .../src/main/resources/applicationContext.xml | 62 -- repository/src/main/resources/logback.xml | 52 -- .../AnnotationBasedRepositoryTest.java | 132 ---- .../iluwatar/repository/AppConfigTest.java | 76 -- .../java/com/iluwatar/repository/AppTest.java | 38 - .../iluwatar/repository/RepositoryTest.java | 130 ---- .../README.md | 22 - ...resource-acquisition-is-initialization.png | Bin 3760 -> 0 bytes ...esource-acquisition-is-initialization.ucls | 30 - ...rce-acquisition-is-initialization.urm.puml | 19 - .../pom.xml | 47 -- .../acquisition/is/initialization/App.java | 65 -- .../is/initialization/SlidingDoor.java | 45 -- .../is/initialization/TreasureChest.java | 48 -- .../is/initialization/AppTest.java | 39 -- .../is/initialization/ClosableTest.java | 87 --- semaphore/README.md | 34 - semaphore/etc/semaphore.png | Bin 30089 -> 0 bytes semaphore/etc/semaphore.urm.puml | 56 -- semaphore/pom.xml | 42 -- .../main/java/com/iluwatar/semaphore/App.java | 50 -- .../java/com/iluwatar/semaphore/Customer.java | 81 --- .../java/com/iluwatar/semaphore/Fruit.java | 63 -- .../com/iluwatar/semaphore/FruitBowl.java | 89 --- .../com/iluwatar/semaphore/FruitShop.java | 120 ---- .../java/com/iluwatar/semaphore/Lock.java | 34 - .../com/iluwatar/semaphore/Semaphore.java | 77 -- .../java/com/iluwatar/semaphore/AppTest.java | 37 - .../com/iluwatar/semaphore/FruitBowlTest.java | 51 -- .../com/iluwatar/semaphore/SemaphoreTest.java | 56 -- servant/README.md | 26 - servant/etc/servant-pattern.png | Bin 30103 -> 0 bytes servant/etc/servant-pattern.ucls | 79 --- servant/etc/servant.urm.puml | 56 -- servant/pom.xml | 47 -- servant/src/etc/servant.jpg | Bin 134957 -> 0 bytes servant/src/etc/servant.svg | 259 ------- servant/src/etc/servant.xml | 662 ------------------ .../main/java/com/iluwatar/servant/App.java | 87 --- .../main/java/com/iluwatar/servant/King.java | 65 -- .../main/java/com/iluwatar/servant/Queen.java | 68 -- .../java/com/iluwatar/servant/Royalty.java | 41 -- .../java/com/iluwatar/servant/Servant.java | 68 -- .../java/com/iluwatar/servant/AppTest.java | 39 -- .../java/com/iluwatar/servant/KingTest.java | 104 --- .../java/com/iluwatar/servant/QueenTest.java | 68 -- .../com/iluwatar/servant/ServantTest.java | 93 --- service-layer/README.md | 32 - service-layer/bin/pom.xml | 50 -- service-layer/etc/service-layer.png | Bin 89966 -> 0 bytes service-layer/etc/service-layer.ucls | 250 ------- service-layer/etc/service-layer.urm.puml | 161 ----- service-layer/pom.xml | 55 -- .../com/iluwatar/servicelayer/app/App.java | 210 ------ .../servicelayer/common/BaseEntity.java | 70 -- .../com/iluwatar/servicelayer/common/Dao.java | 45 -- .../servicelayer/common/DaoBaseImpl.java | 154 ---- .../servicelayer/hibernate/HibernateUtil.java | 82 --- .../servicelayer/magic/MagicService.java | 48 -- .../servicelayer/magic/MagicServiceImpl.java | 82 --- .../iluwatar/servicelayer/spell/Spell.java | 91 --- .../iluwatar/servicelayer/spell/SpellDao.java | 36 - .../servicelayer/spell/SpellDaoImpl.java | 60 -- .../servicelayer/spellbook/Spellbook.java | 115 --- .../servicelayer/spellbook/SpellbookDao.java | 36 - .../spellbook/SpellbookDaoImpl.java | 63 -- .../iluwatar/servicelayer/wizard/Wizard.java | 100 --- .../servicelayer/wizard/WizardDao.java | 36 - .../servicelayer/wizard/WizardDaoImpl.java | 64 -- service-layer/src/main/resources/logback.xml | 57 -- .../iluwatar/servicelayer/app/AppTest.java | 48 -- .../servicelayer/common/BaseDaoTest.java | 145 ---- .../magic/MagicServiceImplTest.java | 160 ----- .../servicelayer/spell/SpellDaoImplTest.java | 57 -- .../spellbook/SpellbookDaoImplTest.java | 57 -- .../wizard/WizardDaoImplTest.java | 57 -- service-locator/README.md | 44 -- service-locator/etc/service-locator.png | Bin 16511 -> 0 bytes service-locator/etc/service-locator.ucls | 79 --- service-locator/etc/service-locator.urm.puml | 41 -- service-locator/pom.xml | 42 -- .../java/com/iluwatar/servicelocator/App.java | 56 -- .../iluwatar/servicelocator/InitContext.java | 56 -- .../com/iluwatar/servicelocator/Service.java | 48 -- .../iluwatar/servicelocator/ServiceCache.java | 75 -- .../iluwatar/servicelocator/ServiceImpl.java | 67 -- .../servicelocator/ServiceLocator.java | 63 -- .../com/iluwatar/servicelocator/AppTest.java | 39 -- .../servicelocator/ServiceLocatorTest.java | 68 -- specification/README.md | 36 - specification/etc/specification.png | Bin 49425 -> 0 bytes specification/etc/specification.ucls | 212 ------ specification/etc/specification.urm.puml | 107 --- specification/pom.xml | 47 -- .../com/iluwatar/specification/app/App.java | 87 --- .../creature/AbstractCreature.java | 75 -- .../specification/creature/Creature.java | 43 -- .../specification/creature/Dragon.java | 39 -- .../specification/creature/Goblin.java | 39 -- .../specification/creature/KillerBee.java | 39 -- .../specification/creature/Octopus.java | 39 -- .../specification/creature/Shark.java | 39 -- .../specification/creature/Troll.java | 39 -- .../specification/property/Color.java | 44 -- .../specification/property/Movement.java | 44 -- .../iluwatar/specification/property/Size.java | 44 -- .../specification/selector/ColorSelector.java | 47 -- .../selector/MovementSelector.java | 47 -- .../specification/selector/SizeSelector.java | 47 -- .../iluwatar/specification/app/AppTest.java | 39 -- .../specification/creature/CreatureTest.java | 133 ---- .../selector/ColorSelectorTest.java | 59 -- .../selector/MovementSelectorTest.java | 60 -- .../selector/SizeSelectorTest.java | 58 -- state/README.md | 36 - state/etc/state.png | Bin 17753 -> 0 bytes state/etc/state.ucls | 80 --- state/etc/state.urm.puml | 39 -- state/etc/state_1.png | Bin 33886 -> 0 bytes state/pom.xml | 47 -- .../java/com/iluwatar/state/AngryState.java | 53 -- .../src/main/java/com/iluwatar/state/App.java | 51 -- .../main/java/com/iluwatar/state/Mammoth.java | 62 -- .../com/iluwatar/state/PeacefulState.java | 53 -- .../main/java/com/iluwatar/state/State.java | 36 - .../test/java/com/iluwatar/state/AppTest.java | 39 -- .../java/com/iluwatar/state/MammothTest.java | 120 ---- step-builder/README.md | 24 - step-builder/etc/step-builder.png | Bin 76038 -> 0 bytes step-builder/etc/step-builder.ucls | 181 ----- step-builder/etc/step-builder.urm.puml | 91 --- step-builder/pom.xml | 43 -- .../java/com/iluwatar/stepbuilder/App.java | 89 --- .../com/iluwatar/stepbuilder/Character.java | 104 --- .../stepbuilder/CharacterStepBuilder.java | 187 ----- .../com/iluwatar/stepbuilder/AppTest.java | 39 -- .../stepbuilder/CharacterStepBuilderTest.java | 177 ----- template-method/README.md | 30 - template-method/etc/template-method.png | Bin 17911 -> 0 bytes template-method/etc/template-method.ucls | 66 -- template-method/etc/template-method.urm.puml | 39 -- template-method/etc/template-method_1.png | Bin 34592 -> 0 bytes template-method/pom.xml | 47 -- .../java/com/iluwatar/templatemethod/App.java | 47 -- .../templatemethod/HalflingThief.java | 45 -- .../templatemethod/HitAndRunMethod.java | 51 -- .../templatemethod/StealingMethod.java | 52 -- .../iluwatar/templatemethod/SubtleMethod.java | 51 -- .../com/iluwatar/templatemethod/AppTest.java | 39 -- .../templatemethod/HalflingThiefTest.java | 72 -- .../templatemethod/HitAndRunMethodTest.java | 45 -- .../templatemethod/StealingMethodTest.java | 171 ----- .../templatemethod/SubtleMethodTest.java | 45 -- thread-pool/README.md | 26 - thread-pool/etc/thread-pool.png | Bin 14796 -> 0 bytes thread-pool/etc/thread-pool.ucls | 62 -- thread-pool/etc/thread-pool.urm.puml | 37 - thread-pool/pom.xml | 47 -- .../java/com/iluwatar/threadpool/App.java | 99 --- .../iluwatar/threadpool/CoffeeMakingTask.java | 42 -- .../threadpool/PotatoPeelingTask.java | 42 -- .../java/com/iluwatar/threadpool/Task.java | 56 -- .../java/com/iluwatar/threadpool/Worker.java | 52 -- .../java/com/iluwatar/threadpool/AppTest.java | 40 -- .../threadpool/CoffeeMakingTaskTest.java | 39 -- .../threadpool/PotatoPeelingTaskTest.java | 39 -- .../com/iluwatar/threadpool/TaskTest.java | 145 ---- .../com/iluwatar/threadpool/WorkerTest.java | 53 -- throttling/README.md | 19 - throttling/etc/throttling-pattern.png | Bin 60408 -> 0 bytes throttling/etc/throttling.urm.puml | 29 - throttling/pom.xml | 44 -- .../java/com/iluwatar/throttling/App.java | 90 --- .../com/iluwatar/throttling/B2BService.java | 62 -- .../com/iluwatar/throttling/CallsCount.java | 77 -- .../java/com/iluwatar/throttling/Tenant.java | 57 -- .../throttling/timer/ThrottleTimerImpl.java | 58 -- .../iluwatar/throttling/timer/Throttler.java | 36 - .../java/com/iluwatar/throttling/AppTest.java | 37 - .../iluwatar/throttling/B2BServiceTest.java | 48 -- .../com/iluwatar/throttling/TenantTest.java | 40 -- tls/README.md | 22 - tls/etc/tls.png | Bin 34509 -> 0 bytes tls/etc/tls.ucls | 79 --- tls/etc/tls.urm.puml | 23 - tls/pom.xml | 43 -- tls/src/main/java/com/iluwatar/tls/App.java | 146 ---- .../com/iluwatar/tls/DateFormatCallable.java | 98 --- .../main/java/com/iluwatar/tls/Result.java | 62 -- .../test/java/com/iluwatar/tls/AppTest.java | 40 -- .../iluwatar/tls/DateFormatCallableTest.java | 144 ---- ...FormatCallableTestIncorrectDateFormat.java | 127 ---- .../DateFormatCallableTestMultiThread.java | 164 ----- tolerant-reader/README.md | 28 - tolerant-reader/etc/tolerant-reader.png | Bin 20514 -> 0 bytes tolerant-reader/etc/tolerant-reader.ucls | 52 -- tolerant-reader/etc/tolerant-reader.urm.puml | 39 -- tolerant-reader/pom.xml | 42 -- .../java/com/iluwatar/tolerantreader/App.java | 76 -- .../iluwatar/tolerantreader/RainbowFish.java | 67 -- .../tolerantreader/RainbowFishSerializer.java | 93 --- .../tolerantreader/RainbowFishV2.java | 64 -- .../com/iluwatar/tolerantreader/AppTest.java | 53 -- .../RainbowFishSerializerTest.java | 90 --- .../tolerantreader/RainbowFishTest.java | 48 -- .../tolerantreader/RainbowFishV2Test.java | 51 -- twin/.gitignore | 1 - twin/README.md | 27 - twin/etc/twin.png | Bin 29682 -> 0 bytes twin/etc/twin.ucls | 79 --- twin/etc/twin.urm.puml | 27 - twin/pom.xml | 47 -- twin/src/main/java/com/iluwatar/twin/App.java | 68 -- .../main/java/com/iluwatar/twin/BallItem.java | 68 -- .../java/com/iluwatar/twin/BallThread.java | 82 --- .../main/java/com/iluwatar/twin/GameItem.java | 49 -- .../test/java/com/iluwatar/twin/AppTest.java | 39 -- .../java/com/iluwatar/twin/BallItemTest.java | 132 ---- .../com/iluwatar/twin/BallThreadTest.java | 111 --- update-ghpages.sh | 45 -- value-object/README.md | 35 - value-object/etc/value-object.png | Bin 5025 -> 0 bytes value-object/etc/value-object.ucls | 19 - value-object/etc/value-object.urm.puml | 22 - value-object/pom.xml | 54 -- .../java/com/iluwatar/value/object/App.java | 60 -- .../com/iluwatar/value/object/HeroStat.java | 112 --- .../com/iluwatar/value/object/AppTest.java | 37 - .../iluwatar/value/object/HeroStatTest.java | 66 -- visitor/README.md | 37 - visitor/etc/visitor.png | Bin 22790 -> 0 bytes visitor/etc/visitor.ucls | 114 --- visitor/etc/visitor.urm.puml | 60 -- visitor/etc/visitor_1.png | Bin 47078 -> 0 bytes visitor/pom.xml | 47 -- .../main/java/com/iluwatar/visitor/App.java | 52 -- .../java/com/iluwatar/visitor/Commander.java | 46 -- .../iluwatar/visitor/CommanderVisitor.java | 51 -- .../java/com/iluwatar/visitor/Sergeant.java | 46 -- .../com/iluwatar/visitor/SergeantVisitor.java | 51 -- .../java/com/iluwatar/visitor/Soldier.java | 46 -- .../com/iluwatar/visitor/SoldierVisitor.java | 51 -- .../main/java/com/iluwatar/visitor/Unit.java | 46 -- .../com/iluwatar/visitor/UnitVisitor.java | 38 - .../java/com/iluwatar/visitor/AppTest.java | 39 -- .../com/iluwatar/visitor/CommanderTest.java | 47 -- .../visitor/CommanderVisitorTest.java | 46 -- .../com/iluwatar/visitor/SergeantTest.java | 47 -- .../iluwatar/visitor/SergeantVisitorTest.java | 46 -- .../com/iluwatar/visitor/SoldierTest.java | 47 -- .../iluwatar/visitor/SoldierVisitorTest.java | 46 -- .../java/com/iluwatar/visitor/UnitTest.java | 82 --- .../com/iluwatar/visitor/VisitorTest.java | 142 ---- 1468 files changed, 89803 deletions(-) delete mode 100644 .travis.yml delete mode 100644 CODE_COVERAGE.md delete mode 100644 CONTRIBUTING.MD delete mode 100644 LICENSE.md delete mode 100644 README.md delete mode 100644 _scripts/postPumlsToServer.py delete mode 100644 abstract-document/README.md delete mode 100644 abstract-document/etc/abstract-document-base.png delete mode 100644 abstract-document/etc/abstract-document-base.ucls delete mode 100644 abstract-document/etc/abstract-document.png delete mode 100644 abstract-document/etc/abstract-document.ucls delete mode 100644 abstract-document/etc/abstract-document.urm.puml delete mode 100644 abstract-document/pom.xml delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java delete mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java delete mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java delete mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java delete mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java delete mode 100644 abstract-factory/.gitignore delete mode 100644 abstract-factory/README.md delete mode 100644 abstract-factory/pom.xml delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java delete mode 100644 abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java delete mode 100644 abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java delete mode 100644 abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java delete mode 100644 aggregator-microservices/README.md delete mode 100644 aggregator-microservices/aggregator-service/pom.xml delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Aggregator.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/App.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Product.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClient.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClient.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java delete mode 100644 aggregator-microservices/aggregator-service/src/main/resources/application.properties delete mode 100644 aggregator-microservices/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java delete mode 100644 aggregator-microservices/etc/aggregator-microservice.png delete mode 100644 aggregator-microservices/etc/aggregator-service.urm.puml delete mode 100644 aggregator-microservices/etc/information-microservice.urm.puml delete mode 100644 aggregator-microservices/etc/inventory-microservice.urm.puml delete mode 100644 aggregator-microservices/information-microservice/pom.xml delete mode 100644 aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationApplication.java delete mode 100644 aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java delete mode 100644 aggregator-microservices/information-microservice/src/main/resources/application.properties delete mode 100644 aggregator-microservices/information-microservice/src/test/java/com/iluwatar/information/microservice/InformationControllerTest.java delete mode 100644 aggregator-microservices/inventory-microservice/pom.xml delete mode 100644 aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryApplication.java delete mode 100644 aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryController.java delete mode 100644 aggregator-microservices/inventory-microservice/src/main/resources/application.properties delete mode 100644 aggregator-microservices/inventory-microservice/src/test/java/com/iluwatar/inventory/microservice/InventoryControllerTest.java delete mode 100644 aggregator-microservices/pom.xml delete mode 100644 api-gateway/README.md delete mode 100644 api-gateway/api-gateway-service/pom.xml delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java delete mode 100644 api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java delete mode 100644 api-gateway/api-gateway-service/src/main/resources/application.properties delete mode 100644 api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java delete mode 100644 api-gateway/etc/api-gateway-service.urm.puml delete mode 100644 api-gateway/etc/api-gateway.png delete mode 100644 api-gateway/etc/api-gateway.ucls delete mode 100644 api-gateway/etc/image-microservice.urm.puml delete mode 100644 api-gateway/etc/price-microservice.urm.puml delete mode 100644 api-gateway/image-microservice/etc/image-microservice.png delete mode 100644 api-gateway/image-microservice/etc/image-microservice.ucls delete mode 100644 api-gateway/image-microservice/pom.xml delete mode 100644 api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java delete mode 100644 api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java delete mode 100644 api-gateway/image-microservice/src/main/resources/application.properties delete mode 100644 api-gateway/image-microservice/src/test/java/com/iluwatar/image/microservice/ImageControllerTest.java delete mode 100644 api-gateway/pom.xml delete mode 100644 api-gateway/price-microservice/etc/price-microservice.png delete mode 100644 api-gateway/price-microservice/etc/price-microservice.ucls delete mode 100644 api-gateway/price-microservice/pom.xml delete mode 100644 api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java delete mode 100644 api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java delete mode 100644 api-gateway/price-microservice/src/main/resources/application.properties delete mode 100644 api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceControllerTest.java delete mode 100644 async-method-invocation/README.md delete mode 100644 async-method-invocation/etc/async-method-invocation.png delete mode 100644 async-method-invocation/etc/async-method-invocation.ucls delete mode 100644 async-method-invocation/etc/async-method-invocation.urm.puml delete mode 100644 async-method-invocation/pom.xml delete mode 100644 async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java delete mode 100644 async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncCallback.java delete mode 100644 async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncExecutor.java delete mode 100644 async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java delete mode 100644 async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java delete mode 100644 async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/AppTest.java delete mode 100644 async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java delete mode 100644 balking/README.md delete mode 100644 balking/etc/balking.png delete mode 100644 balking/etc/balking.ucls delete mode 100644 balking/etc/balking.urm.puml delete mode 100644 balking/pom.xml delete mode 100644 balking/src/main/java/com/iluwatar/balking/App.java delete mode 100644 balking/src/main/java/com/iluwatar/balking/WashingMachine.java delete mode 100644 balking/src/main/java/com/iluwatar/balking/WashingMachineState.java delete mode 100644 balking/src/test/java/com/iluwatar/balking/AppTest.java delete mode 100644 balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java delete mode 100644 bridge/README.md delete mode 100644 bridge/pom.xml delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/App.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/Enchantment.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/Hammer.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/Sword.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/Weapon.java delete mode 100644 bridge/src/test/java/com/iluwatar/bridge/AppTest.java delete mode 100644 bridge/src/test/java/com/iluwatar/bridge/HammerTest.java delete mode 100644 bridge/src/test/java/com/iluwatar/bridge/SwordTest.java delete mode 100644 bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java delete mode 100644 builder/.gitignore delete mode 100644 builder/README.md delete mode 100644 builder/pom.xml delete mode 100644 builder/src/main/java/com/iluwatar/builder/App.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/Armor.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/HairColor.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/HairType.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/Hero.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/Profession.java delete mode 100644 builder/src/main/java/com/iluwatar/builder/Weapon.java delete mode 100644 builder/src/test/java/com/iluwatar/builder/AppTest.java delete mode 100644 builder/src/test/java/com/iluwatar/builder/HeroTest.java delete mode 100644 business-delegate/README.md delete mode 100644 business-delegate/etc/business-delegate.png delete mode 100644 business-delegate/etc/business-delegate.ucls delete mode 100644 business-delegate/etc/business-delegate.urm.puml delete mode 100644 business-delegate/pom.xml delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/App.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessLookup.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessService.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/Client.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java delete mode 100644 business-delegate/src/main/java/com/iluwatar/business/delegate/ServiceType.java delete mode 100644 business-delegate/src/test/java/com/iluwatar/business/delegate/AppTest.java delete mode 100644 business-delegate/src/test/java/com/iluwatar/business/delegate/BusinessDelegateTest.java delete mode 100644 caching/.gitignore delete mode 100644 caching/README.md delete mode 100644 caching/etc/caching.png delete mode 100644 caching/etc/caching.ucls delete mode 100644 caching/etc/caching.urm.puml delete mode 100644 caching/pom.xml delete mode 100644 caching/src/main/java/com/iluwatar/caching/App.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/AppManager.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/CacheStore.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/CachingPolicy.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/DbManager.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/LruCache.java delete mode 100644 caching/src/main/java/com/iluwatar/caching/UserAccount.java delete mode 100644 caching/src/test/java/com/iluwatar/caching/AppTest.java delete mode 100644 caching/src/test/java/com/iluwatar/caching/CachingTest.java delete mode 100644 callback/README.md delete mode 100644 callback/etc/callback.png delete mode 100644 callback/etc/callback.ucls delete mode 100644 callback/etc/callback.urm.puml delete mode 100644 callback/pom.xml delete mode 100644 callback/src/main/java/com/iluwatar/callback/App.java delete mode 100644 callback/src/main/java/com/iluwatar/callback/Callback.java delete mode 100644 callback/src/main/java/com/iluwatar/callback/LambdasApp.java delete mode 100644 callback/src/main/java/com/iluwatar/callback/SimpleTask.java delete mode 100644 callback/src/main/java/com/iluwatar/callback/Task.java delete mode 100644 callback/src/test/java/com/iluwatar/callback/AppTest.java delete mode 100644 callback/src/test/java/com/iluwatar/callback/CallbackTest.java delete mode 100644 chain/README.md delete mode 100644 chain/pom.xml delete mode 100644 chain/src/main/java/com/iluwatar/chain/App.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/OrcCommander.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/OrcKing.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/OrcOfficer.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/OrcSoldier.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/Request.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/RequestHandler.java delete mode 100644 chain/src/main/java/com/iluwatar/chain/RequestType.java delete mode 100644 chain/src/test/java/com/iluwatar/chain/AppTest.java delete mode 100644 chain/src/test/java/com/iluwatar/chain/OrcKingTest.java delete mode 100644 checkstyle-suppressions.xml delete mode 100644 checkstyle.xml delete mode 100644 converter/README.md delete mode 100644 converter/etc/Converter.png delete mode 100644 converter/etc/Converter.ucls delete mode 100644 converter/etc/converter.urm.puml delete mode 100644 converter/pom.xml delete mode 100644 converter/src/main/java/com/iluwatar/converter/App.java delete mode 100644 converter/src/main/java/com/iluwatar/converter/Converter.java delete mode 100644 converter/src/main/java/com/iluwatar/converter/User.java delete mode 100644 converter/src/main/java/com/iluwatar/converter/UserConverter.java delete mode 100644 converter/src/main/java/com/iluwatar/converter/UserDto.java delete mode 100644 converter/src/test/java/com/iluwatar/converter/AppTest.java delete mode 100644 converter/src/test/java/com/iluwatar/converter/ConverterTest.java delete mode 100644 cqrs/README.md delete mode 100644 cqrs/etc/cqrs.png delete mode 100644 cqrs/etc/cqrs.ucls delete mode 100644 cqrs/etc/cqrs.urm.puml delete mode 100644 cqrs/pom.xml delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/app/App.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java delete mode 100644 cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java delete mode 100644 cqrs/src/main/resources/hibernate.cfg.xml delete mode 100644 cqrs/src/main/resources/logback.xml delete mode 100644 cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java delete mode 100644 cqrs/src/test/resources/hibernate.cfg.xml delete mode 100644 cqrs/src/test/resources/logback.xml delete mode 100644 dao/README.md delete mode 100644 dao/etc/dao.png delete mode 100644 dao/etc/dao.ucls delete mode 100644 dao/etc/dao.urm.puml delete mode 100644 dao/pom.xml delete mode 100644 dao/src/main/java/com/iluwatar/dao/App.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/CustomException.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/Customer.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/CustomerDao.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java delete mode 100644 dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java delete mode 100644 dao/src/main/resources/log4j.xml delete mode 100644 dao/src/test/java/com/iluwatar/dao/AppTest.java delete mode 100644 dao/src/test/java/com/iluwatar/dao/CustomerTest.java delete mode 100644 dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java delete mode 100644 dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java delete mode 100644 data-bus/.gitignore delete mode 100644 data-bus/README.md delete mode 100644 data-bus/etc/data-bus.urm.png delete mode 100644 data-bus/etc/data-bus.urm.puml delete mode 100644 data-bus/pom.xml delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/AbstractDataType.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/App.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/DataBus.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/DataType.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/Member.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/data/MessageData.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java delete mode 100644 data-bus/src/main/java/com/iluwatar/databus/members/StatusMember.java delete mode 100644 data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java delete mode 100644 data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java delete mode 100644 data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java delete mode 100644 data-mapper/README.md delete mode 100644 data-mapper/etc/data-mapper.png delete mode 100644 data-mapper/etc/data-mapper.ucls delete mode 100644 data-mapper/etc/data-mapper.urm.puml delete mode 100644 data-mapper/pom.xml delete mode 100644 data-mapper/src/main/java/com/iluwatar/datamapper/App.java delete mode 100644 data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java delete mode 100644 data-mapper/src/main/java/com/iluwatar/datamapper/Student.java delete mode 100644 data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapper.java delete mode 100644 data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapperImpl.java delete mode 100644 data-mapper/src/main/resources/log4j.xml delete mode 100644 data-mapper/src/test/java/com/iluwatar/datamapper/AppTest.java delete mode 100644 data-mapper/src/test/java/com/iluwatar/datamapper/DataMapperTest.java delete mode 100644 data-mapper/src/test/java/com/iluwatar/datamapper/StudentTest.java delete mode 100644 data-transfer-object/README.md delete mode 100644 data-transfer-object/etc/data-transfer-object.ucls delete mode 100644 data-transfer-object/etc/data-transfer-object.urm.png delete mode 100644 data-transfer-object/etc/data-transfer-object.urm.puml delete mode 100644 data-transfer-object/pom.xml delete mode 100644 data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerClientApp.java delete mode 100644 data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerDto.java delete mode 100644 data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerResource.java delete mode 100644 data-transfer-object/src/test/java/com/iluwatar/datatransfer/CustomerResourceTest.java delete mode 100644 delegation/README.md delete mode 100644 delegation/etc/delegation.png delete mode 100644 delegation/etc/delegation.ucls delete mode 100644 delegation/etc/delegation.urm.puml delete mode 100644 delegation/pom.xml delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/App.java delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java delete mode 100644 delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java delete mode 100644 delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java delete mode 100644 delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java delete mode 100644 dependency-injection/README.md delete mode 100644 dependency-injection/etc/dependency-injection.png delete mode 100644 dependency-injection/etc/dependency-injection.ucls delete mode 100644 dependency-injection/etc/dependency-injection.urm.puml delete mode 100644 dependency-injection/pom.xml delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedSorceress.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedWizard.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/App.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/GuiceWizard.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/OldTobyTobacco.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/RivendellTobacco.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/SecondBreakfastTobacco.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/SimpleWizard.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/TobaccoModule.java delete mode 100644 dependency-injection/src/main/java/com/iluwatar/dependency/injection/Wizard.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedSorceressTest.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/AppTest.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java delete mode 100644 double-checked-locking/README.md delete mode 100644 double-checked-locking/etc/double-checked-locking.png delete mode 100644 double-checked-locking/etc/double-checked-locking.ucls delete mode 100644 double-checked-locking/etc/double-checked-locking.urm.puml delete mode 100644 double-checked-locking/etc/double_checked_locking_1.png delete mode 100644 double-checked-locking/pom.xml delete mode 100644 double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java delete mode 100644 double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java delete mode 100644 double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java delete mode 100644 double-checked-locking/src/main/resources/logback.xml delete mode 100644 double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/AppTest.java delete mode 100644 double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java delete mode 100644 double-dispatch/README.md delete mode 100644 double-dispatch/etc/double-dispatch.png delete mode 100644 double-dispatch/etc/double-dispatch.ucls delete mode 100644 double-dispatch/etc/double-dispatch.urm.puml delete mode 100644 double-dispatch/pom.xml delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/FlamingAsteroid.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/GameObject.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationIss.java delete mode 100644 double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/AppTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java delete mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java delete mode 100644 eip-splitter/README.md delete mode 100644 eip-splitter/etc/sequencer.gif delete mode 100644 eip-splitter/pom.xml delete mode 100644 eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java delete mode 100644 eip-splitter/src/main/java/com/iluwatar/eip/splitter/routes/SplitterRoute.java delete mode 100644 eip-splitter/src/main/resources/application.properties delete mode 100644 eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java delete mode 100644 eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java delete mode 100644 eip-splitter/src/test/resources/application-test.properties delete mode 100644 eip-wire-tap/README.md delete mode 100644 eip-wire-tap/etc/wiretap.gif delete mode 100644 eip-wire-tap/pom.xml delete mode 100644 eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java delete mode 100644 eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/routes/WireTapRoute.java delete mode 100644 eip-wire-tap/src/main/resources/application.properties delete mode 100644 eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java delete mode 100644 eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java delete mode 100644 eip-wire-tap/src/test/resources/application-test.properties delete mode 100644 event-aggregator/README.md delete mode 100644 event-aggregator/etc/classes.png delete mode 100644 event-aggregator/etc/classes.ucls delete mode 100644 event-aggregator/etc/event-aggregator.urm.puml delete mode 100644 event-aggregator/pom.xml delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/App.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/Event.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventObserver.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingsHand.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordBaelish.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordVarys.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/Scout.java delete mode 100644 event-aggregator/src/main/java/com/iluwatar/event/aggregator/Weekday.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/AppTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java delete mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java delete mode 100644 event-asynchronous/README.md delete mode 100644 event-asynchronous/etc/event-asynchronous.png delete mode 100644 event-asynchronous/etc/event-asynchronous.ucls delete mode 100644 event-asynchronous/etc/event-asynchronous.urm.puml delete mode 100644 event-asynchronous/pom.xml delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventDoesNotExistException.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/InvalidOperationException.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/LongRunningEventException.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/MaxNumOfEventsAllowedException.java delete mode 100644 event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java delete mode 100644 event-asynchronous/src/main/resources/config.properties delete mode 100644 event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/AppTest.java delete mode 100644 event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java delete mode 100644 event-driven-architecture/README.md delete mode 100644 event-driven-architecture/etc/eda.png delete mode 100644 event-driven-architecture/etc/eda.ucls delete mode 100644 event-driven-architecture/etc/event-driven-architecture.urm.puml delete mode 100644 event-driven-architecture/pom.xml delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/App.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java delete mode 100644 event-driven-architecture/src/test/java/com/iluwatar/eda/AppTest.java delete mode 100644 event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java delete mode 100644 event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java delete mode 100644 event-queue/README.md delete mode 100644 event-queue/etc/Bass-Drum-1.aif delete mode 100644 event-queue/etc/Bass-Drum-1.wav delete mode 100644 event-queue/etc/Closed-Hi-Hat-1.aif delete mode 100644 event-queue/etc/Closed-Hi-Hat-1.wav delete mode 100644 event-queue/etc/event-queue.urm.puml delete mode 100644 event-queue/etc/model.png delete mode 100644 event-queue/etc/model.ucls delete mode 100644 event-queue/pom.xml delete mode 100644 event-queue/src/main/java/com/iluwatar/event/queue/App.java delete mode 100644 event-queue/src/main/java/com/iluwatar/event/queue/Audio.java delete mode 100644 event-queue/src/main/java/com/iluwatar/event/queue/PlayMessage.java delete mode 100644 event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java delete mode 100644 event-sourcing/README.md delete mode 100644 event-sourcing/etc/event-sourcing.png delete mode 100644 event-sourcing/etc/event-sourcing.ucls delete mode 100644 event-sourcing/etc/event-sourcing.urm.puml delete mode 100644 event-sourcing/pom.xml delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/app/App.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java delete mode 100644 event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java delete mode 100644 event-sourcing/src/test/java/IntegrationTest.java delete mode 100644 exclude-pmd.properties delete mode 100644 execute-around/README.md delete mode 100644 execute-around/etc/execute-around.png delete mode 100644 execute-around/etc/execute-around.ucls delete mode 100644 execute-around/etc/execute-around.urm.puml delete mode 100644 execute-around/pom.xml delete mode 100644 execute-around/src/main/java/com/iluwatar/execute/around/App.java delete mode 100644 execute-around/src/main/java/com/iluwatar/execute/around/FileWriterAction.java delete mode 100644 execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java delete mode 100644 execute-around/src/test/java/com/iluwatar/execute/around/AppTest.java delete mode 100644 execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java delete mode 100644 extension-objects/README.md delete mode 100644 extension-objects/etc/extension-objects.urm.puml delete mode 100644 extension-objects/etc/extension_obj.png delete mode 100644 extension-objects/etc/extension_obj.ucls delete mode 100644 extension-objects/pom.xml delete mode 100644 extension-objects/src/main/java/App.java delete mode 100644 extension-objects/src/main/java/abstractextensions/CommanderExtension.java delete mode 100644 extension-objects/src/main/java/abstractextensions/SergeantExtension.java delete mode 100644 extension-objects/src/main/java/abstractextensions/SoldierExtension.java delete mode 100644 extension-objects/src/main/java/abstractextensions/UnitExtension.java delete mode 100644 extension-objects/src/main/java/concreteextensions/Commander.java delete mode 100644 extension-objects/src/main/java/concreteextensions/Sergeant.java delete mode 100644 extension-objects/src/main/java/concreteextensions/Soldier.java delete mode 100644 extension-objects/src/main/java/units/CommanderUnit.java delete mode 100644 extension-objects/src/main/java/units/SergeantUnit.java delete mode 100644 extension-objects/src/main/java/units/SoldierUnit.java delete mode 100644 extension-objects/src/main/java/units/Unit.java delete mode 100644 extension-objects/src/test/java/AppTest.java delete mode 100644 extension-objects/src/test/java/concreteextensions/CommanderTest.java delete mode 100644 extension-objects/src/test/java/concreteextensions/SergeantTest.java delete mode 100644 extension-objects/src/test/java/concreteextensions/SoldierTest.java delete mode 100644 extension-objects/src/test/java/units/CommanderUnitTest.java delete mode 100644 extension-objects/src/test/java/units/SergeantUnitTest.java delete mode 100644 extension-objects/src/test/java/units/SoldierUnitTest.java delete mode 100644 extension-objects/src/test/java/units/UnitTest.java delete mode 100644 factory-kit/README.md delete mode 100644 factory-kit/etc/factory-kit.png delete mode 100644 factory-kit/etc/factory-kit.ucls delete mode 100644 factory-kit/etc/factory-kit.urm.puml delete mode 100644 factory-kit/pom.xml delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/App.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java delete mode 100644 factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java delete mode 100644 factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java delete mode 100644 factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java delete mode 100644 factory-method/.gitignore delete mode 100644 factory-method/README.md delete mode 100644 factory-method/pom.xml delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/App.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/Blacksmith.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/Weapon.java delete mode 100644 factory-method/src/main/java/com/iluwatar/factory/method/WeaponType.java delete mode 100644 factory-method/src/test/java/com/iluwatar/factory/method/AppTest.java delete mode 100644 factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java delete mode 100644 faq.md delete mode 100644 feature-toggle/README.md delete mode 100644 feature-toggle/etc/feature-toggle.png delete mode 100644 feature-toggle/etc/feature-toggle.ucls delete mode 100644 feature-toggle/etc/feature-toggle.urm.puml delete mode 100644 feature-toggle/pom.xml delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java delete mode 100644 feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java delete mode 100644 feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java delete mode 100644 feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java delete mode 100644 feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java delete mode 100644 fluentinterface/README.md delete mode 100644 fluentinterface/etc/fluentinterface.png delete mode 100644 fluentinterface/etc/fluentinterface.ucls delete mode 100644 fluentinterface/etc/fluentinterface.urm.puml delete mode 100644 fluentinterface/pom.xml delete mode 100644 fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java delete mode 100644 fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java delete mode 100644 fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java delete mode 100644 fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java delete mode 100644 fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java delete mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/app/AppTest.java delete mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java delete mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java delete mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java delete mode 100644 flux/README.md delete mode 100644 flux/etc/flux.png delete mode 100644 flux/etc/flux.ucls delete mode 100644 flux/etc/flux.urm.puml delete mode 100644 flux/pom.xml delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/Action.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/ActionType.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/Content.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/ContentAction.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/MenuAction.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/action/MenuItem.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/app/App.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/store/ContentStore.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/store/MenuStore.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/store/Store.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/view/ContentView.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/view/MenuView.java delete mode 100644 flux/src/main/java/com/iluwatar/flux/view/View.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/action/ContentTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/app/AppTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java delete mode 100644 flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java delete mode 100644 flyweight/README.md delete mode 100644 flyweight/pom.xml delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/App.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/Potion.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/PotionFactory.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/PotionType.java delete mode 100644 flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java delete mode 100644 flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java delete mode 100644 flyweight/src/test/java/com/iluwatar/flyweight/AppTest.java delete mode 100644 front-controller/README.md delete mode 100644 front-controller/etc/front-controller.png delete mode 100644 front-controller/etc/front-controller.ucls delete mode 100644 front-controller/etc/front-controller.urm.puml delete mode 100644 front-controller/pom.xml delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/App.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/Command.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java delete mode 100644 front-controller/src/main/java/com/iluwatar/front/controller/View.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java delete mode 100644 guarded-suspension/README.md delete mode 100644 guarded-suspension/etc/guarded-suspension.png delete mode 100644 guarded-suspension/etc/guarded-suspension.ucls delete mode 100644 guarded-suspension/etc/guarded-suspension.urm.puml delete mode 100644 guarded-suspension/pom.xml delete mode 100644 guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/App.java delete mode 100644 guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java delete mode 100644 guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java delete mode 100644 half-sync-half-async/README.md delete mode 100644 half-sync-half-async/etc/half-sync-half-async.png delete mode 100644 half-sync-half-async/etc/half-sync-half-async.ucls delete mode 100644 half-sync-half-async/etc/half-sync-half-async.urm.puml delete mode 100644 half-sync-half-async/pom.xml delete mode 100644 half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java delete mode 100644 half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java delete mode 100644 half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java delete mode 100644 half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AppTest.java delete mode 100644 half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java delete mode 100644 hexagonal/README.md delete mode 100644 hexagonal/etc/hexagonal.png delete mode 100644 hexagonal/etc/hexagonal.ucls delete mode 100644 hexagonal/etc/hexagonal.urm.puml delete mode 100644 hexagonal/etc/layers.png delete mode 100644 hexagonal/etc/ports_and_adapters.png delete mode 100644 hexagonal/etc/ports_and_adapters.xml delete mode 100644 hexagonal/etc/presentation.html delete mode 100644 hexagonal/pom.xml delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/App.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/LotteryEventLog.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryModule.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryTestingModule.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java delete mode 100644 hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/banking/InMemoryBankTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/banking/MongoBankTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryNumbersTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResultTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketIdTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/domain/PlayerDetailsTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/eventlog/MongoEventLogTest.java delete mode 100644 hexagonal/src/test/java/com/iluwatar/hexagonal/test/LotteryTestUtils.java delete mode 100644 intercepting-filter/README.md delete mode 100644 intercepting-filter/etc/intercepting-filter.png delete mode 100644 intercepting-filter/etc/intercepting-filter.ucls delete mode 100644 intercepting-filter/etc/intercepting-filter.urm.puml delete mode 100644 intercepting-filter/pom.xml delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/App.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java delete mode 100644 intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java delete mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/AppTest.java delete mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java delete mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java delete mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java delete mode 100644 interpreter/README.md delete mode 100644 interpreter/etc/interpreter.png delete mode 100644 interpreter/etc/interpreter.ucls delete mode 100644 interpreter/etc/interpreter.urm.puml delete mode 100644 interpreter/etc/interpreter_1.png delete mode 100644 interpreter/pom.xml delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/App.java delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/Expression.java delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java delete mode 100644 interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/AppTest.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java delete mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java delete mode 100644 layers/README.md delete mode 100644 layers/etc/layers.png delete mode 100644 layers/etc/layers.ucls delete mode 100644 layers/etc/layers.urm.puml delete mode 100644 layers/pom.xml delete mode 100644 layers/src/main/java/com/iluwatar/layers/App.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/Cake.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeBakingException.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeBakingService.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeDao.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeInfo.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeLayer.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeLayerDao.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeTopping.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeToppingDao.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java delete mode 100644 layers/src/main/java/com/iluwatar/layers/View.java delete mode 100644 layers/src/main/resources/META-INF/persistence.xml delete mode 100644 layers/src/main/resources/applicationContext.xml delete mode 100644 layers/src/main/resources/logback.xml delete mode 100644 layers/src/test/java/com/iluwatar/layers/AppTest.java delete mode 100644 layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java delete mode 100644 layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java delete mode 100644 layers/src/test/java/com/iluwatar/layers/CakeTest.java delete mode 100644 layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java delete mode 100644 lazy-loading/README.md delete mode 100644 lazy-loading/etc/lazy-loading.png delete mode 100644 lazy-loading/etc/lazy-loading.ucls delete mode 100644 lazy-loading/etc/lazy-loading.urm.puml delete mode 100644 lazy-loading/pom.xml delete mode 100644 lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java delete mode 100644 lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java delete mode 100644 lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java delete mode 100644 lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java delete mode 100644 lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java delete mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java delete mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/AppTest.java delete mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java delete mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java delete mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java delete mode 100644 marker/.gitignore delete mode 100644 marker/README.md delete mode 100644 marker/etc/MarkerDiagram.png delete mode 100644 marker/etc/MarkerDiagram.ucls delete mode 100644 marker/etc/marker.urm.puml delete mode 100644 marker/pom.xml delete mode 100644 marker/src/main/java/App.java delete mode 100644 marker/src/main/java/Guard.java delete mode 100644 marker/src/main/java/Permission.java delete mode 100644 marker/src/main/java/Thief.java delete mode 100644 marker/src/test/java/AppTest.java delete mode 100644 marker/src/test/java/GuardTest.java delete mode 100644 marker/src/test/java/ThiefTest.java delete mode 100644 mediator/README.md delete mode 100644 mediator/etc/mediator.png delete mode 100644 mediator/etc/mediator.ucls delete mode 100644 mediator/etc/mediator.urm.puml delete mode 100644 mediator/etc/mediator_1.png delete mode 100644 mediator/pom.xml delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Action.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/App.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Hobbit.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Hunter.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Party.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/PartyMember.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Rogue.java delete mode 100644 mediator/src/main/java/com/iluwatar/mediator/Wizard.java delete mode 100644 mediator/src/test/java/com/iluwatar/mediator/AppTest.java delete mode 100644 mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java delete mode 100644 mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java delete mode 100644 memento/README.md delete mode 100644 memento/etc/memento.png delete mode 100644 memento/etc/memento.ucls delete mode 100644 memento/etc/memento.urm.puml delete mode 100644 memento/pom.xml delete mode 100644 memento/src/main/java/com/iluwatar/memento/App.java delete mode 100644 memento/src/main/java/com/iluwatar/memento/Star.java delete mode 100644 memento/src/main/java/com/iluwatar/memento/StarMemento.java delete mode 100644 memento/src/main/java/com/iluwatar/memento/StarType.java delete mode 100644 memento/src/test/java/com/iluwatar/memento/AppTest.java delete mode 100644 memento/src/test/java/com/iluwatar/memento/StarTest.java delete mode 100644 message-channel/.gitignore delete mode 100644 message-channel/README.md delete mode 100644 message-channel/etc/message-channel.png delete mode 100644 message-channel/etc/message-channel.ucls delete mode 100644 message-channel/etc/message-channel.urm.puml delete mode 100644 message-channel/pom.xml delete mode 100644 message-channel/src/main/java/com/iluwatar/message/channel/App.java delete mode 100644 message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java delete mode 100644 model-view-controller/README.md delete mode 100644 model-view-controller/etc/model-view-controller.png delete mode 100644 model-view-controller/etc/model-view-controller.ucls delete mode 100644 model-view-controller/etc/model-view-controller.urm.puml delete mode 100644 model-view-controller/pom.xml delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java delete mode 100644 model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java delete mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/AppTest.java delete mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java delete mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java delete mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java delete mode 100644 model-view-presenter/README.md delete mode 100644 model-view-presenter/etc/data/test.txt delete mode 100644 model-view-presenter/etc/model-view-presenter.png delete mode 100644 model-view-presenter/etc/model-view-presenter.ucls delete mode 100644 model-view-presenter/etc/model-view-presenter.urm.puml delete mode 100644 model-view-presenter/etc/model-view-presenter_1.png delete mode 100644 model-view-presenter/pom.xml delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java delete mode 100644 model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java delete mode 100644 model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java delete mode 100644 model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java delete mode 100644 model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java delete mode 100644 module/README.md delete mode 100644 module/error.txt delete mode 100644 module/etc/module.png delete mode 100644 module/etc/module.ucls delete mode 100644 module/etc/module.urm.puml delete mode 100644 module/output.txt delete mode 100644 module/pom.xml delete mode 100644 module/src/main/java/com/iluwatar/module/App.java delete mode 100644 module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java delete mode 100644 module/src/main/java/com/iluwatar/module/FileLoggerModule.java delete mode 100644 module/src/main/resources/log4j.xml delete mode 100644 module/src/test/java/com/iluwatar/module/AppTest.java delete mode 100644 module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java delete mode 100644 monad/README.md delete mode 100644 monad/etc/monad.png delete mode 100644 monad/etc/monad.ucls delete mode 100644 monad/etc/monad.urm.puml delete mode 100644 monad/pom.xml delete mode 100644 monad/src/main/java/com/iluwatar/monad/App.java delete mode 100644 monad/src/main/java/com/iluwatar/monad/Sex.java delete mode 100644 monad/src/main/java/com/iluwatar/monad/User.java delete mode 100644 monad/src/main/java/com/iluwatar/monad/Validator.java delete mode 100644 monad/src/test/java/com/iluwatar/monad/AppTest.java delete mode 100644 monad/src/test/java/com/iluwatar/monad/MonadTest.java delete mode 100644 monostate/README.md delete mode 100644 monostate/etc/MonoState.ucls delete mode 100644 monostate/etc/monostate.png delete mode 100644 monostate/etc/monostate.urm.puml delete mode 100644 monostate/pom.xml delete mode 100644 monostate/src/main/java/com/iluwatar/monostate/App.java delete mode 100644 monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java delete mode 100644 monostate/src/main/java/com/iluwatar/monostate/Request.java delete mode 100644 monostate/src/main/java/com/iluwatar/monostate/Server.java delete mode 100644 monostate/src/test/java/com/iluwatar/monostate/AppTest.java delete mode 100644 monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java delete mode 100644 multiton/README.md delete mode 100644 multiton/etc/multiton.png delete mode 100644 multiton/etc/multiton.ucls delete mode 100644 multiton/etc/multiton.urm.puml delete mode 100644 multiton/pom.xml delete mode 100644 multiton/src/main/java/com/iluwatar/multiton/App.java delete mode 100644 multiton/src/main/java/com/iluwatar/multiton/Nazgul.java delete mode 100644 multiton/src/main/java/com/iluwatar/multiton/NazgulName.java delete mode 100644 multiton/src/test/java/com/iluwatar/multiton/AppTest.java delete mode 100644 multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java delete mode 100644 mute-idiom/README.md delete mode 100644 mute-idiom/etc/mute-idiom.png delete mode 100644 mute-idiom/etc/mute-idiom.ucls delete mode 100644 mute-idiom/etc/mute-idiom.urm.puml delete mode 100644 mute-idiom/pom.xml delete mode 100644 mute-idiom/src/main/java/com/iluwatar/mute/App.java delete mode 100644 mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java delete mode 100644 mute-idiom/src/main/java/com/iluwatar/mute/Mute.java delete mode 100644 mute-idiom/src/main/java/com/iluwatar/mute/Resource.java delete mode 100644 mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java delete mode 100644 mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java delete mode 100644 mutex/README.md delete mode 100644 mutex/etc/mutex.png delete mode 100644 mutex/etc/mutex.urm.puml delete mode 100644 mutex/pom.xml delete mode 100644 mutex/src/main/java/com/iluwatar/mutex/App.java delete mode 100644 mutex/src/main/java/com/iluwatar/mutex/Jar.java delete mode 100644 mutex/src/main/java/com/iluwatar/mutex/Lock.java delete mode 100644 mutex/src/main/java/com/iluwatar/mutex/Mutex.java delete mode 100644 mutex/src/main/java/com/iluwatar/mutex/Thief.java delete mode 100644 mutex/src/test/java/com/iluwatar/mutex/AppTest.java delete mode 100644 mutex/src/test/java/com/iluwatar/mutex/JarTest.java delete mode 100644 mutex/src/test/java/com/iluwatar/mutex/MutexTest.java delete mode 100644 naked-objects/.gitattributes delete mode 100644 naked-objects/.gitignore delete mode 100644 naked-objects/README delete mode 100644 naked-objects/README.md delete mode 100644 naked-objects/dom/pom.xml delete mode 100644 naked-objects/dom/src/main/java/META-INF/persistence.xml delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.java delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.layout.json delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.png delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.java delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.layout.json delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.png delete mode 100644 naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java delete mode 100644 naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectTest.java delete mode 100644 naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectsTest.java delete mode 100644 naked-objects/etc/naked-objects-dom.urm.puml delete mode 100644 naked-objects/etc/naked-objects-fixture.urm.puml delete mode 100644 naked-objects/etc/naked-objects-integtests.urm.puml delete mode 100644 naked-objects/etc/naked-objects.png delete mode 100644 naked-objects/etc/naked-objects.ucls delete mode 100644 naked-objects/fixture/pom.xml delete mode 100644 naked-objects/fixture/src/main/java/domainapp/fixture/DomainAppFixturesProvider.java delete mode 100644 naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java delete mode 100644 naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectsTearDown.java delete mode 100644 naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java delete mode 100644 naked-objects/integtests/.gitignore delete mode 100644 naked-objects/integtests/pom.xml delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/specglue/BootstrappingGlue.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/specglue/CatalogOfFixturesGlue.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/specs/RunSpecs.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/specs/modules/simple/SimpleObjectSpec_listAllAndCreate.feature delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java delete mode 100644 naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java delete mode 100644 naked-objects/pom.xml delete mode 100644 naked-objects/webapp/ide/eclipse/launch/.gitignore delete mode 100644 naked-objects/webapp/ide/intellij/launch/README.txt delete mode 100644 naked-objects/webapp/ide/intellij/launch/SimpleApp_PROTOTYPE.xml delete mode 100644 naked-objects/webapp/ide/intellij/launch/SimpleApp__enhance_only_.xml delete mode 100644 naked-objects/webapp/lib/.gitignore delete mode 100644 naked-objects/webapp/pom.xml delete mode 100644 naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java delete mode 100644 naked-objects/webapp/src/main/jettyconsole/isis-banner.pdn delete mode 100644 naked-objects/webapp/src/main/jettyconsole/isis-banner.png delete mode 100644 naked-objects/webapp/src/main/resources/domainapp/webapp/welcome.html delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/isis.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/persistor.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/persistor_datanucleus.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/shiro.ini delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/translations-en.po delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/translations-es.po delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/translations-nl.po delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/translations.po delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/viewer_restfulobjects.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/viewer_wicket.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/web.xml delete mode 100644 naked-objects/webapp/src/main/webapp/about/images/isis-logo.png delete mode 100644 naked-objects/webapp/src/main/webapp/about/index.html delete mode 100644 naked-objects/webapp/src/main/webapp/css/application.css delete mode 100644 naked-objects/webapp/src/main/webapp/images/spinning-icon.gif delete mode 100644 naked-objects/webapp/src/main/webapp/scripts/application.js delete mode 100644 null-object/README.md delete mode 100644 null-object/etc/null-object.png delete mode 100644 null-object/etc/null-object.ucls delete mode 100644 null-object/etc/null-object.urm.puml delete mode 100644 null-object/pom.xml delete mode 100644 null-object/src/main/java/com/iluwatar/nullobject/App.java delete mode 100644 null-object/src/main/java/com/iluwatar/nullobject/Node.java delete mode 100644 null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java delete mode 100644 null-object/src/main/java/com/iluwatar/nullobject/NullNode.java delete mode 100644 null-object/src/test/java/com/iluwatar/nullobject/AppTest.java delete mode 100644 null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java delete mode 100644 null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java delete mode 100644 object-mother/README.md delete mode 100644 object-mother/etc/object-mother.png delete mode 100644 object-mother/etc/object-mother.ucls delete mode 100644 object-mother/etc/object-mother.urm.puml delete mode 100644 object-mother/pom.xml delete mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/King.java delete mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/Queen.java delete mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java delete mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java delete mode 100644 object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java delete mode 100644 object-pool/README.md delete mode 100644 object-pool/etc/object-pool.png delete mode 100644 object-pool/etc/object-pool.ucls delete mode 100644 object-pool/etc/object-pool.urm.puml delete mode 100644 object-pool/pom.xml delete mode 100644 object-pool/src/main/java/com/iluwatar/object/pool/App.java delete mode 100644 object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java delete mode 100644 object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java delete mode 100644 object-pool/src/main/java/com/iluwatar/object/pool/OliphauntPool.java delete mode 100644 object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java delete mode 100644 object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java delete mode 100644 page-object/README.md delete mode 100644 page-object/etc/page-object.png delete mode 100644 page-object/etc/page-object.ucls delete mode 100644 page-object/etc/page-object.urm.puml delete mode 100644 page-object/pom.xml delete mode 100644 page-object/src/main/java/com/iluwatar/pageobject/App.java delete mode 100644 page-object/src/main/resources/sample-ui/album-list.html delete mode 100644 page-object/src/main/resources/sample-ui/album-page.html delete mode 100644 page-object/src/main/resources/sample-ui/css/album-list.css delete mode 100644 page-object/src/main/resources/sample-ui/css/style.css delete mode 100644 page-object/src/main/resources/sample-ui/login.html delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/LoginPageTest.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumListPage.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumPage.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/pages/LoginPage.java delete mode 100644 page-object/src/test/java/com/iluwatar/pageobject/pages/Page.java delete mode 100644 partial-response/README.md delete mode 100644 partial-response/etc/partial-response.ucls delete mode 100644 partial-response/etc/partial-response.urm.png delete mode 100644 partial-response/etc/partial-response.urm.puml delete mode 100644 partial-response/pom.xml delete mode 100644 partial-response/src/main/java/com/iluwatar/partialresponse/App.java delete mode 100644 partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java delete mode 100644 partial-response/src/main/java/com/iluwatar/partialresponse/Video.java delete mode 100644 partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java delete mode 100644 partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java delete mode 100644 partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java delete mode 100644 partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java delete mode 100644 poison-pill/README.md delete mode 100644 poison-pill/etc/poison-pill.png delete mode 100644 poison-pill/etc/poison-pill.ucls delete mode 100644 poison-pill/etc/poison-pill.urm.puml delete mode 100644 poison-pill/pom.xml delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/App.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java delete mode 100644 poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/AppTest.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java delete mode 100644 pom.xml delete mode 100644 private-class-data/README.md delete mode 100644 private-class-data/etc/private-class-data.png delete mode 100644 private-class-data/etc/private-class-data.ucls delete mode 100644 private-class-data/etc/private-class-data.urm.puml delete mode 100644 private-class-data/pom.xml delete mode 100644 private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java delete mode 100644 private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java delete mode 100644 private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java delete mode 100644 private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java delete mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/AppTest.java delete mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java delete mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java delete mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java delete mode 100644 producer-consumer/README.md delete mode 100644 producer-consumer/etc/producer-consumer.png delete mode 100644 producer-consumer/etc/producer-consumer.ucls delete mode 100644 producer-consumer/etc/producer-consumer.urm.puml delete mode 100644 producer-consumer/pom.xml delete mode 100644 producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java delete mode 100644 producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java delete mode 100644 producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java delete mode 100644 producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java delete mode 100644 producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java delete mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/AppTest.java delete mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java delete mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java delete mode 100644 promise/README.md delete mode 100644 promise/etc/promise.png delete mode 100644 promise/etc/promise.ucls delete mode 100644 promise/etc/promise.urm.puml delete mode 100644 promise/pom.xml delete mode 100644 promise/src/main/java/com/iluwatar/promise/App.java delete mode 100644 promise/src/main/java/com/iluwatar/promise/Promise.java delete mode 100644 promise/src/main/java/com/iluwatar/promise/PromiseSupport.java delete mode 100644 promise/src/main/java/com/iluwatar/promise/Utility.java delete mode 100644 promise/src/test/java/com/iluwatar/promise/AppTest.java delete mode 100644 promise/src/test/java/com/iluwatar/promise/PromiseTest.java delete mode 100644 property/README.md delete mode 100644 property/etc/property.png delete mode 100644 property/etc/property.ucls delete mode 100644 property/etc/property.urm.puml delete mode 100644 property/pom.xml delete mode 100644 property/src/main/java/com/iluwatar/property/App.java delete mode 100644 property/src/main/java/com/iluwatar/property/Character.java delete mode 100644 property/src/main/java/com/iluwatar/property/Prototype.java delete mode 100644 property/src/main/java/com/iluwatar/property/Stats.java delete mode 100644 property/src/test/java/com/iluwatar/property/AppTest.java delete mode 100644 property/src/test/java/com/iluwatar/property/CharacterTest.java delete mode 100644 prototype/README.md delete mode 100644 prototype/pom.xml delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/App.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/Beast.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/ElfMage.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/Mage.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/OrcMage.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/Prototype.java delete mode 100644 prototype/src/main/java/com/iluwatar/prototype/Warlord.java delete mode 100644 prototype/src/test/java/com/iluwatar/prototype/AppTest.java delete mode 100644 prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java delete mode 100644 prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java delete mode 100644 proxy/README.md delete mode 100644 proxy/etc/presentation.html delete mode 100644 proxy/etc/proxy-concept.png delete mode 100644 proxy/etc/proxy-concept.xml delete mode 100644 proxy/pom.xml delete mode 100644 proxy/src/main/java/com/iluwatar/proxy/App.java delete mode 100644 proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java delete mode 100644 proxy/src/main/java/com/iluwatar/proxy/Wizard.java delete mode 100644 proxy/src/main/java/com/iluwatar/proxy/WizardTower.java delete mode 100644 proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/AppTest.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/IvoryTowerTest.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/WizardTest.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java delete mode 100644 publish-subscribe/.gitignore delete mode 100644 publish-subscribe/README.md delete mode 100644 publish-subscribe/etc/publish-subscribe.png delete mode 100644 publish-subscribe/etc/publish-subscribe.ucls delete mode 100644 publish-subscribe/etc/publish-subscribe.urm.puml delete mode 100644 publish-subscribe/pom.xml delete mode 100644 publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java delete mode 100644 publish-subscribe/src/main/resources/logback.xml delete mode 100644 publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java delete mode 100644 queue-load-leveling/README.md delete mode 100644 queue-load-leveling/etc/queue-load-leveling.gif delete mode 100644 queue-load-leveling/etc/queue-load-leveling.ucls delete mode 100644 queue-load-leveling/etc/queue-load-leveling.urm.puml delete mode 100644 queue-load-leveling/pom.xml delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/App.java delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Message.java delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/MessageQueue.java delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/ServiceExecutor.java delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Task.java delete mode 100644 queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/TaskGenerator.java delete mode 100644 queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/AppTest.java delete mode 100644 queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageQueueTest.java delete mode 100644 queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageTest.java delete mode 100644 queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/TaskGenSrvExeTest.java delete mode 100644 reactor/README.md delete mode 100644 reactor/etc/reactor.png delete mode 100644 reactor/etc/reactor.ucls delete mode 100644 reactor/etc/reactor.urm.puml delete mode 100644 reactor/pom.xml delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/app/App.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java delete mode 100644 reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java delete mode 100644 reactor/src/test/java/com/iluwatar/reactor/app/ReactorTest.java delete mode 100644 reader-writer-lock/README.md delete mode 100644 reader-writer-lock/etc/reader-writer-lock.png delete mode 100644 reader-writer-lock/etc/reader-writer-lock.ucls delete mode 100644 reader-writer-lock/etc/reader-writer-lock.urm.puml delete mode 100644 reader-writer-lock/pom.xml delete mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java delete mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java delete mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java delete mode 100644 reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.java delete mode 100644 repository/README.md delete mode 100644 repository/etc/repository.png delete mode 100644 repository/etc/repository.ucls delete mode 100644 repository/etc/repository.urm.puml delete mode 100644 repository/pom.xml delete mode 100644 repository/src/main/java/com/iluwatar/repository/App.java delete mode 100644 repository/src/main/java/com/iluwatar/repository/AppConfig.java delete mode 100644 repository/src/main/java/com/iluwatar/repository/Person.java delete mode 100644 repository/src/main/java/com/iluwatar/repository/PersonRepository.java delete mode 100644 repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java delete mode 100644 repository/src/main/resources/META-INF/persistence.xml delete mode 100644 repository/src/main/resources/applicationContext.xml delete mode 100644 repository/src/main/resources/logback.xml delete mode 100644 repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java delete mode 100644 repository/src/test/java/com/iluwatar/repository/AppConfigTest.java delete mode 100644 repository/src/test/java/com/iluwatar/repository/AppTest.java delete mode 100644 repository/src/test/java/com/iluwatar/repository/RepositoryTest.java delete mode 100644 resource-acquisition-is-initialization/README.md delete mode 100644 resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.png delete mode 100644 resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.ucls delete mode 100644 resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml delete mode 100644 resource-acquisition-is-initialization/pom.xml delete mode 100644 resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java delete mode 100644 resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java delete mode 100644 resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java delete mode 100644 resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/AppTest.java delete mode 100644 resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java delete mode 100644 semaphore/README.md delete mode 100644 semaphore/etc/semaphore.png delete mode 100644 semaphore/etc/semaphore.urm.puml delete mode 100644 semaphore/pom.xml delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/App.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Customer.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Lock.java delete mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java delete mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java delete mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java delete mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java delete mode 100644 servant/README.md delete mode 100644 servant/etc/servant-pattern.png delete mode 100644 servant/etc/servant-pattern.ucls delete mode 100644 servant/etc/servant.urm.puml delete mode 100644 servant/pom.xml delete mode 100644 servant/src/etc/servant.jpg delete mode 100644 servant/src/etc/servant.svg delete mode 100644 servant/src/etc/servant.xml delete mode 100644 servant/src/main/java/com/iluwatar/servant/App.java delete mode 100644 servant/src/main/java/com/iluwatar/servant/King.java delete mode 100644 servant/src/main/java/com/iluwatar/servant/Queen.java delete mode 100644 servant/src/main/java/com/iluwatar/servant/Royalty.java delete mode 100644 servant/src/main/java/com/iluwatar/servant/Servant.java delete mode 100644 servant/src/test/java/com/iluwatar/servant/AppTest.java delete mode 100644 servant/src/test/java/com/iluwatar/servant/KingTest.java delete mode 100644 servant/src/test/java/com/iluwatar/servant/QueenTest.java delete mode 100644 servant/src/test/java/com/iluwatar/servant/ServantTest.java delete mode 100644 service-layer/README.md delete mode 100644 service-layer/bin/pom.xml delete mode 100644 service-layer/etc/service-layer.png delete mode 100644 service-layer/etc/service-layer.ucls delete mode 100644 service-layer/etc/service-layer.urm.puml delete mode 100644 service-layer/pom.xml delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/common/Dao.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicService.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spell/Spell.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDao.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDao.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/wizard/Wizard.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDao.java delete mode 100644 service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java delete mode 100644 service-layer/src/main/resources/logback.xml delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java delete mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java delete mode 100644 service-locator/README.md delete mode 100644 service-locator/etc/service-locator.png delete mode 100644 service-locator/etc/service-locator.ucls delete mode 100644 service-locator/etc/service-locator.urm.puml delete mode 100644 service-locator/pom.xml delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/App.java delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/Service.java delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java delete mode 100644 service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java delete mode 100644 service-locator/src/test/java/com/iluwatar/servicelocator/AppTest.java delete mode 100644 service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java delete mode 100644 specification/README.md delete mode 100644 specification/etc/specification.png delete mode 100644 specification/etc/specification.ucls delete mode 100644 specification/etc/specification.urm.puml delete mode 100644 specification/pom.xml delete mode 100644 specification/src/main/java/com/iluwatar/specification/app/App.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Creature.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Dragon.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Goblin.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Octopus.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Shark.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/creature/Troll.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/property/Color.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/property/Movement.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/property/Size.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java delete mode 100644 specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java delete mode 100644 specification/src/test/java/com/iluwatar/specification/app/AppTest.java delete mode 100644 specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java delete mode 100644 specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java delete mode 100644 specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java delete mode 100644 specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java delete mode 100644 state/README.md delete mode 100644 state/etc/state.png delete mode 100644 state/etc/state.ucls delete mode 100644 state/etc/state.urm.puml delete mode 100644 state/etc/state_1.png delete mode 100644 state/pom.xml delete mode 100644 state/src/main/java/com/iluwatar/state/AngryState.java delete mode 100644 state/src/main/java/com/iluwatar/state/App.java delete mode 100644 state/src/main/java/com/iluwatar/state/Mammoth.java delete mode 100644 state/src/main/java/com/iluwatar/state/PeacefulState.java delete mode 100644 state/src/main/java/com/iluwatar/state/State.java delete mode 100644 state/src/test/java/com/iluwatar/state/AppTest.java delete mode 100644 state/src/test/java/com/iluwatar/state/MammothTest.java delete mode 100644 step-builder/README.md delete mode 100644 step-builder/etc/step-builder.png delete mode 100644 step-builder/etc/step-builder.ucls delete mode 100644 step-builder/etc/step-builder.urm.puml delete mode 100644 step-builder/pom.xml delete mode 100644 step-builder/src/main/java/com/iluwatar/stepbuilder/App.java delete mode 100644 step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java delete mode 100644 step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java delete mode 100644 step-builder/src/test/java/com/iluwatar/stepbuilder/AppTest.java delete mode 100644 step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java delete mode 100644 template-method/README.md delete mode 100644 template-method/etc/template-method.png delete mode 100644 template-method/etc/template-method.ucls delete mode 100644 template-method/etc/template-method.urm.puml delete mode 100644 template-method/etc/template-method_1.png delete mode 100644 template-method/pom.xml delete mode 100644 template-method/src/main/java/com/iluwatar/templatemethod/App.java delete mode 100644 template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java delete mode 100644 template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java delete mode 100644 template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java delete mode 100644 template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java delete mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/AppTest.java delete mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java delete mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java delete mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java delete mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java delete mode 100644 thread-pool/README.md delete mode 100644 thread-pool/etc/thread-pool.png delete mode 100644 thread-pool/etc/thread-pool.ucls delete mode 100644 thread-pool/etc/thread-pool.urm.puml delete mode 100644 thread-pool/pom.xml delete mode 100644 thread-pool/src/main/java/com/iluwatar/threadpool/App.java delete mode 100644 thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java delete mode 100644 thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java delete mode 100644 thread-pool/src/main/java/com/iluwatar/threadpool/Task.java delete mode 100644 thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java delete mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/AppTest.java delete mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java delete mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java delete mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java delete mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java delete mode 100644 throttling/README.md delete mode 100644 throttling/etc/throttling-pattern.png delete mode 100644 throttling/etc/throttling.urm.puml delete mode 100644 throttling/pom.xml delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/App.java delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/B2BService.java delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/CallsCount.java delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/Tenant.java delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java delete mode 100644 throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java delete mode 100644 throttling/src/test/java/com/iluwatar/throttling/AppTest.java delete mode 100644 throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java delete mode 100644 throttling/src/test/java/com/iluwatar/throttling/TenantTest.java delete mode 100644 tls/README.md delete mode 100644 tls/etc/tls.png delete mode 100644 tls/etc/tls.ucls delete mode 100644 tls/etc/tls.urm.puml delete mode 100644 tls/pom.xml delete mode 100644 tls/src/main/java/com/iluwatar/tls/App.java delete mode 100644 tls/src/main/java/com/iluwatar/tls/DateFormatCallable.java delete mode 100644 tls/src/main/java/com/iluwatar/tls/Result.java delete mode 100644 tls/src/test/java/com/iluwatar/tls/AppTest.java delete mode 100644 tls/src/test/java/com/iluwatar/tls/DateFormatCallableTest.java delete mode 100644 tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestIncorrectDateFormat.java delete mode 100644 tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestMultiThread.java delete mode 100644 tolerant-reader/README.md delete mode 100644 tolerant-reader/etc/tolerant-reader.png delete mode 100644 tolerant-reader/etc/tolerant-reader.ucls delete mode 100644 tolerant-reader/etc/tolerant-reader.urm.puml delete mode 100644 tolerant-reader/pom.xml delete mode 100644 tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java delete mode 100644 tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java delete mode 100644 tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java delete mode 100644 tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java delete mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/AppTest.java delete mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java delete mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java delete mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java delete mode 100644 twin/.gitignore delete mode 100644 twin/README.md delete mode 100644 twin/etc/twin.png delete mode 100644 twin/etc/twin.ucls delete mode 100644 twin/etc/twin.urm.puml delete mode 100644 twin/pom.xml delete mode 100644 twin/src/main/java/com/iluwatar/twin/App.java delete mode 100644 twin/src/main/java/com/iluwatar/twin/BallItem.java delete mode 100644 twin/src/main/java/com/iluwatar/twin/BallThread.java delete mode 100644 twin/src/main/java/com/iluwatar/twin/GameItem.java delete mode 100644 twin/src/test/java/com/iluwatar/twin/AppTest.java delete mode 100644 twin/src/test/java/com/iluwatar/twin/BallItemTest.java delete mode 100644 twin/src/test/java/com/iluwatar/twin/BallThreadTest.java delete mode 100644 update-ghpages.sh delete mode 100644 value-object/README.md delete mode 100644 value-object/etc/value-object.png delete mode 100644 value-object/etc/value-object.ucls delete mode 100644 value-object/etc/value-object.urm.puml delete mode 100644 value-object/pom.xml delete mode 100644 value-object/src/main/java/com/iluwatar/value/object/App.java delete mode 100644 value-object/src/main/java/com/iluwatar/value/object/HeroStat.java delete mode 100644 value-object/src/test/java/com/iluwatar/value/object/AppTest.java delete mode 100644 value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java delete mode 100644 visitor/README.md delete mode 100644 visitor/etc/visitor.png delete mode 100644 visitor/etc/visitor.ucls delete mode 100644 visitor/etc/visitor.urm.puml delete mode 100644 visitor/etc/visitor_1.png delete mode 100644 visitor/pom.xml delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/App.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/Commander.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/Sergeant.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/Soldier.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/Unit.java delete mode 100644 visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/AppTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/UnitTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a2aaf764ba8c..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: java -jdk: -- oraclejdk8 - -env: - global: - - GH_REF: github.com/iluwatar/java-design-patterns.git - - secure: LxTDuNS/rBWIvKkaEqr79ImZAe48mCdoYCF41coxNXgNoippo4GIBArknqtv+XvdkiuRZ1yGyj6pn8GU33c/yn+krddTUkVCwTbVatbalW5jhQjDbHYym/JcxaK9ZS/3JTeGcWrBgiPqHEEDhCf26vPZsXoMSeVCEORVKTp1BSg= - - secure: "eoWlW9GyTJY04P8K3pxayXwU9/hmptQg/LfirispQkV9YvmziCfSzXnatnBhNfud98sCzY8BScXnb+OWLTnjLKpId4rtEqb0aJ40Jc32cUKzgzFAUn7cNcDAbUIfyPAGVqyQqfj/11wYSADwWMMOPlW97ExUtoyiH2WenXuRHso=" - -before_install: -- export DISPLAY=:99.0 -- sh -e /etc/init.d/xvfb start - -# default install command is just "mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V" -install: -- mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V -e - -after_success: -- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar -Dsonar.host.url=https://sonarqube.com -Dsonar.login=$SONAR_TOKEN -- bash update-ghpages.sh - -# use latest java version available instead of travis default -addons: - apt: - packages: - - oracle-java8-installer - -notifications: - email: - - iluwatar@gmail.com - webhooks: - urls: - - https://webhooks.gitter.im/e/3319623945358a093a6f - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always - -sudo: required \ No newline at end of file diff --git a/CODE_COVERAGE.md b/CODE_COVERAGE.md deleted file mode 100644 index 589c7ad7934c..000000000000 --- a/CODE_COVERAGE.md +++ /dev/null @@ -1,13 +0,0 @@ -# Code Coverage Report generation - -To generate the code coverage report, execute the following command: -> mvn clean verify - -This will generate code coverage report in each of the modules. In order to view the same, open the following file in your browser. -> target/site/jacoco/index.html - -Please note that the above folder is created under each of the modules. For example: -* adapter/target/site/jacoco/index.html -* busniess-delegate/target/site/jacoco/index.html - - diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD deleted file mode 100644 index 39087fbf12d3..000000000000 --- a/CONTRIBUTING.MD +++ /dev/null @@ -1,4 +0,0 @@ -This is great you have something to contribute! - -Before going any further please read the [wiki](https://github.com/iluwatar/java-design-patterns/wiki) -with conventions and rules we used for this project. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index e73cf6618a69..000000000000 --- a/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2016 Ilkka Seppälä - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 6eed9561b551..000000000000 --- a/README.md +++ /dev/null @@ -1,47 +0,0 @@ - - -# Design patterns implemented in Java - -[![Build status](https://travis-ci.org/iluwatar/java-design-patterns.svg?branch=master)](https://travis-ci.org/iluwatar/java-design-patterns) -[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md) -[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Quality Gate](https://sonarqube.com/api/badges/gate?key=com.iluwatar%3Ajava-design-patterns)](https://sonarqube.com/dashboard/index/com.iluwatar%3Ajava-design-patterns) - -# Introduction - -Design patterns are formalized best practices that the programmer can use to -solve common problems when designing an application or system. - -Design patterns can speed up the development process by providing tested, proven -development paradigms. - -Reusing design patterns helps to prevent subtle issues that can cause major -problems, and it also improves code readability for coders and architects who -are familiar with the patterns. - -# Getting started - -Before you dive into the material, you should be familiar with various -Programming/Software Design Principles. - -All designs should be as simple as possible. You should start with KISS, YAGNI, -and Do The Simplest Thing That Could Possibly Work principles. Complexity and -patterns should only be introduced when they are needed for practical -extensibility. - -Once you are familiar with these concepts you can start drilling down into -patterns by any of the following approaches - - - Using difficulty tags, `Difficulty-Beginner`, `Difficulty-Intermediate` & `Difficulty-Expert`. - - Using pattern categories, `Creational`, `Behavioral` and others. - - Search for a specific pattern. Can't find one? Please report a new pattern [here](https://github.com/iluwatar/java-design-patterns/issues). - -# How to contribute - -If you are willing to contribute to the project you will find the relevant information in our [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). We will help you and answer your questions in the [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns). - -# License - -This project is licensed under the terms of the MIT license. diff --git a/_scripts/postPumlsToServer.py b/_scripts/postPumlsToServer.py deleted file mode 100644 index 107ea19883db..000000000000 --- a/_scripts/postPumlsToServer.py +++ /dev/null @@ -1,67 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -import requests, glob, re, os - -# taken from here: http://stackoverflow.com/a/13641746 -def replace(file, pattern, subst): - # Read contents from file as a single string - file_handle = open(file, 'r') - file_string = file_handle.read() - file_handle.close() - - # Use RE package to allow for replacement (also allowing for (multiline) REGEX) - file_string = (re.sub(pattern, subst, file_string)) - - # Write contents to file. - # Using mode 'w' truncates the file. - file_handle = open(file, 'w') - file_handle.write(file_string) - file_handle.close() - -# list of all puml files -fileList = glob.glob('*/etc/*.puml') -for puml in fileList: - pathSplit = puml.split("/") - # parent folder - parent = pathSplit[0] - # individual artifact/project name - artifact = pathSplit[2].replace(".urm.puml", "") - print "parent: " + parent + "; artifact: " + artifact - - # do a POST to the official plantuml hosting site with a little trick "!includeurl" and raw github content - data = { - 'text': "!includeurl https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/" + puml - } - r = requests.post('http://plantuml.com/plantuml/uml', data=data) - pumlId = r.url.replace("http://plantuml.com/plantuml/uml/", "") - - # the only thing needed to get a png/svg/ascii from the server back - print "Puml Server ID: " + pumlId - - # add the id so jekyll/liquid can use it - if (parent == artifact): - replace("./" + parent + "/README.md", "categories:", "pumlid: {}\\ncategories:".format(pumlId)) - else: - print "I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file '" + puml + "'\npumlid: {}".format(pumlId) - diff --git a/abstract-document/README.md b/abstract-document/README.md deleted file mode 100644 index c8755ce078a0..000000000000 --- a/abstract-document/README.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: pattern -title: Abstract Document -folder: abstract-document -permalink: /patterns/abstract-document/ -pumlid: PSjB3eCm34NHhPG599vtDyQn85L-ifzX-p3lxEf8Twj3MXGDQvyJMFubChxpKN767gucSq07iinEjSNDOACVNvoAUZr6MWoe3QVE_WRnxZ0Mf38b-hkIGlurX_MyehS7 -categories: Structural -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Achieve flexibility of untyped languages and keep the type-safety - -![alt text](./etc/abstract-document-base.png "Abstract Document Base") - -![alt text](./etc/abstract-document.png "Abstract Document Traits and Domain") - - -## Applicability -Use the Abstract Document Pattern when - -* there is a need to add new properties on the fly -* you want a flexible way to organize domain in tree like structure -* you want more loosely coupled system - - -## Credits - -* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern) -* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf) \ No newline at end of file diff --git a/abstract-document/etc/abstract-document-base.png b/abstract-document/etc/abstract-document-base.png deleted file mode 100644 index 13345dbb862c12463c352af53dafb7f3ee42bf37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14973 zcmbumbzGEhvp=qgC<{m}B?w42D6(`T-QBpPbV`TB64H${QUcQ5vUDrmh?Gc3cYN=K z&+|Oze9rlv=X`&^KiC)SeP1(k%{4RE%zK6qMR^Gf&{NR8d-pJ;B*m2P-Mc>t{4_mA z0={`L?uvQu9*>xmn6RpA>UNs#7m{(W6OF=ioL<&_q}OuGF|SVLLe!FVHR8kKYsy~q z8HKJr55yRP@t{5z)8!Pkvw3mKLj`H;xKx^Oo-)j&l7Ak_`r{SNOV>lJwoY@ZQM#B> ztX&%G=fVoBQJmi00%q5#H|qmCTSKYSj>i|{8XAp`!>Rm^rfZe0+?9^r#rKhgvBpxh zO6;x+U-j2B;Bxh=ULuIEVt92fjrIwVV3GZ2}xIo`k}$I-Nbr4dkr* zo1F!mNju{;c6^1Qocl+*{zdF`R!)9DNLu`D#*#OWgrT4D2QTZ7Us8~^(lNomSBXuz zT`iEzm(OomH`elH-t_4+n$)fOXD%Hh5_QuzssOTn!cP zP)Xy@Vw+|}9Ub8})_IBLOu86q-0Ey-jyk>Bm!4;mgi3+OQu*|-+7)_%v+(AOS5)hz z9AfqFq3XF{*JSR=yf}DodK9mcf#FnkoPF4sz1UKJ#Dik=MQaFX)3UtQz1p2xihb(7 zvEEAz#KOWMj-_9(J4OfUA-Q1E^&avInnmivr$IYxeodYVg#C0!za#>!i?eta)+rwp zDyY0GdH&P z`vq$ZOTe2Rb0s-PQl#2}q# z7h9U|CMDl(-rLi$;ccK~ck|lViHu$iueAmN6qQ`ppBkoBq~n2b$F9#x7!xA4J%7j3 z8l0M3j%*52_>gJ2y`3!A`*Snm{;cCtB6#$?Np2oNyvz}!e26d|6%<=)=wR%5_RE^q z$6kc{QTjzB+4b^h=n5TnOUbBKa?aVOxO^{DcxD+f%&8?(Y{QQ|p2Y!20b0{#B-o^*k~5oCGNXWW z^B7)kZBq7sF!O`2$hdAlOZ+4Fk%UapeS3_W_vU!m=7!jC|K~_BE(dcqr^ZRJiUvX#4#eguas;i&ej{8;coAe!-oQ;=~2hObP=m z7iJnawhvlqbx!7n4NfnkJ8k(gNLX3{>E1P`l>8oAyqwQ%YBJH)%&9zQe)jEt8(@J- zZ0p(uni8$NvoTto3xXRvSOP`AdfxxWrAYs|Ux~k`NjKpBF||r5 zQ6zRGmPs}xo$p?{fZ^wwDQW0_t!OaT36D~o9YorcK+n|i*NOs*>D4DD1sw|OkYb_p z5Ruq~3$H9~by*#~Ib-$oaa@VBO95#ONlSAu#2IW$Oqo3vKH)zyfpW0JW|MiYHGzn+ z!LC?)==o(1AG)y9P+rMgQDsW}4#uWSZP`9{pXZW>h|b6#U)IfRFo(nhwrj9Nt>+s` zprnxm92x0HRyBy{Hu23Ke|bNGw}!zPt*6V9N5oO4lWk{Dyw%t~CRn3~0^(H#?m~)m zoN_kq;n~pgW?u1pyBf6()8W^>>6DAH(_x=Hm3hkz##W!gj*xyvXIY0zLoKg1XioY` ziKeyty0m#L9yj)r5#djyK(N5+NY8%?cd#SD&d|jZil`h_Ru;@oV<|lEC+~BJfK666 zR9pKTS|nh$+PUxT;;D=)`dA*hR$mgUo$HR$V75vtPsE@RIDxHG&23T1(tP^Lil~lX7zegQ^a`*{gj(Li%ccRNSuUw^Ktr1qagR z?gomo#nhgtvzOuRE+R4;z)b{D)-1h!f{L zD;uDTOg26mn8NV{R(|PGc_DHexMlwHYurS9UWFgYEsz{9m>zHsW`|IaI!x>uq(wM< zl6wB+XFB~J7g+xE;vzqoD7at*$&F>a$*y&Ad(>*=72nQ?VHzEGa86iR0cv;Un6I4? zAnw~w!4iCvn%cuip{v*@vf(l+ryXsfk8I~NE^1FQxSYzh15LW{2VDe1B2?fs2Fqbh zPS2}fsL*eX0EeW8zxQqO*v_nkIR{I8j-8)HV#$om^X5mmzyG9*L#zGnslN{c9=ozD zxjuhxTk!P%2!EkGZylsdAz;hjqn*9I0H{1^=+u#EbXPcHiNCqo-4^#=1U zTMMB%hEJ7oV@0VJH=S|_!Ra=4%Zx|}NU7)Ah&bg~_$ln2hJU;0|9MF^f1qD1>);Zx zqXeHjt~})gp0G)CSl_9pTXMHN+O7bQ*PYrlmcb2gKapka3T2+5{SuVeI6ZzIayL0Tq>mfLA2EXUK zOR70;OQjdfCdq4dyacdfgj)3J)t;o-k-CX*Ww1f^sI){VbrGMERMXx14TI zr)ygh?sTLdImC^_TtPdx%~4fF6u!af3pM-JoTShtJsTA-+k(y$T@iVZT{x<;_C}47 zz|=|YX_s`x1698F`>&1lvaHv}P z=eoQShR9)>Xn6NS`wqf<4)Kh8DP*Ewq?l6wi1*zKZOHA#P9<}6lRE1cnp$)MF?ttA zd3Hz5#2ttckK03t5$cP7&1bYeBQ!VaG^Y{)XK}DLE?s`Iapes+%p%z0FrHNJ6;`pc zZ_~6&HBoz*`(70!OZeo=jc}9OrRNCMJG$30Q!&acKhhUw& zdUg_*T^6cKd}eu^CQGlY`M@mJSvEK!>Fwp5GMMGmv_?tu%$p&vY&Gc~OmsvHJJMd) zHO}sly~6WSl5YN0IzGE7OG<;5xzLJo24A>4#yMx@w?Jc5vy=Y7&^)Dx5I@^BKP84) z&dQlLOFOwZ{hEPise@gJ6txq3nD8GWqP8v|sJLZc*;tWeluiEysdkFWPH zSq2Gw;iQjS_57tbc9+@#J^;U`YMEtZGp#;1aJUE{Js(y}Wiu|_R`_EWYG?{TeVoVp zl1rGatMn3wZYy?o*5k8~>*c(PFI*rb^$ozX-FA{(Z{;)j<1ST20TB3D)@(SPnwI!% z)=4yze&i#&SeTK^d{i*BODm3>Ec6>N5OJ;WbN!WpimB0a;|&6@D`9@f6#82 z2O$!SAK$wX(vRflk4?8#3$a~jYHFHuVkDpB@wxVFoR3(p1JsT87<{a=VnucTdtaY4 zpo%%v%5)SO#VL>Gv$Yh2P*)$Pzb7#3M38WgI5B4SA%lX*mw^;y_Uz1!PinQaXJ^zW zGFWT29hZ(II1Uy0apGi&UL&*}CAB==!p-fYXC;FmdiT{7`9n|;B_v}B-~ti%&A_{0 zgfDVMbkaJpS$cd%g87dCt4KX}gC{+Zcl+66Y-Y!y&mngZ7D>+WlZrJUSA;p5A(se*9Si`n1qKeC+#L)q9t-Hp@N@CtbC}Rw;?8b zt6yvLEZyN)WEyj~>AqatBoGaDVr7a=I&F+9_*3<(CELi2~WfxzkbCj_(Go!%VP z%qKHv;YV~OO%8QLe?8Jb=|gVg_Ixz|nPYO(AO4&W{6syoj4{;i6*IQb^q;}+iZv>))!74c!C!pI%V-(bkARncF<&D)VC(194!k z;0$+@)rO#2gR`%f2Hw^OT^BVmlR2B$dn*qD;48K>(Sw{gPiAjb6y$zV{^+r%t>XQNvloivZH5A-ycp3R<(F)Fm|_MhfX`iNZ%RP2AtOoE^J6aM7m z-Ox3`;D6Lc)`3N~`o8&2k4S(3FtIiR0r%NngH*+HX5xsRFBsA}!&tTJhxL@=U1SBq z>GaklmC_Zx47sQyc{m;MR`1GgH>&%?l1#e}D7;Da&(tS0XuZ8JuVXJFt_}PFKQ`%I91X7g;Rq@*E8WlryE*iHY@^H2462|p!B1HUb5PWM zk)0(bdw;_73B+FcF%NaQZV2IJg<+FOag*|M+R~b`G~}|gNh$3Iwkc)!H#C{LG?rR5 zPa#AI*Rb{JVz zBa&RAB_kiAl%PIWdHz}UW5P!@Ln0e|hThM#L#MGus;2^k+F84>tQx^$Et11GR(Rw^ zCGpmAyILat(Ck~oB1r0h`&65aT1%WnMVuei-?VJ)6ixh@mc5)R$W}-fsL4HnF&^7K zHwjP^+yB5NV?dmMrt$O8kDu(DqD(R3yNu4R`zW0MuFq)QJ);a=bQM4i_i?%2 z-gM{G8&7LJYn1uYw6B6Zq>gP(GqAS@BA!8Ua`IEak~O1-==N9|+?z?VttgR%5~W$d z*7iX0O%}f23r7G=65na^zrlcbw*MmrB-6LD%F(p{9d#+l(kkoK3>(;b=UW2%iA~oXS=MCNeKh+9+R9Xv9Mtm8_4C=S_)#eLr#c&AkhGq?!0I1<9lguW zwFF;O4|&Bvj*{QC@-7fG-6KUCV>4*(@^Jif0%rZ&mGKFS=Oiq54wXgo`Rd0|f9dZ9 zyQA6~J+HUK02~zyq&Cnx=i7iw+L^Dfb#~g80-0-Gr99D6cc%AtN+V!4j)#hcj>6p?N;u<)g3Yx6#OsnKTwY|F$WpJJ3^i z+G2eF2|b?;=D_<~3$t9q1ReBZX?qF;IFI$N>vHCB#27(A-EoF)6sY?=8NYqy-X!=W z>InBm?-j zu{BKp0`}W`X`HEq>V0qnI5{re_<2fes(de9XNWo|wl&QdCqtk11J00mZ`hx+an9lZ zalgL(Dr#j)>xUx>;N+^gKWO6>hBLo^(p2t$N$2V_YgcR#(U!?BE6;YFeM`_gAFMfL zaT^jo;1za7vzbSHeTv8P1%($jT05^_N-QDeO7}X^s_P}kfR$9-N)5Q@X|EBK$A}1R zC4R&Em$B&ndr|##YY%my4bVYgN)HQ5BF)X%GzMt)Hc)F;OI95lT4COk$hX6n$qW7% z8lzbqYl`|)7Z)UX+Mj3%oI#Qh?_zDVC^`J*Z%3zwy_(_}VZvjh0FM!kR%C$RqM2$Wi z2UrkCSFjil$@fcP)OL0gKt?$irU3^9w)*ItI)1oFFyJWIUGv z$idm9n>R*tAx^we*Mbm&K{?&l@17Lo7G-M3?bNpc_Kwr&o6D13JGF zR>{Z4#|wPI-;E7KGVQPcwW_^<`CLcK4fs2WQRs!>OAhVIkKrS6wumL$=t}mHCz3tR z%GG|*W>VvjjG-ch-&-&fBS7&{OgGS~!KO4Z`ZMwCP=0Bs0CB_lcV>=ZopWKS70dU@ zsnxO8-s&%Z8@|5K4Ppn9js)23_Iv8$%c~-+nlkanU{9>D<05A(-beU3J=1JI9h~|_I5WOtu zV5?csdZDGq?Vl-eIyvYlaU7N|Kk+hKh5y-?PVi82j+D=28`PPr;E0?QO|)}Pnc)M$ z(8Q@gJ44grRAVRy*dct~pSk?P?4cQe;}sc#Fzws)vd6ZL3CN6|ZS0T~J#YTa+Q8c_ zZm#uH|6sme0Mm9l7+DS_b%8(oZRLF0GX6`F&|2hG=O-Y#fj>j9J=ruU8kYiRlU&vV zYB(^kT}2RL8iEqJoAWOj4DIhmUiW9~J0+A#%T=l*!d44^nB?6L%9*iGiPs ze#9|$!GNueivgMTRQ&%Y*{ik~f5`mUFHe6()jAnJ9LVDlh-n!nfN=uV(%&*ewLrK( zCX4N5Y-elTuL#Vv(+mP)K{}{w9>OcW(>Ed5co_D4;77W=6rb=bxf; zj@n$aIbH3swDF7eMt@GU5QiVAd}?fqVShg3;KCxsK7dQSE)$q;Zlpj-FK@>pXDvXq z)>ZSek~ah9RWgYCdboNP_m#pNPl7>qg&Ws4sz6sstLr?~BgTq_cnCo41AXf5$%z6s zJC@4cORfE?mZY)ys45XDE!$qwQnP$AaGo>4+LQ_RoF>Mls>X;yl4IK{hJ5TRw4%)d zp`3wZ5sw&%Bx;fefAY2HX@W9m8C_ctJzCr@tLUQ&WHMz+1AIu%DDKIaP^qq@GpDH^ zrW+ZNUDI633a`03!g`QE8C8atc}oQT+N$>QOU# zd1Y+iOxo01>L7wx5=+*wg0%~6QxDOU1DJixJ~!G`1Gmc|yvx`{yH6>3s@JJ4%O!K6 z$Isa1bw~zt@6Om(?n8bndF~mF7Stcuh_fJuWq9pg`Ex#bqQBUC)z!9)d0n6!w$6ah z4kC6$nGJjvuNfwxmaw^F2qK{IR=50iK(VQn@vv7aZ+jC|l&^sr&?$0gw)oWw7bgl2 zz3?~o6KSgsP`(X6%I+)@NG$hgE06$0j6k@y~}>0e>hZhvB2%ceo}N1G4Bzr z8%Fyli@70lI8_C4L+fIK&hA%`TB84#x`-!g>)$F zwT$d5ZyS0LL73zeoz*t(D2@yhIw+9?I7g5;Rm6_g)zGHiTDHeRQ3BDK;Y3u$f;g0# z*UR3*S74Z-YsRW> zM0O0_m%@V6+!;-T(<_47b9LQ2MzLXMj|Hq397;9T&?rNF`n|geb^P)nUAJl9f2p|t zo}~S|7k=lL(c^V~U0lI-r_6ODoHBiyzNjWBpTUI`SbQg}Ex-378H?9pjO|b?fe|Tx zAJZexJVM)8iC>sM3LPiHf;AKgSr7#$p5m#|&1I(oKepFR{*BXa?nMvUzB;oC+meic zfv^$-h&5JXMNVx^k$`59NK)lY5)*^5f3)j8d>0Yq;=|#yK6Zb`CGgYvyn@fk-DL2k zJG;_Pzi+N!=c!_^74U|upvoLr_`!ES-@WcrR@8iPHt&+w#OUHlaQprtQJ+LAa@uS^ zu!i2Fqx6v*1JteMY$_=YIWP!OV?aQyW{cyTeC1_V8?3o4@t4%Ly&?sg*syJLrdJ*b zeDIg{Py7A)*6km`mVVzkRqeB@-zJX)t51StJTmkeE~csXe^xv=FwRmP;G%%a7(I`W zJWb*An=sEb6WC!2%LPYD5^6tbS4UVDaO4I+=lb+pJ|PQo zs$g&0$Zvm!P{|mA21XS2#u}X+t%1Ij#BB)kDRAx|H5m3T5Z5OJ#a(Sr5*E+}&bsYC z&iU{@1%WYqpy%sYrB~P6pU;btAXh`43qvGC*f1!eGa?oGdxG^p-~)fl=Z;jSv`R2$ z55PyO^Y5W9cUHjPUk!DwsatCzX4~om@(+g0-CbSc2P$whb5oM;dPtR)&J#E zo4PvVIvw*cdji3&2O;Hk?o5;}@f;EfnyzC>cu2(?ayTp>fom}2?Xqp6vIf=-=@R4e z$-XdMz#w!s1N0^*4kZkHc3Y4B?YjJ5AT4*AROg=m{q zC@|cIEvpbv;z0HDm8>7Q@*s)&n3w)~hMVRb4r3KJzv&?s3RBPh-^*v10;2&U%rAnn zFlwZy@@2LoJHkV_*>part!N?miXOSy(KZh3U# z#$B^`8-`7c4#G4|fSWj4zm-|pm~xC52$?Lj&{dCHhqKi;UYdL>WP?i7%Q4!dkC5J1 z*2Y|kr~36m9mhrT4Co5se+yZ}w|G#&KBuTte6_|ilo>|Lv6fochz z^EI^Oy!iJDjamo%p=kN*<}A+Y%$smlEVRg?ueEdHOELA3Lq0GHsDH8sXv-IwKgiOh z+A6CMYW-cM{`s9`TX29p^gx{XdsyU~+92znZgN zjZfV`K#XKB9Q=is+6I(e*$hiCykF;qsU`zSr|Cd-xXXvbM#raF7V=X{cB6q$$Z2W~ zw(hC%h*@Ga%TGhtJ z95Q&NAPISQ3A94~rtDPt+~!%TeLFUccBi&4CME8CE;*y~GXi_vkA}1H`2!~VZv)eR zts~JN7H~zR*dQUR(I^t`D-;v8xWnMM5vDzY)>CC!8#F?SCP=X7kNuLtbm(WaVQ8Yy zQNe+ixLvTUsDNyuecAQljP5!%aEuW2v0o+)Foc*M(g9~=WCZ#(ehj#D=x%vH6RAYM zxnV>7j?}OiU6VNGlAj~4r9h9HAPN#7o<4N@UbBra=MD&7OAVgl_aUt-%PB?AFLL7&rI==z{< zCIhf7(jG4V;j@Ev)}~#!ldJ$~JPr+e;&S;sLmQ2}%nJ}lRbTgRnC76+hvw_U5W4`r);H7gPrQwls`&y zP8nY*ZxO39%SpMV@0+EC)PEskB{Nd*=_L~PaeTe57Id$5zJ30WeF+zJ%roM56#C?t zwmQ=i9nZ|?jpOCxz`r`EjE8O{^iu?2V0;kz;Y^Rt!=L9kbv!^`00Nf`aM!H4dtJo% z3PB@`kUHX=JW+kk8xr)z3uw=Rt?Jc7-d}J@x1z+r9S*FRrSw;*afNWVepl~d#I+j5 zQQN(~bsXIgT-9D^CeXd$dh&I7ki-ob8MO?Sl6%E^j}uL=@<)=`L?4!zu*_i_s2Q@< z8qhDA_!al*Edpx7LX1YMtMXvj7&^AvmRBC8sqg|8?oXIq)gcMZt+{Uq&A($&UAzqU z)D+4xMiLgEvWY{V2Z@#kzAOk*PKp%#MuVrQc?CWTeNJ{BW!YX=hN#6sU}rOTB?Th6 zKash$lZ184l1dnk#uMsG*3TPD7zT%7_AERRf*9B-`-RWQrkZ{KBV6Rkc7+cWu zrq$%?=BMM873$uO&neXQrl6@wZ0T|Xx;<^^wMGtwS31RSz1vrHLfNx|j`gC|5*YDR zvfVH>Uw?VwR9r=s)|14~j4^3-o7fFqc5Y@|&v7g^t~O+Uth~NiQfcj3@NPNaH&mu! zEmcfvUB!OO!_mm*f}9Z@G*n}hW!E+6X?o(stS@w`YXWUZAdIKPcfNxyhdkTYC^Ig9 zQBGQW9wsxA(hQy7{93+AZ>H`qZT`7?l+qHLs6i(iO&g^_M=9Pn@UXlLi^f} z>po?&FtqkgsRL9)X^V$xnr;uJ73 zL7dii`c`911$GEWTg@$eos(z%(;*18e&S}{YMM$>j7W#qe!VJcZLO^4G{G+@G1 zq*c)2G@)3cwPrb>4o%-BThXeA%W$jLCUkDEK%p6y zx{pDecR4YO*Qu{hqs{U%ufV}o>7uvt;b6w)LQPSN%ymB+!KJ?Ilr0q@(X!|MvHU9s zrh$ZYj?N~BaCp;oou|fElRJYbN42QcKRYd+O|O49J32NTMUCSJ)w~0mPp*4qZjJ`| zSr_Kc1P@YLM6XFN&p~U^?}Pq7TD!(pT`a#clWd1d*VU@MX$Z+VFlQOxf8yczd-?m3 zTN7#0{kwqD3CwU1hjVKDiHc;@Db`+i4(s0bCAw=y4q9FBZ-wZeL$V(%=?P4`(GF!C z#%C3~}kN@dYH^#6OOWrZc(+bF-2U??$!a6`CA<9u^8sVY0E+ z$JAoXEt|uWmXIRW`KDB5T_w2DKH{K~B8Z+hbnAR-m31-qDAHcVv{7d?hsj0D=Z{7I z6k~+-E7+BW98Ff0?&*viT45mfIBd#Mo#$w@08^ zE;7!AlNSxv%oYh6f0J)_UNgJ-ZkY}hGxyia49=hzlKM7;c4gq6QTqzbq@lVlBscnK zy_N>ZkElem*>pU`26)pFO+{$`2C~q!ndQHba&0Q@;%;17Wrur z@@yrj52-F!`#C_H4?8q9XYu3V6X&CHJBi`2%IdiAYNs(QpviLAXPJ;&=IF00`v`xz zL3o{GuLcZLetrvn=PErI_jbf#NF8b=Oivz$hIaO{B1==hm@7Ybw?0pfRDk8n7it2Q zUvx8E?W;&Pzkue2`JGMuy{Z0hN_>m)LNskGWVz;^f|*y$$*MhI#DF7|3;^Fr3jb@1 z{x51k-AT?G(CFA!2n6um?jftqVepjleduuX( z<{fToM;mllexezA6^j2%|4aHRRT7-%a~@hSC^@c#xhP`K~&ZEu9~y)ZfE zkt5@#v3n<@Df?2j0`pm;x4j-eD}VnQ{i`>~O@44YRKN!S7>Dd)oz?qy$gc~*t9*af zd5PO%J3ub&Gjl*{sygzEfMVqd{e<`P$YNPkr8T%_)VQ856x20?*&Ff-QY9to3*j$+ z5>zETTr>QU%1W`xP#@GgyTuqVk!t&8=3WAt))2cwVt)92*b+9v42fa2H$N7NBANKy z&asY!_Y;`nK9sX1z}_*yI;q37Ld9+dcD(dcMN!G6c9W{F zMyfuLJ!;yIOUi+K-1355d?75RYAYEt&0?H#SRf@NMf6;z=`J5N&NOB$dQJ8=I&`~4 z*8;GE>>Cwsf}a&`8YZ&jhaKYA=vae|YQh+R9dbF8 zA`4~bKd?80GUd98!M`~W)*!;-LzngI2A6}bAOWu*XU&Z_NAmlAO=|tWP8z4)v#u-g ztYyxn;qK_}rD%Lvkp!=~tWyXiF-FfH%2e+G1&j`~ftS|vGs#OC!A_MwGlSLkE>B1i z6$YaCXIAjxzsP;+2BlLx21=ns3$7$U-i>)T${2yS^CNd)iYbZGv;KKW zj9kPFT=4ME#gRo&o`lSsI&Z+fEGR(jci6}OvtRskLIyzFDs_o#*6Dxu16awGAU6hbA3otr7}^* zO4S&SXXWuzG?&`q6N1PPWt?EB+bU|dE@P9dw@*H{TM8lq}Zj?EgVqv)VPy zaRjms;f^DHvsYb?19hD8v~4C$OJ>o|iN!~arPy0YxL8z9De^9QRWAj}pAS}KCm>A@ z?_40x%fmnPX`I}yhCM6Zf++!5$2!Pu*&599(NeTWw2d|u9N|E1g3{PAF>0~$+2m$i z#cC|QOcdpQn!unW)Dos`_(YW0D!xo1afa-Kr+1brd2@~KyBP+@z(B#cx@GHl+FZa6 z!7?lk>TF(ImK>gIWlPtcUwm^^rag;B2_Xazf%m&+5rz_2BbFY)zuuGTT3py=^4g6B zJ+`sm0Hqj&>l`;*^>dAW8=E}$NJwAGkJO0TJ}B-FEtBc}v{UOW2sv*%M)mlNZAnZ@ z)bM!esx`r>A@qX$YuUoL6zy*}`=L`61mfmwbgA?!;kCC&paq@Pprev3bbGEO5iUZg z^8f~O)Cqx4X(H#cWiT1o#@Gd>d}7nMQh(OKPan{tzG}l(KfDeX6q7Bse28K3k%aYanRaBVLb|_tU?81-$r`Ihq$k-_VcC_@y z&o%`J^+|x*chUb>d1sNj-Z$X?F@L|7AI~%Yo+FY602bd4(f)ySAkd5Ro3|dSdF=BI T^}xTC-jjMQFIFP*#_#_C2aR!W diff --git a/abstract-document/etc/abstract-document-base.ucls b/abstract-document/etc/abstract-document-base.ucls deleted file mode 100644 index bfe927ed9357..000000000000 --- a/abstract-document/etc/abstract-document-base.ucls +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/abstract-document/etc/abstract-document.png b/abstract-document/etc/abstract-document.png deleted file mode 100644 index 98d186f7e7aa8de23be6656c58332c826db77aa7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16712 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/abstract-document/etc/abstract-document.urm.puml b/abstract-document/etc/abstract-document.urm.puml deleted file mode 100644 index 0c6ffc5ece2e..000000000000 --- a/abstract-document/etc/abstract-document.urm.puml +++ /dev/null @@ -1,59 +0,0 @@ -@startuml -package com.iluwatar.abstractdocument.domain { - class Car { - + Car(properties : Map) - } - interface HasModel { - + PROPERTY : String {static} - + getModel() : Optional - } - interface HasParts { - + PROPERTY : String {static} - + getParts() : Stream - } - interface HasPrice { - + PROPERTY : String {static} - + getPrice() : Optional - } - interface HasType { - + PROPERTY : String {static} - + getType() : Optional - } - class Part { - + Part(properties : Map) - } -} -package com.iluwatar.abstractdocument { - abstract class AbstractDocument { - - properties : Map - # AbstractDocument(properties : Map) - + children(key : String, constructor : Function, T>) : Stream - + get(key : String) : Object - + put(key : String, value : Object) - + toString() : String - } - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - interface Document { - + children(String, Function, T>) : Stream {abstract} - + get(String) : Object {abstract} - + put(String, Object) {abstract} - } -} -AbstractDocument ..|> Document -Car ..|> HasModel -Car ..|> HasPrice -Car ..|> HasParts -Car --|> AbstractDocument -HasModel --|> Document -HasParts --|> Document -HasPrice --|> Document -HasType --|> Document -Part ..|> HasType -Part ..|> HasModel -Part ..|> HasPrice -Part --|> AbstractDocument -@enduml \ No newline at end of file diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml deleted file mode 100644 index cf49544cd1e0..000000000000 --- a/abstract-document/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - abstract-document - - - junit - junit - test - - - \ No newline at end of file diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java deleted file mode 100644 index 36a946cc9eca..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Stream; - -/** - * Abstract implementation of Document interface - */ -public abstract class AbstractDocument implements Document { - - private final Map properties; - - protected AbstractDocument(Map properties) { - Objects.requireNonNull(properties, "properties map is required"); - this.properties = properties; - } - - @Override - public Void put(String key, Object value) { - properties.put(key, value); - return null; - } - - @Override - public Object get(String key) { - return properties.get(key); - } - - @Override - public Stream children(String key, Function, T> constructor) { - Optional>> any = Stream.of(get(key)).filter(el -> el != null) - .map(el -> (List>) el).findAny(); - return any.isPresent() ? any.get().stream().map(constructor) : Stream.empty(); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(getClass().getName()).append("["); - properties.entrySet() - .forEach(e -> builder.append("[").append(e.getKey()).append(" : ").append(e.getValue()).append("]")); - builder.append("]"); - return builder.toString(); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java deleted file mode 100644 index 83f6ab3d59dd..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import com.iluwatar.abstractdocument.domain.Car; -import com.iluwatar.abstractdocument.domain.HasModel; -import com.iluwatar.abstractdocument.domain.HasParts; -import com.iluwatar.abstractdocument.domain.HasPrice; -import com.iluwatar.abstractdocument.domain.HasType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * The Abstract Document pattern enables handling additional, non-static - * properties. This pattern uses concept of traits to enable type safety and - * separate properties of different classes into set of interfaces. - *

- *

- * In Abstract Document pattern,({@link AbstractDocument}) fully implements - * {@link Document}) interface. Traits are then defined to enable access to - * properties in usual, static way. - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Executes the App - */ - public App() { - LOGGER.info("Constructing parts and car"); - - Map carProperties = new HashMap<>(); - carProperties.put(HasModel.PROPERTY, "300SL"); - carProperties.put(HasPrice.PROPERTY, 10000L); - - Map wheelProperties = new HashMap<>(); - wheelProperties.put(HasType.PROPERTY, "wheel"); - wheelProperties.put(HasModel.PROPERTY, "15C"); - wheelProperties.put(HasPrice.PROPERTY, 100L); - - Map doorProperties = new HashMap<>(); - doorProperties.put(HasType.PROPERTY, "door"); - doorProperties.put(HasModel.PROPERTY, "Lambo"); - doorProperties.put(HasPrice.PROPERTY, 300L); - - carProperties.put(HasParts.PROPERTY, Arrays.asList(wheelProperties, doorProperties)); - - Car car = new Car(carProperties); - - 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())); - } - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - new App(); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java deleted file mode 100644 index 13782351492f..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Stream; - -/** - * Document interface - */ -public interface Document { - - /** - * Puts the value related to the key - * - * @param key element key - * @param value element value - * @return Void - */ - Void put(String key, Object value); - - /** - * Gets the value for the key - * - * @param key element key - * @return value or null - */ - Object get(String key); - - /** - * Gets the stream of child documents - * - * @param key element key - * @param constructor constructor of child class - * @return child documents - */ - Stream children(String key, Function, T> constructor); -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java deleted file mode 100644 index 44f640b415fd..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import java.util.Map; - -import com.iluwatar.abstractdocument.AbstractDocument; - -/** - * Car entity - */ -public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts { - - public Car(Map properties) { - super(properties); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java deleted file mode 100644 index 252a4644f289..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import java.util.Optional; - -import com.iluwatar.abstractdocument.Document; - -/** - * HasModel trait for static access to 'model' property - */ -public interface HasModel extends Document { - - String PROPERTY = "model"; - - default Optional getModel() { - return Optional.ofNullable((String) get(PROPERTY)); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java deleted file mode 100644 index 9df836376f55..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import java.util.stream.Stream; - -import com.iluwatar.abstractdocument.Document; - -/** - * HasParts trait for static access to 'parts' property - */ -public interface HasParts extends Document { - - String PROPERTY = "parts"; - - default Stream getParts() { - return children(PROPERTY, Part::new); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java deleted file mode 100644 index 39e4d159ce58..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import java.util.Optional; - -import com.iluwatar.abstractdocument.Document; - -/** - * HasPrice trait for static access to 'price' property - */ -public interface HasPrice extends Document { - - String PROPERTY = "price"; - - default Optional getPrice() { - return Optional.ofNullable((Number) get(PROPERTY)); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java deleted file mode 100644 index 4a80bff20c16..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import com.iluwatar.abstractdocument.Document; - -import java.util.Optional; - -/** - * HasType trait for static access to 'type' property - */ -public interface HasType extends Document { - - String PROPERTY = "type"; - - default Optional getType() { - return Optional.ofNullable((String) get(PROPERTY)); - } - -} diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java deleted file mode 100644 index 649ccf41365b..000000000000 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument.domain; - -import java.util.Map; - -import com.iluwatar.abstractdocument.AbstractDocument; - -/** - * Part entity - */ -public class Part extends AbstractDocument implements HasType, HasModel, HasPrice { - - public Part(Map properties) { - super(properties); - } - -} diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java deleted file mode 100644 index f6686ff8fd19..000000000000 --- a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNotNull; - -/** - * AbstractDocument test class - */ -public class AbstractDocumentTest { - - private static final String KEY = "key"; - private static final String VALUE = "value"; - - private class DocumentImplementation extends AbstractDocument { - - DocumentImplementation(Map properties) { - super(properties); - } - } - - private DocumentImplementation document = new DocumentImplementation(new HashMap<>()); - - @Test - public void shouldPutAndGetValue() { - document.put(KEY, VALUE); - assertEquals(VALUE, document.get(KEY)); - } - - @Test - public void shouldRetrieveChildren() { - Map child1 = new HashMap<>(); - Map child2 = new HashMap<>(); - List> children = Arrays.asList(child1, child2); - - document.put(KEY, children); - - Stream childrenStream = document.children(KEY, DocumentImplementation::new); - assertNotNull(children); - assertEquals(2, childrenStream.count()); - } - - @Test - public void shouldRetrieveEmptyStreamForNonExistingChildren() { - Stream children = document.children(KEY, DocumentImplementation::new); - assertNotNull(children); - assertEquals(0, children.count()); - } - - @Test - public void shouldIncludePropsInToString() { - Map props = new HashMap<>(); - props.put(KEY, VALUE); - DocumentImplementation document = new DocumentImplementation(props); - assertNotNull(document.toString().contains(KEY)); - assertNotNull(document.toString().contains(VALUE)); - } - -} diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java deleted file mode 100644 index b91f57b2746c..000000000000 --- a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import org.junit.Test; - -/** - * Simple App test - */ -public class AppTest { - - @Test - public void shouldExecuteAppWithoutException() { - App.main(null); - } - -} diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java deleted file mode 100644 index 03d75d5e5e6e..000000000000 --- a/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractdocument; - -import com.iluwatar.abstractdocument.domain.Car; -import com.iluwatar.abstractdocument.domain.HasModel; -import com.iluwatar.abstractdocument.domain.HasParts; -import com.iluwatar.abstractdocument.domain.HasPrice; -import com.iluwatar.abstractdocument.domain.HasType; -import com.iluwatar.abstractdocument.domain.Part; -import org.junit.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static junit.framework.TestCase.assertEquals; - -/** - * Test for Part and Car - */ -public class DomainTest { - - private static final String TEST_PART_TYPE = "test-part-type"; - private static final String TEST_PART_MODEL = "test-part-model"; - private static final long TEST_PART_PRICE = 0L; - - private static final String TEST_CAR_MODEL = "test-car-model"; - private static final long TEST_CAR_PRICE = 1L; - - @Test - public void shouldConstructPart() { - Map partProperties = new HashMap<>(); - partProperties.put(HasType.PROPERTY, TEST_PART_TYPE); - partProperties.put(HasModel.PROPERTY, TEST_PART_MODEL); - partProperties.put(HasPrice.PROPERTY, TEST_PART_PRICE); - Part part = new Part(partProperties); - - assertEquals(TEST_PART_TYPE, part.getType().get()); - assertEquals(TEST_PART_MODEL, part.getModel().get()); - assertEquals(TEST_PART_PRICE, part.getPrice().get()); - } - - @Test - public void shouldConstructCar() { - Map carProperties = new HashMap<>(); - carProperties.put(HasModel.PROPERTY, TEST_CAR_MODEL); - carProperties.put(HasPrice.PROPERTY, TEST_CAR_PRICE); - carProperties.put(HasParts.PROPERTY, Arrays.asList(new HashMap<>(), new HashMap<>())); - Car car = new Car(carProperties); - - assertEquals(TEST_CAR_MODEL, car.getModel().get()); - assertEquals(TEST_CAR_PRICE, car.getPrice().get()); - assertEquals(2, car.getParts().count()); - } - -} diff --git a/abstract-factory/.gitignore b/abstract-factory/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/abstract-factory/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/abstract-factory/README.md b/abstract-factory/README.md deleted file mode 100644 index c049401fcd5c..000000000000 --- a/abstract-factory/README.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -layout: pattern -title: Abstract Factory -folder: abstract-factory -permalink: /patterns/abstract-factory/ -pumlid: PSZB3OD034NHLa81Czwd6sCC39gVxEUWT1_ssLmTtQLqgR5fM7sTmFGtaV6TZu8prd0r6HtQaMKqAZLk1XjT_E6qgPUZfyc0MdTgx0-8LuUn8ErFXdr98NypXxKyezKV -categories: Creational -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Also known as -Kit - -## Intent -Provide an interface for creating families of related or dependent -objects without specifying their concrete classes. - -## Explanation -Real world example - -> To create a kingdom we need objects with common theme. Elven kingdom needs an Elven king, Elven castle and Elven army whereas Orcish kingdom needs an Orcish king, Orcish castle and Orcish army. There is a dependency between the objects in the kingdom. - -In plain words - -> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes. - -Wikipedia says - -> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes - -**Programmatic Example** - -Translating the kingdom example above. First of all we have some interfaces and implementation for the objects in the kingdom - -``` -public interface Castle { - String getDescription(); -} -public interface King { - String getDescription(); -} -public interface Army { - String getDescription(); -} - -// Elven implementations -> -public class ElfCastle implements Castle { - static final String DESCRIPTION = "This is the Elven castle!"; - @Override - public String getDescription() { - return DESCRIPTION; - } -} -public class ElfKing implements King { - static final String DESCRIPTION = "This is the Elven king!"; - @Override - public String getDescription() { - return DESCRIPTION; - } -} -public class ElfArmy implements Army { - static final String DESCRIPTION = "This is the Elven Army!"; - @Override - public String getDescription() { - return DESCRIPTION; - } -} - -// Orcish implementations similarly... - -``` - -Then we have the abstraction and implementations for the kingdom factory - -``` -public interface KingdomFactory { - Castle createCastle(); - King createKing(); - Army createArmy(); -} - -public class ElfKingdomFactory implements KingdomFactory { - public Castle createCastle() { - return new ElfCastle(); - } - public King createKing() { - return new ElfKing(); - } - public Army createArmy() { - return new ElfArmy(); - } -} - -public class OrcKingdomFactory implements KingdomFactory { - public Castle createCastle() { - return new OrcCastle(); - } - public King createKing() { - return new OrcKing(); - } - public Army createArmy() { - return new OrcArmy(); - } -} -``` - -Now we have our abstract factory that lets us make family of related objects i.e. Elven kingdom factory creates Elven castle, king and army etc. - -``` -KingdomFactory factory = new ElfKingdomFactory(); -Castle castle = factory.createCastle(); -King king = factory.createKing(); -Army army = factory.createArmy(); - -castle.getDescription(); // Output: This is the Elven castle! -king.getDescription(); // Output: This is the Elven king! -army.getDescription(); // Output: This is the Elven Army! -``` - -## Applicability -Use the Abstract Factory pattern when - -* a system should be independent of how its products are created, composed and represented -* a system should be configured with one of multiple families of products -* a family of related product objects is designed to be used together, and you need to enforce this constraint -* you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations -* the lifetime of the dependency is conceptually shorter than the lifetime of the consumer. -* you need a run-time value to construct a particular dependency -* you want to decide which product to call from a family at runtime. -* you need to supply one or more parameters only known at run-time before you can resolve a dependency. - -## Use Cases: - -* Selecting to call the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime. -* Unit test case writing becomes much easier - -## Consequences: - -* Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time. - -## Real world examples - -* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) -* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--) -* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml deleted file mode 100644 index f3a266f8ef7d..000000000000 --- a/abstract-factory/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - abstract-factory - - - junit - junit - test - - - diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java deleted file mode 100644 index d7cb296c0b18..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * without specifying their concrete classes. In normal usage, the client software creates a concrete implementation of - * the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part - * of the theme. The client does not know (or care) which concrete objects it gets from each of these internal - * factories, since it uses only the generic interfaces of their products. This pattern separates the details of - * implementation of a set of objects from their general usage and relies on object composition, as object creation is - * implemented in methods exposed in the factory interface. - *

- * The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and its implementations ( - * {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both concrete implementations to create a - * king, a castle and an army. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - private King king; - private Castle castle; - private Army army; - - /** - * Creates kingdom - */ - public void createKingdom(final KingdomFactory factory) { - setKing(factory.createKing()); - setCastle(factory.createCastle()); - setArmy(factory.createArmy()); - } - - King getKing(final KingdomFactory factory) { - return factory.createKing(); - } - - public King getKing() { - return king; - } - - private void setKing(final King king) { - this.king = king; - } - - Castle getCastle(final KingdomFactory factory) { - return factory.createCastle(); - } - - public Castle getCastle() { - return castle; - } - - private void setCastle(final Castle castle) { - this.castle = castle; - } - - Army getArmy(final KingdomFactory factory) { - return factory.createArmy(); - } - - public Army getArmy() { - return army; - } - - private void setArmy(final Army army) { - this.army = army; - } - - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - - App app = new App(); - - LOGGER.info("Elf Kingdom"); - app.createKingdom(new ElfKingdomFactory()); - LOGGER.info(app.getArmy().getDescription()); - LOGGER.info(app.getCastle().getDescription()); - LOGGER.info(app.getKing().getDescription()); - - LOGGER.info("Orc Kingdom"); - app.createKingdom(new OrcKingdomFactory()); - LOGGER.info(app.getArmy().getDescription()); - LOGGER.info(app.getCastle().getDescription()); - LOGGER.info(app.getKing().getDescription()); - - } - -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java deleted file mode 100644 index 3d107dd3479e..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * Army interface - * - */ -public interface Army { - - String getDescription(); -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java deleted file mode 100644 index 837952d0d364..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * Castle interface - * - */ -public interface Castle { - - String getDescription(); -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java deleted file mode 100644 index f9687073df29..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * ElfArmy - * - */ -public class ElfArmy implements Army { - - static final String DESCRIPTION = "This is the Elven Army!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java deleted file mode 100644 index 108bdc8d315a..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * ElfCastle - * - */ -public class ElfCastle implements Castle { - - static final String DESCRIPTION = "This is the Elven castle!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java deleted file mode 100644 index f6e400bc0d8c..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * ElfKing - * - */ -public class ElfKing implements King { - - static final String DESCRIPTION = "This is the Elven king!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java deleted file mode 100644 index 31cfddb70ff8..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * ElfKingdomFactory concrete factory. - * - */ -public class ElfKingdomFactory implements KingdomFactory { - - public Castle createCastle() { - return new ElfCastle(); - } - - public King createKing() { - return new ElfKing(); - } - - public Army createArmy() { - return new ElfArmy(); - } - -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java deleted file mode 100644 index bffc994d24cb..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * King interface - * - */ -public interface King { - - String getDescription(); -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java deleted file mode 100644 index fb3434fae136..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * KingdomFactory factory interface. - * - */ -public interface KingdomFactory { - - Castle createCastle(); - - King createKing(); - - Army createArmy(); - -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java deleted file mode 100644 index 31552f4301db..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * OrcArmy - * - */ -public class OrcArmy implements Army { - - static final String DESCRIPTION = "This is the Orc Army!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java deleted file mode 100644 index e72da4a77b50..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * OrcCastle - * - */ -public class OrcCastle implements Castle { - - static final String DESCRIPTION = "This is the Orc castle!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java deleted file mode 100644 index f48115f89d3a..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * OrcKing - * - */ -public class OrcKing implements King { - - static final String DESCRIPTION = "This is the Orc king!"; - - @Override - public String getDescription() { - return DESCRIPTION; - } -} diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java deleted file mode 100644 index 5b2ba3a30fc9..000000000000 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -/** - * - * OrcKingdomFactory concrete factory. - * - */ -public class OrcKingdomFactory implements KingdomFactory { - - public Castle createCastle() { - return new OrcCastle(); - } - - public King createKing() { - return new OrcKing(); - } - - public Army createArmy() { - return new OrcArmy(); - } -} diff --git a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java deleted file mode 100644 index b6fca8b2389f..000000000000 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -/** - * Test for abstract factory - */ -public class AbstractFactoryTest { - - private App app = new App(); - private KingdomFactory elfFactory; - private KingdomFactory orcFactory; - - @Before - public void setUp() { - elfFactory = new ElfKingdomFactory(); - orcFactory = new OrcKingdomFactory(); - } - - @Test - public void king() { - final King elfKing = app.getKing(elfFactory); - assertTrue(elfKing instanceof ElfKing); - assertEquals(ElfKing.DESCRIPTION, elfKing.getDescription()); - final King orcKing = app.getKing(orcFactory); - assertTrue(orcKing instanceof OrcKing); - assertEquals(OrcKing.DESCRIPTION, orcKing.getDescription()); - } - - @Test - public void castle() { - final Castle elfCastle = app.getCastle(elfFactory); - assertTrue(elfCastle instanceof ElfCastle); - assertEquals(ElfCastle.DESCRIPTION, elfCastle.getDescription()); - final Castle orcCastle = app.getCastle(orcFactory); - assertTrue(orcCastle instanceof OrcCastle); - assertEquals(OrcCastle.DESCRIPTION, orcCastle.getDescription()); - } - - @Test - public void army() { - final Army elfArmy = app.getArmy(elfFactory); - assertTrue(elfArmy instanceof ElfArmy); - assertEquals(ElfArmy.DESCRIPTION, elfArmy.getDescription()); - final Army orcArmy = app.getArmy(orcFactory); - assertTrue(orcArmy instanceof OrcArmy); - assertEquals(OrcArmy.DESCRIPTION, orcArmy.getDescription()); - } - - @Test - public void createElfKingdom() { - app.createKingdom(elfFactory); - final King king = app.getKing(); - final Castle castle = app.getCastle(); - final Army army = app.getArmy(); - assertTrue(king instanceof ElfKing); - assertEquals(ElfKing.DESCRIPTION, king.getDescription()); - assertTrue(castle instanceof ElfCastle); - assertEquals(ElfCastle.DESCRIPTION, castle.getDescription()); - assertTrue(army instanceof ElfArmy); - assertEquals(ElfArmy.DESCRIPTION, army.getDescription()); - } - - @Test - public void createOrcKingdom() { - app.createKingdom(orcFactory); - final King king = app.getKing(); - final Castle castle = app.getCastle(); - final Army army = app.getArmy(); - assertTrue(king instanceof OrcKing); - assertEquals(OrcKing.DESCRIPTION, king.getDescription()); - assertTrue(castle instanceof OrcCastle); - assertEquals(OrcCastle.DESCRIPTION, castle.getDescription()); - assertTrue(army instanceof OrcArmy); - assertEquals(OrcArmy.DESCRIPTION, army.getDescription()); - } -} diff --git a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java deleted file mode 100644 index b9d5f7d906e0..000000000000 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.abstractfactory; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Abstract Factory example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/aggregator-microservices/README.md b/aggregator-microservices/README.md deleted file mode 100644 index 75fe373fd301..000000000000 --- a/aggregator-microservices/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Aggregator Microservices -folder: aggregator-microservices -permalink: /patterns/aggregator-microservices/ -pumlid: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00 -categories: Architectural -tags: -- Java -- Spring ---- - -## Intent - -The user makes a single call to the Aggregator, and the aggregator then calls each relevant microservice and collects -the data, apply business logic to it, and further publish is as a REST Endpoint. -More variations of the aggregator are: -- Proxy Microservice Design Pattern: A different microservice is called upon the business need. -- Chained Microservice Design Pattern: In this case each microservice is dependent/ chained to a series -of other microservices. - -![alt text](./etc/aggregator-microservice.png "Aggregator Microservice") - -## Applicability - -Use the Aggregator Microservices pattern when you need a unified API for various microservices, regardless the client device. - -## Credits - -* [Microservice Design Patterns](http://blog.arungupta.me/microservice-design-patterns/) diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml deleted file mode 100644 index 32d5caa3f2eb..000000000000 --- a/aggregator-microservices/aggregator-service/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - aggregator-microservices - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - aggregator-service - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - org.mockito - mockito-core - test - - - org.apache.httpcomponents - httpclient - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Aggregator.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Aggregator.java deleted file mode 100644 index 9f1e4f4daeb8..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Aggregator.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * The aggregator aggregates calls on various micro-services, collects - * data and further publishes them under a REST endpoint. - */ -@RestController -public class Aggregator { - - - @Resource - private ProductInformationClient informationClient; - - @Resource - private ProductInventoryClient inventoryClient; - - - /** - * Retrieves product data. - * - * @return a Product. - */ - @RequestMapping("/product") - public Product getProduct() { - Product product = new Product(); - product.setTitle(informationClient.getProductTitle()); - product.setProductInventories(inventoryClient.getProductInventories()); - return product; - } - -} diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/App.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/App.java deleted file mode 100644 index c43112c2e00a..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/App.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * Spring Boot EntryPoint Class - */ -@SpringBootApplication -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - SpringApplication.run(App.class, args); - } -} diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Product.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Product.java deleted file mode 100644 index 1ded980f90ea..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Product.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -/** - * Encapsulates all the data for a Product that clients will request. - */ -public class Product { - - /** - * The title of the product. - */ - private String title; - - - /** - * The inventories of the product. - */ - private int productInventories; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getProductInventories() { - return productInventories; - } - - public void setProductInventories(int productInventories) { - this.productInventories = productInventories; - } - -} diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClient.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClient.java deleted file mode 100644 index 81cfdc87bb36..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClient.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -/** - * Interface for the Information micro-service. - */ -public interface ProductInformationClient { - - String getProductTitle(); - -} 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 deleted file mode 100644 index 16849d529386..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * An adapter to communicate with information micro-service. - */ -@Component -public class ProductInformationClientImpl implements ProductInformationClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(ProductInformationClientImpl.class); - - @Override - public String getProductTitle() { - String response = null; - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("http://localhost:51515/information"); - try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { - response = EntityUtils.toString(httpResponse.getEntity()); - } - } catch (IOException e) { - LOGGER.error("Exception caught.", e); - } - return response; - } -} diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClient.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClient.java deleted file mode 100644 index c5953dc30dc0..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClient.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -/** - * Interface to Inventory micro-service. - */ -public interface ProductInventoryClient { - - int getProductInventories(); -} 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 deleted file mode 100644 index 89f1a25e0580..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * An adapter to communicate with inventory micro-service. - */ -@Component -public class ProductInventoryClientImpl implements ProductInventoryClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(ProductInventoryClientImpl.class); - - @Override - public int getProductInventories() { - String response = "0"; - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("http://localhost:51516/inventories"); - try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { - response = EntityUtils.toString(httpResponse.getEntity()); - } - } catch (IOException e) { - LOGGER.error("Exception caught.", e); - } - return Integer.parseInt(response); - } -} diff --git a/aggregator-microservices/aggregator-service/src/main/resources/application.properties b/aggregator-microservices/aggregator-service/src/main/resources/application.properties deleted file mode 100644 index ae91c5eb5625..000000000000 --- a/aggregator-microservices/aggregator-service/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=50004 \ No newline at end of file diff --git a/aggregator-microservices/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java b/aggregator-microservices/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java deleted file mode 100644 index 2955f6781d92..000000000000 --- a/aggregator-microservices/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.aggregator.microservices; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Test Aggregation of domain objects - */ -public class AggregatorTest { - - @InjectMocks - private Aggregator aggregator; - - @Mock - private ProductInformationClient informationClient; - - @Mock - private ProductInventoryClient inventoryClient; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - /** - * Tests getting the data for a desktop client - */ - @Test - public void testGetProduct() { - String title = "The Product Title."; - int inventories = 5; - - when(informationClient.getProductTitle()).thenReturn(title); - when(inventoryClient.getProductInventories()).thenReturn(inventories); - - Product testProduct = aggregator.getProduct(); - - assertEquals(title, testProduct.getTitle()); - assertEquals(inventories, testProduct.getProductInventories()); - } - -} diff --git a/aggregator-microservices/etc/aggregator-microservice.png b/aggregator-microservices/etc/aggregator-microservice.png deleted file mode 100644 index ad344a7e1e0fa72633fb06e53ae4ddc0a0695ae4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41304 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˂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

+0z( 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 diff --git a/aggregator-microservices/etc/aggregator-service.urm.puml b/aggregator-microservices/etc/aggregator-service.urm.puml deleted file mode 100644 index ebb782f202b5..000000000000 --- a/aggregator-microservices/etc/aggregator-service.urm.puml +++ /dev/null @@ -1,43 +0,0 @@ -@startuml -package com.iluwatar.aggregator.microservices { - class Aggregator { - - informationClient : ProductInformationClient - - inventoryClient : ProductInventoryClient - + Aggregator() - + getProduct() : Product - } - class App { - + App() - + main(args : String[]) {static} - } - class Product { - - productInventories : int - - title : String - + Product() - + getProductInventories() : int - + getTitle() : String - + setProductInventories(productInventories : int) - + setTitle(title : String) - } - interface ProductInformationClient { - + getProductTitle() : String {abstract} - } - class ProductInformationClientImpl { - - LOGGER : Logger {static} - + ProductInformationClientImpl() - + getProductTitle() : String - } - interface ProductInventoryClient { - + getProductInventories() : int {abstract} - } - class ProductInventoryClientImpl { - - LOGGER : Logger {static} - + ProductInventoryClientImpl() - + getProductInventories() : int - } -} -Aggregator --> "-informationClient" ProductInformationClient -Aggregator --> "-inventoryClient" ProductInventoryClient -ProductInformationClientImpl ..|> ProductInformationClient -ProductInventoryClientImpl ..|> ProductInventoryClient -@enduml \ No newline at end of file diff --git a/aggregator-microservices/etc/information-microservice.urm.puml b/aggregator-microservices/etc/information-microservice.urm.puml deleted file mode 100644 index e0a2ccb24fb2..000000000000 --- a/aggregator-microservices/etc/information-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.information.microservice { - class InformationApplication { - + InformationApplication() - + main(args : String[]) {static} - } - class InformationController { - + InformationController() - + getProductTitle() : String - } -} -@enduml \ No newline at end of file diff --git a/aggregator-microservices/etc/inventory-microservice.urm.puml b/aggregator-microservices/etc/inventory-microservice.urm.puml deleted file mode 100644 index 90f327e07db8..000000000000 --- a/aggregator-microservices/etc/inventory-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.inventory.microservice { - class InventoryApplication { - + InventoryApplication() - + main(args : String[]) {static} - } - class InventoryController { - + InventoryController() - + getProductInventories() : int - } -} -@enduml \ No newline at end of file diff --git a/aggregator-microservices/information-microservice/pom.xml b/aggregator-microservices/information-microservice/pom.xml deleted file mode 100644 index 8b24cdcc0f10..000000000000 --- a/aggregator-microservices/information-microservice/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - aggregator-microservices - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - information-microservice - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - diff --git a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationApplication.java b/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationApplication.java deleted file mode 100644 index 67d568e17dc4..000000000000 --- a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationApplication.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.information.microservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * Inventory Application starts container (Spring Boot) and exposes the Inventory micro-service. - */ -@SpringBootApplication -public class InformationApplication { - - public static void main(String[] args) { - SpringApplication.run(InformationApplication.class, args); - } -} diff --git a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java b/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java deleted file mode 100644 index 63b6fb9d5c0b..000000000000 --- a/aggregator-microservices/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.information.microservice; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -/** - * Controller providing endpoints to retrieve information about products - */ -@RestController -public class InformationController { - - /** - * Endpoint to retrieve a product's informations. - * - * @return product inventory. - */ - @RequestMapping(value = "/information", method = RequestMethod.GET) - public String getProductTitle() { - return "The Product Title."; - } -} diff --git a/aggregator-microservices/information-microservice/src/main/resources/application.properties b/aggregator-microservices/information-microservice/src/main/resources/application.properties deleted file mode 100644 index a921ea0fd100..000000000000 --- a/aggregator-microservices/information-microservice/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=51515 \ No newline at end of file diff --git a/aggregator-microservices/information-microservice/src/test/java/com/iluwatar/information/microservice/InformationControllerTest.java b/aggregator-microservices/information-microservice/src/test/java/com/iluwatar/information/microservice/InformationControllerTest.java deleted file mode 100644 index 127dd39563eb..000000000000 --- a/aggregator-microservices/information-microservice/src/test/java/com/iluwatar/information/microservice/InformationControllerTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.information.microservice; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test for Information Rest Controller - */ -public class InformationControllerTest { - - @Test - public void shouldGetProductTitle() { - InformationController infoController = new InformationController(); - - String title = infoController.getProductTitle(); - - Assert.assertEquals("The Product Title.", title); - } - -} diff --git a/aggregator-microservices/inventory-microservice/pom.xml b/aggregator-microservices/inventory-microservice/pom.xml deleted file mode 100644 index 06804343cd99..000000000000 --- a/aggregator-microservices/inventory-microservice/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - aggregator-microservices - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - inventory-microservice - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryApplication.java b/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryApplication.java deleted file mode 100644 index 73b4c0b18925..000000000000 --- a/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryApplication.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.inventory.microservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * Inventory Application starts container (Spring Boot) and exposes the Inventory micro-service. - */ -@SpringBootApplication -public class InventoryApplication { - - public static void main(String[] args) { - SpringApplication.run(InventoryApplication.class, args); - } - -} diff --git a/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryController.java b/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryController.java deleted file mode 100644 index e6b2eca80863..000000000000 --- a/aggregator-microservices/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryController.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.inventory.microservice; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -/** - * Controller providing endpoints to retrieve product inventories - */ -@RestController -public class InventoryController { - - /** - * Endpoint to retrieve a product's inventories. - * - * @return product inventory. - */ - @RequestMapping(value = "/inventories", method = RequestMethod.GET) - public int getProductInventories() { - return 5; - } - -} diff --git a/aggregator-microservices/inventory-microservice/src/main/resources/application.properties b/aggregator-microservices/inventory-microservice/src/main/resources/application.properties deleted file mode 100644 index 46b49a8a1464..000000000000 --- a/aggregator-microservices/inventory-microservice/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=51516 \ No newline at end of file diff --git a/aggregator-microservices/inventory-microservice/src/test/java/com/iluwatar/inventory/microservice/InventoryControllerTest.java b/aggregator-microservices/inventory-microservice/src/test/java/com/iluwatar/inventory/microservice/InventoryControllerTest.java deleted file mode 100644 index b04370fba22b..000000000000 --- a/aggregator-microservices/inventory-microservice/src/test/java/com/iluwatar/inventory/microservice/InventoryControllerTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.inventory.microservice; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test Inventory Rest Controller - */ -public class InventoryControllerTest { - @Test - public void testGetProductInventories() throws Exception { - InventoryController inventoryController = new InventoryController(); - - int numberOfInventories = inventoryController.getProductInventories(); - - Assert.assertEquals(5, numberOfInventories); - } -} diff --git a/aggregator-microservices/pom.xml b/aggregator-microservices/pom.xml deleted file mode 100644 index aae6b88d5a26..000000000000 --- a/aggregator-microservices/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - aggregator-microservices - pom - - - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - - - - aggregator-microservices - - - - - - - - information-microservice - aggregator-service - inventory-microservice - - diff --git a/api-gateway/README.md b/api-gateway/README.md deleted file mode 100644 index 93b975e131d3..000000000000 --- a/api-gateway/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: API Gateway -folder: api-gateway -permalink: /patterns/api-gateway/ -pumlid: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0 -categories: Architectural -tags: -- Java -- Difficulty-Intermediate -- Spring ---- - -## Intent - -Aggregate calls to microservices in a single location: the API Gateway. The user makes a single -call to the API Gateway, and the API Gateway then calls each relevant microservice. - -![alt text](./etc/api-gateway.png "API Gateway") - -## Applicability - -Use the API Gateway pattern when - -* you're also using the Microservices pattern and need a single point of aggregation for your -microservice calls - -## Credits - -* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html) -* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/) diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml deleted file mode 100644 index a97c25cfc3c4..000000000000 --- a/api-gateway/api-gateway-service/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - api-gateway - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - api-gateway-service - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - org.mockito - mockito-core - test - - - org.apache.httpcomponents - httpclient - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java deleted file mode 100644 index aab1247963a7..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * The ApiGateway aggregates calls to microservices based on the needs of the individual clients. - */ -@RestController -public class ApiGateway { - - @Resource - private ImageClient imageClient; - - @Resource - private PriceClient priceClient; - - /** - * Retrieves product information that desktop clients need - * @return Product information for clients on a desktop - */ - @RequestMapping("/desktop") - public DesktopProduct getProductDesktop() { - DesktopProduct desktopProduct = new DesktopProduct(); - desktopProduct.setImagePath(imageClient.getImagePath()); - desktopProduct.setPrice(priceClient.getPrice()); - return desktopProduct; - } - - /** - * Retrieves product information that mobile clients need - * @return Product information for clients on a mobile device - */ - @RequestMapping("/mobile") - public MobileProduct getProductMobile() { - MobileProduct mobileProduct = new MobileProduct(); - mobileProduct.setPrice(priceClient.getPrice()); - return mobileProduct; - } -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java deleted file mode 100644 index 3b529aa5fe96..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * With the Microservices pattern, a client may need data from multiple different microservices. - * If the client called each microservice directly, that could contribute to longer load times, - * since the client would have to make a network request for each microservice called. Moreover, - * having the client call each microservice directly ties the client to that microservice - if the - * internal implementations of the microservices change (for example, if two microservices are - * combined sometime in the future) or if the location (host and port) of a microservice changes, - * then every client that makes use of those microservices must be updated. - * - *

- * The intent of the API Gateway pattern is to alleviate some of these issues. In the API Gateway - * pattern, an additional entity (the API Gateway) is placed between the client and the - * microservices. The job of the API Gateway is to aggregate the calls to the microservices. - * Rather than the client calling each microservice individually, the client calls the API Gateway - * a single time. The API Gateway then calls each of the microservices that the client needs. - * - *

- * This implementation shows what the API Gateway pattern could look like for an e-commerce site. - * The {@link ApiGateway} makes calls to the Image and Price microservices using the - * {@link ImageClientImpl} and {@link PriceClientImpl} respectively. Customers viewing the site on a - * desktop device can see both price information and an image of a product, so the {@link ApiGateway} - * calls both of the microservices and aggregates the data in the {@link DesktopProduct} model. - * However, mobile users only see price information; they do not see a product image. For mobile - * users, the {@link ApiGateway} only retrieves price information, which it uses to populate the - * {@link MobileProduct}. - */ -@SpringBootApplication -public class App { - - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - SpringApplication.run(App.class, args); - } -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java deleted file mode 100644 index e72b98e73c40..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -/** - * Encapsulates all of the information that a desktop client needs to display a product. - */ -public class DesktopProduct { - /** - * The price of the product - */ - private String price; - - /** - * The path to the image of the product - */ - private String imagePath; - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } - - public String getImagePath() { - return imagePath; - } - - public void setImagePath(String imagePath) { - this.imagePath = imagePath; - } -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java deleted file mode 100644 index dca012a412d2..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -/** - * An interface used to communicate with the Image microservice - */ -public interface ImageClient { - String getImagePath(); -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java deleted file mode 100644 index ebabfe839b69..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * An adapter to communicate with the Image microservice - */ -@Component -public class ImageClientImpl implements ImageClient { - /** - * Makes a simple HTTP Get request to the Image microservice - * @return The path to the image - */ - @Override - public String getImagePath() { - String response = null; - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("http://localhost:50005/image-path"); - try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { - response = EntityUtils.toString(httpResponse.getEntity()); - } - } catch (IOException e) { - e.printStackTrace(); - } - return response; - } -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java deleted file mode 100644 index c057379fca81..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -/** - * Encapsulates all of the information that mobile client needs to display a product. - */ -public class MobileProduct { - /** - * The price of the product - */ - private String price; - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java deleted file mode 100644 index 4f4d2bbfc1eb..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -/** - * An interface used to communicate with the Price microservice - */ -public interface PriceClient { - String getPrice(); -} diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java deleted file mode 100644 index 87f44761c649..000000000000 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * An adapter to communicate with the Price microservice - */ -@Component -public class PriceClientImpl implements PriceClient { - /** - * Makes a simple HTTP Get request to the Price microservice - * @return The price of the product - */ - @Override - public String getPrice() { - String response = null; - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("http://localhost:50006/price"); - try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { - response = EntityUtils.toString(httpResponse.getEntity()); - } - } catch (IOException e) { - e.printStackTrace(); - } - return response; - } -} diff --git a/api-gateway/api-gateway-service/src/main/resources/application.properties b/api-gateway/api-gateway-service/src/main/resources/application.properties deleted file mode 100644 index ae91c5eb5625..000000000000 --- a/api-gateway/api-gateway-service/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=50004 \ No newline at end of file diff --git a/api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java b/api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java deleted file mode 100644 index 6a79e5d00279..000000000000 --- a/api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.api.gateway; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Test API Gateway Pattern - */ -public class ApiGatewayTest { - - @InjectMocks - private ApiGateway apiGateway; - - @Mock - private ImageClient imageClient; - - @Mock - private PriceClient priceClient; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - /** - * Tests getting the data for a desktop client - */ - @Test - public void testGetProductDesktop() { - String imagePath = "/product-image.png"; - String price = "20"; - when(imageClient.getImagePath()).thenReturn(imagePath); - when(priceClient.getPrice()).thenReturn(price); - - DesktopProduct desktopProduct = apiGateway.getProductDesktop(); - - assertEquals(price, desktopProduct.getPrice()); - assertEquals(imagePath, desktopProduct.getImagePath()); - } - - /** - * Tests getting the data for a mobile client - */ - @Test - public void testGetProductMobile() { - String price = "20"; - when(priceClient.getPrice()).thenReturn(price); - - MobileProduct mobileProduct = apiGateway.getProductMobile(); - - assertEquals(price, mobileProduct.getPrice()); - } -} diff --git a/api-gateway/etc/api-gateway-service.urm.puml b/api-gateway/etc/api-gateway-service.urm.puml deleted file mode 100644 index 5fabc6a0fab4..000000000000 --- a/api-gateway/etc/api-gateway-service.urm.puml +++ /dev/null @@ -1,48 +0,0 @@ -@startuml -package com.iluwatar.api.gateway { - class ApiGateway { - - imageClient : ImageClient - - priceClient : PriceClient - + ApiGateway() - + getProductDesktop() : DesktopProduct - + getProductMobile() : MobileProduct - } - class App { - + App() - + main(args : String[]) {static} - } - class DesktopProduct { - - imagePath : String - - price : String - + DesktopProduct() - + getImagePath() : String - + getPrice() : String - + setImagePath(imagePath : String) - + setPrice(price : String) - } - interface ImageClient { - + getImagePath() : String {abstract} - } - class ImageClientImpl { - + ImageClientImpl() - + getImagePath() : String - } - class MobileProduct { - - price : String - + MobileProduct() - + getPrice() : String - + setPrice(price : String) - } - interface PriceClient { - + getPrice() : String {abstract} - } - class PriceClientImpl { - + PriceClientImpl() - + getPrice() : String - } -} -ApiGateway --> "-imageClient" ImageClient -ApiGateway --> "-priceClient" PriceClient -ImageClientImpl ..|> ImageClient -PriceClientImpl ..|> PriceClient -@enduml \ No newline at end of file diff --git a/api-gateway/etc/api-gateway.png b/api-gateway/etc/api-gateway.png deleted file mode 100644 index bb3ec2e2e1a824699a539c89f362d2573e3860c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18323 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/api-gateway/etc/image-microservice.urm.puml b/api-gateway/etc/image-microservice.urm.puml deleted file mode 100644 index 130dac9de383..000000000000 --- a/api-gateway/etc/image-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.image.microservice { - class ImageApplication { - + ImageApplication() - + main(args : String[]) {static} - } - class ImageController { - + ImageController() - + getImagePath() : String - } -} -@enduml \ No newline at end of file diff --git a/api-gateway/etc/price-microservice.urm.puml b/api-gateway/etc/price-microservice.urm.puml deleted file mode 100644 index 9893c9c601d1..000000000000 --- a/api-gateway/etc/price-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.price.microservice { - class PriceApplication { - + PriceApplication() - + main(args : String[]) {static} - } - class PriceController { - + PriceController() - + getPrice() : String - } -} -@enduml \ No newline at end of file diff --git a/api-gateway/image-microservice/etc/image-microservice.png b/api-gateway/image-microservice/etc/image-microservice.png deleted file mode 100644 index 340285a14f64aac47061b4c74373476f8fcc74fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2695 zcmV;23V8L2P) z*^d-O9LFayKAP|k_@FVq2}G2QF2e&W^1+$s3};&59RW&M$ILcnqjGh3`>1vSn4Cg zQXe%5%TjkX+g++nY$L_2|KMlYHIKZJYBiP)NFQOjU}f5hCBw4D!d0vaLDgLu;<1%Vg%V;Zoy9DeBq4>^xr}ff$RVx566(>Z8P`67LNEgc1FR}% zb0JXCf}N3La77DrX$DU2(3CkfOOH@;ow`~!Gl#_H!G)ws` z`c;lrj>O3ZHQ&GxZCRq)iEWnv!#47#d(J`^ zzHQ-lPkoH|D}8?PFBHXDHapbEBZs6%sb^^vTZW}RGA#9xVX2P{OMPTm>Z4>?Ub}I1 z$-(tA_jJDW$($L3OJN^E8eV2yl_1OB(LI3ho$uFf8vei&>`&^Q1>p@Zww6kYB>;QA zXIg%A>+u`MF5R)O{C*ie4_!UbGurda#&!;;+Z#}~?k@Iczq&+muWzJi(dtshL|8&Y z3KqF}c+XhME#8(II|soee>`pWr4F+E=xMeY%-vTM<}UPNr7!y=S*=ZDucV= zgDO-$*bSkXanoXhml@jUmu+Js0U;^kq!nX0QdH?-*)gzmZei)cE8jv?ckbWqJovV! zH9xFdd3Y6Q(a>@@M#(aRhlO1Wa9c$(RLRD$c_v)L}qR57_Y{i%y+wvL+b|&SgPwt!1-amU% zex}+k>3BW4kVOWhx1EhPRG(%8XUqbl2G~U*0i$ z)9?<6>W>G1PT4uPea9To;cLUku8%G(u9-HlFvu>$So*D#Q>||OiY(oI%97js5i6Bl z^5LXf$HJ2Sq-H5*EY&RGUfAA0XK8WO!$>j4PU&d#tjwJMci87XAmZ1E}!SP!zdJArtVIqg9kFOQU+qu+&F}r9Lt&^^swzj|@wFlsrp2=k;b)IZLKA66^nB)$vzd zqV%OwFT1R=`~|Cp|NB>}I4o(u7vGUaChL#^+nnw9PKi?)Grn3;xLgvc5`hQK2k_YAK;(gdH_1AqlVfxfie|E?eozJ*$`%A@^J>S6sm<~iK`#vNWkAO$zV0+&CMcJrXo)s zt(2u^66~_!`Kgs!k!ASPVDqXqS?VdnQXd(X`pB@J9mTUxA}m#FH^n(IW@aj4iC>9V&$$mZXF2P;_m>^De!BVfzAJ;U z17F1kmeotnaxKYmg7tR-7HA?~;YH*f${nLzy9q_b91q=949JPR=ewUD?gc=cUnI8* zijX=xmwCYY7ui_fm(>`S>rZ_?|H!&y*N2Gq!B+?rFI#`s0DZX%TAE3*KohmIf<<4P zg4U2wJF0sL2{CXX{0dR%{cGwIY2M`2@ww8vQi1NZDQEduPqz0$Z{Ni}Uv?jSg+Mh+ zVFj*`rIuuJXcK((nK%c2;UbXM_QIAObRt_oh)-Qufl6ApDkaTqWh|fEHGjp?b?Z-T zbhQCK;VT4Iz*1gnDUKB??_|lb3`t!ZmR-Z!r|etSe>UHLCcpDc9(Jbe?S#O}Sc(fY zsoGfNBTpxUDAsNYyevXlMz*m+>Ks3@jZKfkbj8m;uNGI&IPliq3;n%6e*`=5RXir5 zja4nsM4o*tOL{q#yt0$(b+Xb5vxKGpYF61vSn4CgQXd(X`lwMX=}VXr7`Tr0 z*6xT5MDzwI-+wP3nUsq~?O5`D1=Ut}qAc-{h%)~0421X6v95V(bhcjDYQs|HS0Ei0 z;U^#r_b2IuK=%1~l>P=8@pWc?acJ+kG`?NN$H)=pY+5?b+aaJ7b!HjMuON<}fM6E2 zbwZHsQjSOAZ-A4C@Eky^l&B0HJ23dA6JnN1QGb>d_!Z#F4H>CV!U;inzYK~eWXKb- z4CwUdS1M8tlyX;+B8eIfe^$n_0>1*Gx`RgQ>*ItF63>`eqF-5zjvA<#AOG z41p|FrKms4as_?`iTVj78F~FY2WnZ0YFI`oQ9pq?IUywMIgm&xl3;1n7#WuO$gtE$ zhNV6-EcKC^rFmCVGj8g4HJPp1H^Wk&&9KyG`yYfYFS4V)%1ZzM002ovPDHLkV1h34 BF%JL$ diff --git a/api-gateway/image-microservice/etc/image-microservice.ucls b/api-gateway/image-microservice/etc/image-microservice.ucls deleted file mode 100644 index d3520768f851..000000000000 --- a/api-gateway/image-microservice/etc/image-microservice.ucls +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/api-gateway/image-microservice/pom.xml b/api-gateway/image-microservice/pom.xml deleted file mode 100644 index 574623b3aea2..000000000000 --- a/api-gateway/image-microservice/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - api-gateway - com.iluwatar - 1.18.0-SNAPSHOT - - - 4.0.0 - image-microservice - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java deleted file mode 100644 index c4c75c0f0c29..000000000000 --- a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.image.microservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * ImageApplication starts up Spring Boot, exposing endpoints for the Image microservice through - * the {@link ImageController}. - */ -@SpringBootApplication -public class ImageApplication { - - /** - * Microservice entry point - * @param args - * command line args - */ - public static void main(String[] args) { - SpringApplication.run(ImageApplication.class, args); - } -} diff --git a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java deleted file mode 100644 index 18d0d400806c..000000000000 --- a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.image.microservice; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -/** - * Exposes the Image microservice's endpoints - */ -@RestController -public class ImageController { - - /** - * An endpoint for a user to retrieve an image path - * @return An image path - */ - @RequestMapping(value = "/image-path", method = RequestMethod.GET) - public String getImagePath() { - return "/product-image.png"; - } -} diff --git a/api-gateway/image-microservice/src/main/resources/application.properties b/api-gateway/image-microservice/src/main/resources/application.properties deleted file mode 100644 index 5830a3c95c55..000000000000 --- a/api-gateway/image-microservice/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=50005 \ No newline at end of file diff --git a/api-gateway/image-microservice/src/test/java/com/iluwatar/image/microservice/ImageControllerTest.java b/api-gateway/image-microservice/src/test/java/com/iluwatar/image/microservice/ImageControllerTest.java deleted file mode 100644 index 1b934014a415..000000000000 --- a/api-gateway/image-microservice/src/test/java/com/iluwatar/image/microservice/ImageControllerTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.image.microservice; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test for Image Rest Controller - */ -public class ImageControllerTest { - @Test - public void testGetImagePath() { - ImageController imageController = new ImageController(); - - String imagePath = imageController.getImagePath(); - - Assert.assertEquals("/product-image.png", imagePath); - } -} diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml deleted file mode 100644 index 124b3cf24d4e..000000000000 --- a/api-gateway/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - api-gateway - pom - - - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - - - - api-gateway - - - - - - - - image-microservice - price-microservice - api-gateway-service - - diff --git a/api-gateway/price-microservice/etc/price-microservice.png b/api-gateway/price-microservice/etc/price-microservice.png deleted file mode 100644 index 7c57160257cbaed699937c23699d8a4cd4b8896d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2572 zcmV+n3iI`eP) z?QaxC9LFy)zBJ(<@P)?sP9UN*#-tD*%27ff4Jn0_Qm~3v2_-I6Dqyb`TeQ-O@o3@1 zibf11El}klKsSL18be|b-|%w%?bFO}9`jo=whUW~Gc+Lpr13m9kD{E~tJp=?1^yq};FZ z^pxfQ%tVX>FS^t$Jg7LkDx4M&XD?FGg@=c#h5$AVpBVuo_{j}V3`M?* z(Tb7S*&q!x(4}_Zq3Q_T@}Ty;OWwa@`ADFqyenPmN4y9)$DmL-8&-X`Jfy&To`(d( zbFX^4u1OWAjCcZMT9l>WheqqS27u(86L@SWyBqLZnA?U#m-@cv<&<5O_$sz*-1(j` z(4}n}xGR(U;eREA4)4m4gfgjDkB8_I1w|E}RtRZ$3QNONSQ?(f((n|PhNrN~3-8*E ztLqMLUADjDrB7EjkG8`(xKzE&HKQ`Z>!02a%-;E7OV8wouHbw@|8j7zda-Lm<$?!< zp6^?doZfZf#_>yc%qzcNhR=zshx(@bp4r~W@}qyB*|~gH&foR|W}ZwGdm$57c`sN8ZzxN|x4g@Dug%@{`g1#91Hs9HCH<<+W3}-4#tuoz;mBkkilaP&y*u;d91siN-^-rPjYyC#v%<5 z?q`idE8Eju42C8aG7snC{36mZY0TFVP6 zTBP8?ND}@JtU9n^$7J&M{ktUEzaIWQeBrCM@lNiJ*qEpv`Ozn(tBQb zc=AZH-t$n#A`B0dJT*FZXH(O@)g2S>?mRWH=jfL}vghC%R{(I)4C z?RaOI5u@yp1xf2+;E}(H@KwlX$kC=GW6_4^@|(A-sU@|s^Rov06yW+_!(cv@wZhNrMJJcXsGATYDGWR^!-OUbWB!~WQ1J|y3DcVg;@8H} zmgghPq#Fzq;_<9*-bA~*T8>UQp@g`JD2ONCz$ApTVIdD*id+$VJBF}WL|ztYBs33f zg-|02Hr=7>@@|1_KQGf9hv?hs4TKbND^FypyE$uGP8VIDChk8 z!o0E?5*`P`OVaXFMTucBVc$D}=T@+nrAf=bVc+udL?X@|-nMrqJ>VfakA>1U3zZonz=s?5=}U1oB|RxJWX{4|gJG!zE$Oit7vW$ZA-4lz+fIPY%y-G)$hns}lNsvJ%eg z2I&e|=OQ!E4ZvH!iri@xpj6@w!d(it57~``*tN5lMH&gs15+W$bk5%Md}}QR%&adA zmDT*=DWJ-X<|8HzPhr&xyt?Di+@2(`#I8 zBljlYr0V6VE0qSGMUUziseYv4DXcPdn|RH!xRyS@eME#kWI`$2qq_XQ3OU3)Us`Q! zg~Qu+X7uso(z#!Ez=>qQf~%vbcb?1kkO>noB#*q{;Wv;)=8=oM;Vu9EgZ0OZpKpFM zc4ZV!;49x}aywag6_haC*9u9tqF~-}20fmI9@I=2G$8w&HAz<*5W|zC zPQ%iNGrg;-*q0Yo0p8ZrU$h?WK7M`N*BE>SNB$z^TAs}bJ(=pg$IEl^9#2N0=<|Tm zZAiF1EEpGdry4F@F(82_rjEl3``hqOV=4jfvA%f!#r}br0Z--td<93Le%X7Tye$fw zN}z*#GMw>-UUbE5oFQ&1#9c#PfpYRnN zd3YR{knpl@y;XL2SyHbJc%74b7LBbRI+q+eo7{Ug2`7sVbbw>t@VG63n68zKQv&vo zk@kK$;pOZ$xzw3b@ZBcez(^r@pjXrHHy?WIz{R2dUp|Ht_{#eU1uw*a#b?HhGSIj~ z*nrZ9=e^C6Z{PBO*#;~$Y%L5}Tx~h|nfq4(PO4sj3aK{!D%7oNRQOJnW@t z2dyB>ACstHCREg(m#-x~@M#ojtqH-4F}r6sc6-0p6}(WEbZNI4WT!5f**%xB+itAH zL)L5r!Bf54w8B`@EqY@&NDcDi3%Rj70A48uEbKOI`00w^aT5nmRxY*RS$SB}QL!ta z${D*WTdvZ=%cX2@87!;HZ0xRDxhe@yt3uN76qbgkurxe{rQs - - - - - - - - - - - - - - \ No newline at end of file diff --git a/api-gateway/price-microservice/pom.xml b/api-gateway/price-microservice/pom.xml deleted file mode 100644 index aed9fb38b98d..000000000000 --- a/api-gateway/price-microservice/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - api-gateway - com.iluwatar - 1.18.0-SNAPSHOT - - - 4.0.0 - price-microservice - jar - - - - - org.springframework.boot - spring-boot-dependencies - - - - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-web - - - junit - junit - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java deleted file mode 100644 index b12082328bcd..000000000000 --- a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.price.microservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * PriceApplication starts up Spring Boot, exposing endpoints for the Price microservice through - * the {@link PriceController}. - */ -@SpringBootApplication -public class PriceApplication { - - /** - * Microservice entry point - * @param args - * command line args - */ - public static void main(String[] args) { - SpringApplication.run(PriceApplication.class, args); - } -} diff --git a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java deleted file mode 100644 index 906b55c88d14..000000000000 --- a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.price.microservice; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -/** - * Exposes the Price microservice's endpoints - */ -@RestController -public class PriceController { - - /** - * An endpoint for a user to retrieve a product's price - * @return A product's price - */ - @RequestMapping(value = "/price", method = RequestMethod.GET) - public String getPrice() { - return "20"; - } -} diff --git a/api-gateway/price-microservice/src/main/resources/application.properties b/api-gateway/price-microservice/src/main/resources/application.properties deleted file mode 100644 index d7b443b268e7..000000000000 --- a/api-gateway/price-microservice/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -server.port=50006 \ No newline at end of file diff --git a/api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceControllerTest.java b/api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceControllerTest.java deleted file mode 100644 index b1fe66d42f76..000000000000 --- a/api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceControllerTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.price.microservice; - -import org.junit.Assert; -import org.junit.Test; - - -/** - * Test for Price Rest Controller - */ -public class PriceControllerTest { - @Test - public void testgetPrice() { - PriceController priceController = new PriceController(); - - String price = priceController.getPrice(); - - Assert.assertEquals("20", price); - } -} diff --git a/async-method-invocation/README.md b/async-method-invocation/README.md deleted file mode 100644 index b96c1d77a925..000000000000 --- a/async-method-invocation/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: pattern -title: Async Method Invocation -folder: async-method-invocation -permalink: /patterns/async-method-invocation/ -pumlid: TSdB3SCW303GLTe1mFTkunWhk0A3_4dKxTi5UdlIUuhIoCPfuz4Zjhy03EzwIlGyqjbeQR16fJL1HjuOQF362qjZbrFBnWWsTPZeFm3wHwbCZhvQ4RqMOSXIuA1_LzDctJd75m00 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate - - Functional - - Reactive ---- - -## Intent -Asynchronous method invocation is pattern where the calling thread -is not blocked while waiting results of tasks. The pattern provides parallel -processing of multiple independent tasks and retrieving the results via -callbacks or waiting until everything is done. - -![alt text](./etc/async-method-invocation.png "Async Method Invocation") - -## Applicability -Use async method invocation pattern when - -* you have multiple independent tasks that can run in parallel -* you need to improve the performance of a group of sequential tasks -* you have limited amount of processing capacity or long running tasks and the - caller should not wait the tasks to be ready - -## Real world examples - -* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html), [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) and [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) (Java) -* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx) (.NET) diff --git a/async-method-invocation/etc/async-method-invocation.png b/async-method-invocation/etc/async-method-invocation.png deleted file mode 100644 index 764895d7a217b838e4c884ced9df9d0d4888d28f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36923 zcmb@ubySpJ_dYBJpdbiH4&8!?LpLJQ-5@0l%?wC4sFcKjbb~N-cZU*#bhm)gjda8B z2KDni&-eMh>;1iJz5lpoF>~MNoPEyT``XvOjsc4D5)U7cJh*l1)g_C`?jkwSGZD>F$nfeyFe~{bxtxe92eN5C)7*wAH zXRG7`$6YE10+gW+;e;8u<4Cdfsqs}`LA%|Wfa$tnA)vd@1zG9`R?3&yw&g?j&k$2z~3LTafgO9xNlhm9PdbQ-{wLEzWXfwvGe=P z44sb!<90j64EntppX(?3na7D#wGANGpK~8@p^m7J69FIJ<$i#RRN()9GWQKc5$1a{ zLN?QQZ2shHGcFVUlWq3&3W3%;R1wAC>!;Q3fg;pu>VkTqG&4V4>xlV?q21X&f1awS z0_$G&uNi5kl+|fkaqeGiTU#$WQ5r3M8%WI^?S{GzRDQ1D0 zNfg?DMLS3vQs`sIM!{I4+?j4;+;1kw{|V;N^Y`@*m}d(Gf-pUgl~% zTFFyit5>B~`JxJltsWd)8!}04;*Hj7Hsw&i0P-d9hw`$Mxzc#2S1G{-kK!$OUX;>_}+NCpAehKU5 z3k}9lRg;+j3b7rMc!#uyaOTC(k4W0T4*_$0&!)N+5z?$3ayo|=;Jqks=~XwMKx`S` zs-)V4Qz*r+_!L1Ht})1sd;-M;Cig-urv$#UNS^bQ3p8y4X%q`{f0;!`OjQ)&(Vx~G zEw1e3zvF8CWpVtr%M^(dwOaz?dmB2MsEqrd>tms)W?>B(d>nc!vv+510Lm)!Owu`d zn4>ZYl+{$eL3<`?{O#{BUy+|DAN+Z!7@S@C$2Ry-%-n*1HrLyN`OmEWFMgh(3ECUQ z=C<-!yA1Vk*}4WXrlAZ z*FE8LSt8B{;uv>QSm7T6S1khaYlt~ ziHL))-|Ky0_1F+HbNUmBMjm$(WG69u+~I_G;Y|j(A$^Q;O0AQ5)u6k=&)`(YFf1o1|3)@qXu)%Oi1Q^6F@0yv(QP@34gDr zg~Pn{xq$l-#k0!;P-w$3V$bk|!l{x#|FZsgztA)!SM6tOkbB9XYJ!3f{i}?Lytyhm zn#UQKmJ0@IQwsU2brBVBPZ)nLS^WB1glMk|w-fsD{%K6wIz=fo;ak*Z|8CPj=_=_% z|1J|qcudCgKb|d3#kDkr~8U4CbLWD&}IB+?poXPVCvyqX;kK=D1lx1+KSCIUvwHmf0 z2rHMk?yCMTRS-fSZO`wBz=fNhe(7kmTnno{`Kvb(C!MEs*AHWP)M@& zW8&kiq$`&m1h?l~8}XI6s$P%z-5~!-ufwnmQNdS`^U30U<=Ie4`{@rlPTZP=qO`9j zbgEFK+`SCT!KI6zVBM5xws%8tkuRpWh~WeAwFl;q@35BN{_*@SiP(5-T{7?K*CF<* z3gL^c=_`iaUz5V_+sPHatPL{{d(RDzVyY^IfkD4F^ra}~H6J#D1t*9^WpYKn`|1~H zu9GnlHzLjArSjfHBd88*SV5 z6Zv-{ye_mNzaot+*Np=}$GrP_$BlK0Zs`jS zpVJW-NwTryaZ)mVi%?oevy~DAcOoK4_&Ov8$G?OI_Xk)DUe5ICx^2c>I&W>Hcy4KD z30>_%=87~g=NYiCE?c-iD#%s*q*aRI%Lww~0wF#X1U02XJnT{tvO`ZaCeVaGk;gtD zOKJ#eGXKTFtARAvOT2?k1Ud%)V7nP5SX_h)>BP3}_G=Opvt55;jWv6|V6da{G>9|a zAM6^nQ0IR1t}Bit%9sdEtHZlSMVi|tQg)%WFBaE!_3A|kO3Zv&?Hn-@-Y^X<=M&ROq4H=F{2P0v zEg*iXB}gRWAhdhMPA~gU?4=V1%_~qp8K0ez&JSS9Pn)T4nod3#7!ui}I!dO=1?a z6jv?f_0Fv%=k^1IRCZ7j)amO~)XqMhhE(IbEoMC3zT?kI^4lttx7a4B|ps?zY`YzwC>DI?5U z)Xd-S4^XL@h;2=<%@`ye>DsFVi%gH5f$~*@r5T{1!_SHDA7!~!8oAjr=d`ZgH9^8^ zPb)4a;b({iKI^k{kQ&5Hu{@p35R01<3Tmb|YdWhML7yK=vk!Q*uEd_ zcqf@K}7GA;}BGG2YAY5TFN!6T5g-$J(= z=QvkM)~PX7du1e~tM9{K^*awd4^M&TG*q5f!o*DP7!&-1C~d7ct zW^28R2_eD^v;@PUk8+d$yiBYL-2CO3!WUylqWMd-+^l7D#;>tYc zV|;n%ulJsssV-G8?u|lOI3gh9y^eFC&5Nxh)_Epw4M(AagLhwBNf9e6lVq6UkBI)k zyJ=Ig=%xrZYq-fRzUCJkgq5-sbncR(mmKR7=H|@`+DR+bx-t=4Mx@OP!9{uz%2$)C-ZefrTW z0lUe0h^8p8$xRO!7V&)N7FXs_1?g*y^8L`#jFRjjHZcq#5vtKv5OZa0=pXaZ|21o-T|wj=e{|(!&LO1>$+IL(HX6QuAQl^Ahm4zX;TZn@J`N^2OLei};wQBue0& zZ8Y$kW-mI1Ax^Fa4kq?VqUELR(!YSh9VYwyz=%1PLS-#!ZjGyKgp9PC^z^y=f+XIz zs%Ha_AYDqGPidkY!s9Rxk&?#q41a(w@i!!;s`3AqD(klcP*P-O6n= z5M@x53rlA`=QJ;MMC;HiM-veIVw1&u`S8h8m|MhBqw4c+L-X+jM|2-rU}1mWms80_ z-#n4stvz4*V13gBF%l0ekDiZOh-G=)_hopHa(qVturEeB7(lkGQ@JR{R~{AQ?W&;*3r^d!)^+JS-=mH@W{!@y zzd!TzYn}Hv#D2STsaZX-vAq#Isy%L5K3d}C-C6Q71rHx5@;*9HK)Jk!6VpuO5>B2b zTH;PG?M_}c)T-*Cg)b-m(G8jLyLZ}uv0p|2vl*-3^X;P(Zi`0r$! zT-!zH4Fvge`c&E$O5N^SLqFgl!_?rV#zbu3K^I1EV=tlY(*8c2IYX921C=!x#u}bO z1P?6+donJGN{j)nIriuiI01$A(Hd6n!en;$)A^EOuq5v9ja7l&i*iONfk_fpRGR2h zxkOf<$rQa7E8R-a6@=GvOGvglP{NFh@nrI1UkH+Lsfrjt=&j7xl?RRNX_i}egF2=BL^G;jMrDXLqX%RT*zv?0?x@~SOyH6cnraG9~ALyC~3r; z_(O&W>$wtEb)prdT5A2-^~T=e%A6$OAc07rN&fAE-_wKfD}0cQCxZ z6DTR1BS$57(BG_)vWiTF8+Y8h-xm>&thAfokBLq)qR7D<`H!(~9M8Mo83Q;nCtnbc zsZ^Q%{Z-UH(iydru?_n5l_fjOP0X|e^|U(@Do)R4?az6sN{XJ$2<2gNJ`+R zlaoXSZ_Y!TeUE7j-V7H6UBy3I`@JeC=F4o==D)d$6+IONAS3?uSnRO4v0f0HIi8DE zXY>V)i#pw&fXwAxm8BE#Jj$Jic2*=q+|Bp79qRAr1h2}~v2_=i^YGb;tNrnu>zC&i zzyscLF=1#hu_ImY#7oE{L8SuZL=9&}P_aX9yp~L-W&KIk9@RV&Z!^0*xD83btJ@N% z3lh3^QCmi(6eLlAU9P>b`}zL=P8SGhpsT&Cr~teEE9ph@B=>MB3RveGkbHMWY8RQz zT5ZQ{ie!zLRS@QL(NF%&hRHVP9z27}YW-R6LSY1}r&e_gP2aTB{&%px;mHL<5#jns zzf3}HW%f{|Z*QxuMohm{rFxjO3@+Ur5d{Xl+HEWIM6i`mUc!XV=j1}`nJ%|n z;GOmG=GKtYh7qVF4*t%V6Q{0=-LzHIAku!1pf${Aj4e{kqH;lF zpF?>f?HuKG)-NGnfBfTw!gJnDc(eXwuL<9)&&qu7Dk%Qbh%I;|4glQ@96Z5-jY_g?dNB8hBy>!YXe0|&#K&w z9);~~i5_vMh_@*=ZQtDOH;12cVqf)(;Io)>+Zf zL9&e%rf|-A*T@y7N>I@oo_9Q*QZ<$aWz`;O>K8YD!XH!BhK$tv6XZf_9ak$sG1hKt zJy~tO7yl2WNhS=&B~F*E#vrt2H8P-#Rsn0NQ=4!j5`G|jfVI4-RY*ZpN_&*H6C+6T zljq*W$|coPc;`!s#S{~#<;D!9F_66Q;)^(FaO2*uYCqPrUlc!yvX$IG>^3smG4bN- za}-5V+jFz`2i;mI7)E0{k?D>*?MPLXhu1Om!@N?U>&Tgcp72G?*t3QKIP!e6Z^m`o z+iSlrg^-*IatQEzF z5}7uM-&FbxdnUJ4lvaxP6Erkl;pEZU0)C^yukeiVSV|GQ%8_APOM#2XJF7tDz}6d4 zt(Y1X;W23@AwuM304Ze*jyb(TZj;qsWnxz6&tff>gNadfs-Q zW$KP~14)l0sl1hF22p?!hj@XQ!&OwCN`O1k{}V}ahMs?VT76Ch$KI-`&?lghWR2YN z&1P793YAswXgXgA)oEO0dDd)Ztqk>hY53xK#+Q}Y5VJ|CM7=Y~kSE5(Ir$L+)ED2S zb8lc2mA}N32M%NG62i`|OO=ONUNvV|trZ@d6pc=Olg%-D+o-0VC1+jQQz?x$E?YCp z3bB=BesJ&@=7*$eXmD9WTw90FW+y>9VfLsBQ7f`lu70@VGB_&~o|8s$oqAsXNj0|+;}%}*^5(+#I9vRbP@sgo9Qb~spekuz#bUI@efV+|RCVbp z2u>Ub;68X2P)mHm7LeW>`M=?LSU^}Nkl^Y5jNT)r9o1P9o9tKSO*mq-m^PuW>e#fC zSu^gr8$sSsuGQrqZYl-)d!8QNsiBtNnPGDP4(dWaV9eAK^*ca7sQH56aJpZ#+lW@w zU~|%&aJBTSM}eHctF2TMa`Zd~wF>MOFj+|;WA5DhibQ-P-1v*J@xGC$Nq!5re{=`m z;EOr^cAjsj`vitxU5L?`RZyv(lS`VD#gJO_2}y{WQh9tahRQZJBPls%Zm`rZMl!!^ zMz_7s{qzUI|MFLn(38uV!N%FaXlVVy$R%+l#zWvxzMN-?fyX5`PVTZ{eAfHuW>Bt> zAwBp*DR39Z`*y1P@E0U)1-HZUu3UQx9xlerXq%TD`aywT3sUik$TtnSWZye41Ky)* z3@-&LVv^`^KB;vp1&T+YXuRU28U}2Qo{>l2*Nl?d`T{*l8u@s> zG96t18t%9bFC?c`RL{k*z11E`mj-sg=b{g1Da|QhEr540LzZ5)H#VZ)%-%xX@Np`Y zU|D-U>hl#f65BZ8)4-3@@FaiZyw;b=oB$ICsxt6eX1IJ1@UeKA-|o`Ds_ewv6#RE`KB z%XOWK{ecB0!AFz?2*E!T7{pVSGfjWe^`_e55QH0B&xm;Yr78)GtpqKsBNNt_3&OD1zpa)`0jT$1!S@6USTlc(W zh7)Nf%a{h1R7Ny%ArBD>4aA8>1kFzOr|%UMC9L{sNIyE+G08(@*Rfd{3z(fISu=;a z>I(baY&EjJbw$ELLUS86*zGH_DqX|tK;Po@nwM-quusHR|C-oMs~d28V4Yz<#l$L9 z&P}-nBB&skn~~DN473ZD=L&odQV_O@TEJLoWE(gL#wJ;81$<89b0KsbCTr^-<`BRF z-(*(r8*q6j#}NBG?eqzyF5t*$Om1%LAcU`C>G|y;RGm@1E|ODZ>>jbPR3SzxUk;MX z#QK++EcG1mjLc~nOBk}68v!XHm*GnsST;keXg8?vK;Hj|y!(3%O|2_xe%u%~y81A6 zD&gV9YPf5RaoKNf^DdktnA>*nJ&}-{OBv)hwFzB}vb@UC5EsgJIL80Ryy*cM zl!cf*hHodZ>9w@JA3Q|Lm}LP+e%T1Jz$CI1)|u|~5cu~nP2bw*Jg7%VS<5vVU4B&Y zpz^voIa;8gFY1dp`?BT3^6;s-;QE_ADk#P&MkmN2_n4jYjH!C2PByg_50JWhA0 zG#~jwWynX`>qV!HGK4{CUA@DbWUe^VgIbQ$g#Zhk&X2yu^0rKSfF~?C61jdKFB)~Q z>v4^Lu)1M&3t==_{SdWAdDCB`qgZgUUIjNy68zJ?530ZcU;9-&nx7+gx@r}+hhLXH$)qNH0#R~Bknv%?K8}e!I$}%a zT0*nF-0NKBzH;AcK8G!DH(k_g5?DUy!_O_ew$7)304E~7id(lH`!GfZJ|mP6p%H~` z0<2ZN?>FTBCF9d-RH!7Wg2Yzu+mO;Nm7ZiF!QoN7olQGb| zDJ0o*4z0OCz{3zZH!PAuznHqG>p^h_Iu|>*wF5~HHgLzG=T)d zCaH7>6!AVVng~7BMh!T#|CNu!afz~!Az9~Gvs+UZUkWIVbwUTLI4Q((r={5skt&V! z>^UQ{b4+#IMXGLGLS}PsJ0_xsnF5c@`IEi7JgNPl#})J$l|u#7E~^pCxZBT@zi413 z-vv$XBJ@QaUKghap5c-awzFl}w!EdTJcxF4C%taFJ9(Wqd9J2jT~;u#rkqWNdIT7k zi05H zk%#lpgi&UP(_bGn_Yk_G8sF0TSqEHgNO4#qmTd|YX6B=+z{1n#!cO0d4_96;pB!Q@ z;!T{NU9pUwk9d>q2Wsk6pOTkMNX_YRO#cw)p&b4YGfZyO% z{{bNK?hmF67{Iv-1eK|aKSM2r0;^o6CeWGaQUc)tw$$w$e4f&xOL$qCuT1#-?o2%U zz@KM}U@bt=oFif4AKQi0-`2|0L|oub7py8zPD)`hwValef|;{s-G9vlVOQzlxvmvm z^$G`VH&rec;qaX-7nR4%gmd3FHQi&H-Q{MG7&2-h(QExIsOc0@JXh%dWWE4*9p0;a z;TMTX%T+!V>&!eN8QVe=Qr}U>Ss^|WTAF2@%;V}y!+ssdBw6WDRf?&6{0f0h2`L@J zZgXE*sRaPo8Va%H5w5XLjx6VoY`Un%f<;CV($9FXl}}T;w66Nc_*MwG(%PKuzG&za z4{LKW%a1n}DYz-RiUr}8>H`jV7$SF(kraEJ_S{U&zhr1hhWv%>+I@vDTDiCD4iZ_f zp6c;l;a$zTnKV729bD1yVnz=o@~S4+BdH;TH<9|yaD1?SeZ|@Sv#Z?GJoBLnH26Z( zPgiS~esdI?SgMC~M6TO61RRSnvA%o9X`w(|5I{78Zys>@D8~H;R=@EDxY1CfHsI(N zwJ@|Z1GerQHd|xlg<>sBDwC^;O%4ZVmh1ayTF^~>-x1~KZ}a>p_|dq?EwnKr@(|+c z!=R%Q$QsrNZdmD!tI!s5Jse$6zHF69#@+3k`)=p8eZ@TLwM&!d^!?Yt!o6L~k=+-b zp0~cbL)I%9vJo-`M0f<$$F~hN-b^)V?S@jeA$_7-NX3*Kjk~m|s~>A&K@!{JwcXM= zhvcQRu2FirK1k*KDCiN141mepy9hDXo>#(cXi;GnD@2Kr zBNOPBYlC_~WGlbg;DkTuZ5w9nT6j3j7%15fi^11@KddJ>SlFyCHtE1P5c5sacw#?} z|5^9+uLEu2!+nN?yqA|+iGaVhmRdusYPRx8;Yw%^B5vR7K=(U6Te(cAHwcE8ru&&% zsH-5rZo7pG0!Eu4#69Kky3!>Ufg}@^Y0=S2gYnqY!3emN{MYEgH=mszLe@&&Po7cx zh!+5d$$ND4X^X-M$5dBGw8j%}ow&*h3NhX^8+%qUTVwHO*1EhMJj!wV=A{FHKdCj# zOkKBL6@F2VlIAJLgny4b8b&I$J-EOf^0clIWCqO}K_+Far#*)DoO<11TYjciXQ2vb zrZxtf?SP^PhtGX}lD%u-jWKek0=n55`3&51_>!6U^pm$Y{4pqEk~_0c+?XB&nNWK@ z(~3N+(9{!xcRnDVa(%(Mwgbd=J?Y@!f!Ib^u=!ev!4#$})=N4SAjWo%jQV{>VGw@u zT7dF&L~|n6>-2>6a)_dE#%ZcXBE&;OC~Ujw(ynCbvIb*r$T^*jg?3Kk;$Z5976r7T zDF;i?pd1|Fr(J6IHdHlJ))=vozASD$s;jjZU2agj{y9jPXtfJj9dTd@IhS}j_w^lI zB-Im!AbitUQ(}qIhg>PR2)%uKfqsuXJxh+dc zT9j0;5Dq*JscH{ssIzameBZrj< z#+BeDtuNn0+6F0E0)2DOB15y=psOa{id;a5$gK1O^mww^li{E`!X#o2=^MD1!zI2+ zj-ZzeMLKsSm6Oy1J{cwsQHBLO608moo$*rp$O1=94)*X`=J^MYVX7LY@55I~?q40e z=f%ZkS|5f0$|Qh}v>_(vT67>|gLLLZgNJgaqba*BzL#vxq9=8nu#$@tcRY-P!*zaL+#c2&qLg_&!xwY8n> zDhtE00OjOE^tX)DOXYX#aW|C^JMHP1?KDw6mEj00j&Ak}DxZzOz%BVKc0oZwVd19A zN_zFeq9O`@N2rCx+FV;u8$m*iV#Xv%8)2u~^>Tn>srk#sRF#5rEVD)-<~EKRJ|lQn zWp>Y#+Q;xjtm+q2a|_hUN}5hBW^;4X8x8vbL`5?-4(}wUA;$zFX>~Wk+ZE`6rrNJ^ zq257=27o^;sGHjGbNeV>;rb44ZEXz?N9rhcEuQrDh8(LN$K96hKL2(@s=UUI!2)?R z-C)r0Z9L52htk0)baLu4jHs!kv|AZ%ZEcYD5OX@U?#|B6Fd7MQZOtWFi-{@sG9#cjcCAopf~#}l>@MQ zV`E{IDmaE!KRG#>9A*&5{+|pA0IJLz-|T6IG^PyrdvNzITPk4>-KB{vWSWYlf={uV zI1PN(klI=im|R!Mw25nNpv3HMZS{HnygihH@G7urj@&>?@0lAgU~U{RATRF;n%6Hh zxJ|na&Wyv@M7G{C3j?m?{4?=VA;(22=jr(|?MM$`wrtr-1|U43>$hmXTM9<>x!kAS zx@YiaX=%wPPD@u;&Wl%FhDilreb%Uy7|8^ji-%Ut=+uH4r^LPr4VJQ5lNuLYxBLgJ z1foq6y{_r>}$C^cMLlqQb|KE0Ex|%_m|FE?#wH9IYFur2K=W_1qUu z*450oWzUFcvUaCI@+el9!`c8R!wGuWMMge$JYShE(kU-9)6pD#R5d-w#SzjPfAH_z zMGV20H)0V2VxOP7wCY3Zq^T{h&d813wSwp*DVGW9z{EHN4$-nQBAhCCT?5N&Lf zp5>6_!nL%u`R!Nw%`mzW&BrY*@v6!lv?v^rNZk(Ns_z4_90m}@LW|&jq+|%SJ&p}_ zu`{Y=(dC-Ln`I5yys?MvmMUlnmP6bZ&(QO1xgatvrIXfv-~)IrE}OZ|X^w16*tZvI zU#euyHNVPG819ZTtwCR#yd#20jKwxRe=r>NunsP@^}O_1Nk)lB+Zr!lQR?blJaJWF z-=EVAZn4A|E-^&tR2-j3^e8_`Sl3=@|tfr|oN}^-(hmrVqwN;In9D(E|M`ysMvEMZ% zVWO49)@Okl>?kuGn!28RP%6_^YK{p{tGpsFG?;r~?gp9+N^FJnp|MBYx{({4r@5J% zulA>khDC&R?VX&QwDOp!8TFTPgO# zKRYu+!0hDc_)M?f`Nx;{;9t+(A{(-ixgs3MqK{RC@k*rhA3JoEQCFUCv|i-66ZF2# z9Ue5#YiJsIkP!WljsyWq=$Pj{9Ma~X|E9^n#zc$&_sZywnqkteWVDXE&7L}3nfyHR z+yj!m)7AEo-BshGmu3nqwLly-H8G)QU}z9x$LldETZ45_UyHPvvaMw`r_1dVSH_T% z=Jmm05gH@%^Zrj#JI071|Z78F|I`akP*ZNzsZQzeEO^yzlGfd z6I4OL@Dx65rqFd`GZTWuu$L z{M4Pr`*?mjh;SS-D@j?NqE;`F^1v*FC(K2vxa2D+|kO)%+jEy;aFj=W4^$$}9C?lfvVmJ0Uda z-cC_@Qskf+q?z~OoB>rmma2i>QS$rHL^JuLnONaq&fhOzPB6xxn$e zAlEo(d&BN%Mz=rOMr^NqIBxC%7v>R!kN+qcqLB%R8zmaT118FY+4ZSZ!T(@_zcdJx z4tc@qv9nZhVy)xJHcY%zq-ib*Ee5CBDQ3om#0#_`W*m}U2y|Boq)Q0oDJPa1kWh)< z7l|EZFnty%-tHwh?f{?&xyXR5ih54#Zi)1lMu%NTn{`p5ZMXs!A;3*J}(K?;((7&l87 zqLex2!}%r(4~^SPwXD@4X zH2$wRuOl@0q47bZZ=5uKN;Q#96xBFUByh{-4;g0@Nkm~a>o%>irRQ?7-?2?fh%u*c z*Qo~!E{Td+;H%d%EAW8e>K-07%YCR(dHS%h)*AtuaZ^fOF(HHrm_duqe3K7i0tozSV`*FygE_AZyyOhLGTf zFXJWruf{V;&{fo-TuC6$`X|13)(~@*D z>FxsU9V6Dp$RZP286^(a8YrgjIg0zrT#B!_AXIjL*LI_v)X%2g&n~HX&%6J##qbPL z7HCvNNe-F2H0;h9ELJr70v82J?}NN;mA%a{U*`NJ?$P!5LNRmIC{U z{rb@Lp>ah=QF^0qW}}M@w}2h1P*yRR@me(`{kLg&EwuxFt8<79)3lp?+2Igd`%{vm^#w4!vNib3rnzRi-5z;td-Lwa(*uB zo*RX9wmzMZsn18m(=Qd-pMP^}uMQ!xQJts9N=DKMtS}~fL(Ht4 z$sZnudW<37@ol=JnnEm&TylE2sp%>Y=?XxU!hb$-f`xSpMCyJ+Q}kd_{=9{mtXd!Rst= zov$vYV$q%nT^{05cx>a@85$JJwzhmiQ#R4>l)5uTv?!Nri6?5D#{VL9{ym>EsH`wF zh3COTXP)-NIbH?s5cq1!xlAxA;8fAVFQx8DhSJTfK!a=jTPrW7y)Wg(6(?8xzX_IZ zP8u}DU_I3OlegA}kpD~Qr_v%dz)tDc`#BSWMyAkP5oykFc?UsOXwA}Y{(;bw`s<~m zo4R>%s(?lsN-x4+CAJbG{bM(?;*UqQ{lJTmq=v+JGRF|cO_-Sb3 z-0xpk!1WW_L~tQ(WAR@idQf8(82E6UX1eVbGj(3@zI#-W2-duJA(DrqPLsyut9tTj zcfK)JlviR=I(Ip($w%Gv@zzqOBjtQ~>v*gXadqn_Po&>j?;$_8no$qDbB-eRy!j=w zLFv`7oQu3*SR`(rCo6N4CQF?9^IXT?STC8MKc3C8O?w}1a|}5Z)O$RSa-JkKf~wMk z>YvUgwIG2#Umi^T2{cHY4xq9jIIkhbnYLseN=<9+$okFHrH(O$WY>As&%IB8?2|*w zJ}SIWiKp~o81;TY5@V?BeCe)i)a;sr4l%p>yXL#D9oa)m-H z^O)VsKuJM6^@B~H4HD<+G9DPlGx4~hk(Mvmc&%1Gh+Y&z0o{ora#hKDDtv3IsO{IA zhzMe@H-kON2U%8~Wi}Z)?~GuEkvn=^vrZy(LT)uHJVD};gNlgLZ{KEtW{x#71NRr}3(&;Mq({)fn&d>w@NXytwa?G?+CYv&Fi-Sy~N3na>A**B! zkA*@Mbe3!&wge#Xth6VX*MSzzgG;_*uo=3=z5xU)Va=wnd33~vMKKTlD>x-|jmaR_- zDQI49L>J|0Z^#~e^Q~-0?rqlM;_LudfSK$Ju$XUb9OqrX__te-`^0dYCEkNq%F+U7 zytURYEF_3ls-bPC0$13xeYRQerJjlenHsChH&)8RY5QXo(JdW!hK#SaTuZ^cx_lg} zKr)uE0RL4u>&tvFS}w754C9pW*yMKR?Yq60=Ly`^@}D}=JBq5)&=dC9;5dmZg3%$*2shHTh9H_g>{)Vpy=-7h`}6WUyMoU>vzq%Oa&5A7lgwpAwKw zi^G`Wq|rybW~$R;qIiJEmg)U3Oh@cPYe&~4>{@E^XzS$2>)H@%g2Hnt?+q%z4$x7kj<@r5(^Fp6ertYPIJ=o0x z49I^lpEhJ%_OdjATUcjLT2_8$%?wEzTc8*|+eutrXAZrB6Ec8Vnhfr z!QFnRGr)C#!M32zRLAD!q`i|jX|x*HB`smTis zvEJJUdE&ENnXM$9cX2vgAh^IyYvVv70s$8>hoUAm8kZrhYc+{#Wh;@d@`F#(%<$z*UXrYI;s`TejuB10Hs7`Q(&kA=H*%D;y z8$etY$+uNXz%>>!7UIIPH^gHU3s^jT2lLy412(F)sLLQi0APgOic7~P+beW*jbOHP z*}YnyJvpO+>MHR+yTo^58ajF*iyPFI6gk~5?(v_ddHw?~(dkgHMaDpAYAkgUAW05x z*9xxr2MGV8r|Qx;4Dm-H3N0hDtAPSE7Qbv5-@8ewE#Cp5C?+X{eW#OaY9 z4ipW4*RO2P8zajzRV8%)%*^{^YP37y$W=|u^{6Iz=>e!TNriiHqpAC==cj9V-;D;_ z|C}O2aHM&}58&LKZ z?6sYL{EbqOyz`{Qt{bszM3E*%oSp1mB<=&L`e)_imozYaqgc>E1zu-tGU_wDi3HF~fQC+!th zq6_2>uuvKlnST)Bx>A^?b#J&fva!Y>gU7Wx|L!AFLXqUT7kR%{JAze6X_uo%cZ=N9 zNp9KUk5<>Dy(zTx2uIs2wb$R2*}3ZyzEP=ywh+NcQj5`g_U91S-!DS!_<3pH_?^4uYl-0IY3Lw!)po-cvr|#M=jnn|2te;x zv%z&hDoii@l6R(&!X}`I)DUC4$D{JMP|PT1q_GUSOrx;}KI#<>qCKENOK zWV+6t+vw(fGe?WR7I?2HkBY(Z?$;ceIkS)S^<}sP?=vOWSzp%UJI{jd*^%ts(pOrK ztmc&~Yk2CQ9%8|zJeSWUZUu_)NM}3xY&43el$(w$DgM43o9)gJe(+pbtMbH7S-;Bv zfj8>m3|q+=oADQI>%xN9lLL!xbQNKp!7*d8C?}S32^E>`c@`u&&;^b0PuklWj}uKs z`3;%L@nNaPC*Uk>x9OIQARzK)mrfGZME!WaM6k@E>liFn#!Z|>3Ea08spF0~?aJv_o!p19U zx+*X!U9IZoJLsVKb*C-ey3^!}U$f}jv-vcaIdVo*KTqGhdR4;`!JYhyAF3A{>t4z1 zFsItU33)bjmN_2#oxwUveBf8>t1qdx3FtfrUnslz1Qo<%E@f?nU?5n3A*u(XW=y3W?eaUn&xNrY8Gg5 zGa3ff5modrsb%j9D6%(W;-UEexrGJ@l5x3~0P>|_?bndT^hLLtld#9gPt(?>4vr9d zsm%Ky+$z9dB93(p4Wa8~amkhKVdB;GMr9PVwd+ z^QNJLATU(HTB-I8CKD!(mW*%apL2&bVhaU$n!*b9d3ztNiE>tffqo5~jh0J+2EZWs z^O{=_rkV1%khAfu)Or$NURxjU;-TbqUUC?uv)v+k2t=mm#@keUovRTAE)iuMxjFqh z+mv>bcGjNsDxIWRQX-7XJuq1jlDD|wxfcCY2X5IDV^ZCK{vGl4g3;s0+`P5$|7q;4 z1ESu#w&B4514Tt71_VVy5MfAZ1f;t|sbT1l?hq6u2Bf>YyBScFp}Si^T0pwt+oPWQ zobx{S`+P6|>BMi(+G}6yTDdoS_xWHn_qOQgNH0#_J)vbVqhqy+o#VL~(~8D54P<$H z1V$2E85}_4K5Mp$&&;-?-MvAG(df^cw5YSu?uj$O)p7o#m1qufO!!ZcdHV$6bJ&ow zrak~6q*v5fnuSFE|wvBFbJW~7fQ2zkBVbN_z8Up;O*E@Acm#XAoCVN8mHHo8dq z>V(0&H7$U`_`dPLGn;5*#2dwA<4C=#(E4i4y!0}|Ro&kb!A{-;@lqg!JzBSYILGv1 zJ5(T-Jlep9rF#+4A^Tcbbem-^DKs_ynl!ZE z0DNszE!jG$;g#J7zl#5V0p^;#^ZzZJE5QtR<8V7Gyl*a**h>@|fKO9PBduu9SC-wg zqqQp(zr!%}dhwZ17T(`oeE-cx6h=^+pE38JXcyGOg3E5M8@s{F4(kFKYQsnxtPsx? zldG{`-fv8^4BUV@ZQ{ht;U@C|Cj5t*0_wL>`}4BLCq%K1_*`5=2kUtx2f4Z|dqzWW zo5F%{f@*7}m=oN3r}ZN71A9iuA81g5 z5oqAG)rxq@sg6YPAWV~1+ecpY6zQr&8{V2y42oK;#WRzl`qO;(=&O@q5GKz?td5|CS*g4$X?q8x8YO4kPilYlevVSV?WKWOTXJWxA)`pJZxG z9yaAK;{f!-2AD+%E~uiAk&yw3(Bh?lfnX8du?tw=y*e?`a(23CW<(k@LS@=VHxA(> z{SnP_r`=cNr3>20Zmn72W*A7`I-+da;QRV*FNWLYWr0dTX!G*(%`Gkc-%Uu5;$!zLzDzWl#((tGT1pd{JX9|1gOz{=(H}1j<{+gJbw~$yZT~T91h5|mEHo=${`~k8VO#=gijLb|J6V;n~7-W=K6%;<_0G=sl zdSby8FO#_xAb{IT=nP-gkd|UWMoSSlRY)`*gysQs@CZd_N?d`GmH-_QY zQF%gjbyBbhFd0kC(Ljxij6}u6-0=WwR0G)*Pw(>b^48YYtjACOOjgSx1iO)PN6z-? zr^~%W5K3-tZWk?YHU7JEik?W{#jr3dWKi5{@-e3z)4F=O^;33ZhDGP9d06Z`KKPmC z-$2z13k%DO#S4%m*?WY9G&D4BG?Xk4p_Hor$GdkpNo!=^mG&qxEIP>s0ox17BB`yd z?eFhzY`q(QyX6viV*KFXASjMmS}lfU`(-9&Yjo{%l_GfzTRww*P{P^#){IiRd4z@t ze-H$l+!ahQh(7s!WEXO1aasso%1?)ryc9PtuKA4Rvi6e5$B}gw9U znLT%hg6XK;(gEe+htf5R`!#Ptb>DH=9VMDYzs;pG65ZNohe^F%H@JU1s-GPKa)Bg~ zBq&e`LE0zp!{H6q z8-=XHjZ}?Vq$w3^j5veqMSbLso{sz(sgCqQmOYbn>Q+IK>2CJ9%f*w|Zsz3W8FUT8 z*OpDcs!XPi+eh)l=?$UmMgL zfeGix+Qjk^qWt}LTlM@qoV=`b+bg3C*=%9Oh_FpslYErs+Ra9ivE=;dfyUb<^jRuh zyy6KGlhw=?Z%&UDWZsA%AdqwS0iOg|m!KEz5N>Xh+Aa6R?f*@~RMUG#u1RLs8kWJdUR9^=b&B~K z3zP6<%t)!{$GL!X*}4Q{qO%J>W~53u+|Y0ltRFX<=l(6^8)xh9Ey3B@kLOX_l=E`>2*Z*pglk)0oC9--@4-pPC*jw3oE<6vo46a80)77Pmm~mDLJ~k+WyG za>}|AmegehCtt*K1E@mxwV*kHgGH*>2@A4>!|zj9T|Fx5z!!^*u1Yr#D;CVdwI&#H z8w__R-1}OkW}PBIg0@4dFJg#I z=hmR~jh^no3qb!pOL~@VGcqz%R8_$t{eHEVC=0K#l9bDK>Dy;-w~fyLb-YS0kz*_J zSV|3ACxEdhbD%*Eq7>C0$%y}!m>&qUT+hzV?jsDGdg3(n)11(48B-!vxGSb3f8{}5 zd%fE+k(ATR2P7Ba-CbQ>6B84CeSP0*8`1i`KQA&1wH&I9_>!ytdbib&5g2v(CC`Hr_%#q?;0>)P2V^BnkhUB)F#fiV?ana0T573W>^pILo_-`c|Iaq#Z% z82Y@~^r;7L>FDn6?(AIq@#A}y?4QYfa`pfutQgC^jBo>p0Tg_J23-0xmMV;7MmMI@ zpx&Gb0uk}~$plcs#>PfyjQ-#*WtO<6nTDa0X+2!cbfn^ znk^R7Ea5@HnYf}y8aT(jkqi-r74nG~OeE%f{Y{{B^y`-a{3G-y zB8t5Bot>R4JcqASVez9PFV*)K(z-!5@KnIk;&}yZ^Cc`|RJ8~ej^VlzUxEA<7BbY5 z2-M>-^7N$b92y!Dc})RE%KVc>I~P)4qe)WPskPgGHW3`;1BZwC>b)gqk^1C?%&xgm2Qvp6;A)-Rfr<%ZW!ePSqr!Q3As zc-_S&d-@8FcooVr4lN7K&lSasu((L$bjtD8)$BOqS`@#NFeVTSk>hdyfynYc6nOWk zP0&sq{JnZbHhehG&P{9%?ZK~Kk%xD$#E9Etj1`W;7#*Vn59dW)7EZi=F~HSEE|bm?D{S=Re6Vu zotoJH!z+m@{J9c6nws!43cXM!>^{EvaP%b!>h$m&@sD0i!C@V?8aJp|DtMOYJ0k@n z>U?2Q-ba}EGS>{;+}z;s)TNgKz7!-E!{-2^`1||6BONn2E)ppbS>js3<=1B;OiXBq%`KDu9H)-Ef)TTLZ)GD zGXM$@AWU3b@iL{O`Z7eXg;=rM0%)75sj0tCr?A}lRso~x*HJ9rNx|JlC$(Y5lL#4t zYC$C_Q1|8sc-N<-m-VjIKhKz$M~M6*G!;q<-|l#nCR#SS1uBRqe`U@ zFmk%y&0VuZ;SI9*F{q4SV7=NDkd1l%6MK96q2b~EIwOGfZ|I&+6VX0s4kV*jzD1p) z01^Z|7@nUDkmCFIM}>pQcn6~bPF0SZdh+;<`hUUK_l}BYEl%`LU@D;UAJ#z8@3ZI> zmRS%^0cFu3gyicuB`YISke^Qwe>;mw7@qW6SY9QZ5Cj!|O}nKaKe-Zc(4H2-L;*ys z2TosnT-*~wSt7DO$oUbYmH7Dh0WYwt!9M#n27UVBcsD*WFJJ=gh|k@&t>e7XrCgZ* zBWK#_{+ty$p!Nj@wyTS3YBa*J0rM7l>yZ!_m-q3_CUGz_cv8%;BG{IC()dRw<>P&0 zc+~FYbc}f2N@{CeevA|gy}t<-O2h$p!2?^a_%^2~6f1Q5Q&aP_`)ullo1V-QTqT6k z#0LWnTr|2$SLJeYl+mKpiI)@xViV0QEdlcPe#Er~nK~xslVKQ!BpRl90Ag`u$ZvCe zJ>T+tDc5ky^(B}AcB8e1{Yz>&MW^&A8{Peci@tqt*Qt8nN}WKf0t*s-L!Q1r4zj;< zMBI6|sd>c&H90Xo<;VQ^PRsejyO^JdDlRRhOgQ?*nLmvPvSN$)6v2S$P{wT(9x?0q zFERKzIxyibSyDadM9LwZ{HpjR<*=WU`YewcdZoWHWR67PHiz_4Ji>?rRa{o4w42EX z`7}E_dvxU7Tit>ci*yI^MR}M3&bm8!V%&bWy9APq?wgcYJvqq%9%KhKt1mm z(OhvEwTV?3&I56vku6{M_V!LrTzjiMHNXz~Aeopt4QzPEzK)r7)RNa8b`dUYH2hST z#rx2J`AQjl9D$l^@xB9ZJH7xQH%A%3{hH+}I*s6EaO3(bQ11YYsJVaiTk(}RoxcGX6R^f7?=5^Ub_qz?MW zXFPR- z7)~K7EI+hE%SHL+VZ$<`03pY$8etDo0W92_;~*x)HsHbj`Nj`u6}ISIJ+NQK#@R~&xbax2FnOUu5o1A^ zJh}#pShws-6NNwcP)}20n=`-}+j$&M*tf0u_7o|4F2Yob1`)&+WhtNqSJX5#9$vYK z@HE2R=>&8F6yKW+X5;;a34#3EK_}JKoF+&)Iza5)Sorz1D~SvKj6fbBX_$PGfB#U< z{pVm0J@C|Wb8~?sP4w5x!Jvr%oZG>i$;*%c*zw+4Y+@p?I87kliK!w@3MA#U*0-_> zroauuPl0_5j*pM;?Cj*-7zC*IIAGR1fb}y%aMK8$KmXD}E9J3;+#8@_16MZdGQF9pIb*#1t|JEa4BS7@B`BxPw84V0jQbT|+}d@UsC%y)e8)ahWdT8#?Hbe*+<- z))Owqrnw3j-b>e$H8A;Qie}+!V^3~)4)UrX?5qJ$u7v&u;Nhx{5P5Dc0)e^LUe^f5 z5*Qr)<+?V05`Jd(U$THCAy>U`_nIG-gHhMPp#=Ud1EXcr>9RbC0YBlpj5J0goy+1ZE#F4N*R&D=DyVI_Bp272YAl#iLRG zGt@}^j;)3|xwdX_iu@q7%dC`GSgEnc?}6J7R{i#1Gac$`N;jm~#IBg$Vu-24I?GvE ztdJQl5M2Q5Oh6x;PrLP#YszoyVM(RM#l2?iS0AqeSQ@`?lHhv!J)1-3@=Dwtz%2G8 zbdBUMC|YIrk4>*1ptkMsQ!<9lrM?RZUVaXS?tYJ)4Tj80m&Ma}_8BSpV1^k6&}?sS zhlYj{5oJ9Th6{)~5~Z|>0N3Y#mYqgRJ!ZqcE<{={erxE(0Zv1#`-J-R$0-B&Ko?UD z^6II=$cfabu!X_Uq~Y+k4*VmX8Sba58O=zU%u>)xW2*%Ys~$j9Af%<2VI=<>aZw+B zBLEu{6x#?~D!j2yjX4kpV zHu8jFshoTadW24z0uBrjxxIr!^uQf7~#;Y0hM-=2FhdH)3xwpW^& zd3oJHq{#^RlY#uOMbwo>$dHK04oUI@PNb}~Gz{c9zTX5GCiXSe&DnYE z)KfM<1Dh%07Lu6%WTYL9#(oYcA2yK3Lr%w^I+^{&ZqDE*fY?%WbaZxh_HBb}Nr0HK z$N;w$up1CW1Mw#ak)fj*k<9WP@KdA|_8pQoH$2~oQ z=wyMF`RM}4Ffc%CqiY~QHEJWn!^2ZpE`8Fi=? zfetZ0W-lfP6Nw&_h1bol7k>-_`T9XH`%~j>5h?F_SU3W(*($k->yUt`gW?%p!KV-2 z%83i3DpYPEv!4P6Yr-Cjn~e*h1cM-N(P79c!oa~{nEZOeGhE1BFoGClr*+{bmwTg3 zfTuq&pu{S374m5b461x9L1!kF|82G4mis{yY>@!+>B_G}9NkJe@V=#}MkXeBUVnpV z--CoHSb`biKApSbU^XW*Gvr!m(MkSn~ zlH_ zWOj^~M0IZ#5mI_5TRSL{#LCXxTP;G6~5`vT&h zDdc(&em>G5*`BJoK9gzkAp`!*qKbY_1?^1|`<8g$cwA^`Hw%!pfomzSd0iJ57dRZ= zZNm)M8syV8_6!p+aWa*)-$b}RW%V8ympl3@%Q(P=h3npGaoQJRw?KP2#iFK??q^uN zQJY|7k;+fI$V<99z(b0Nh`_i&0@p^O{OE)blPj>4{MjDi%<_iG&CUQe>AWekfZ|e# zihy)c_?^{dD2qypmL~lN^xZ)I?D_Ter<5UB0#slFG}eRLW&^3L)F@Xz-;o-5=pfqb zT>Yp|SfUcvOKs8&ZB|+EranR+&`TfdrBK_7G|JUZ?`GQCR1~MXa;B*u-%Ijwb9;bam=clH!T73KEw-bbYj%<_uQ|`%OC8F-M%TJ;xI6 zheTaE1BJNvfy76m5)=7ffAc&rJy9Bg&gg>dhiDu<#8ci2`M6d^rs41#ijdp_MZGhi zeI9>~a62z&@Idyo@_VGCc0kN!I7Nzxs9O~b;0@v`)%f_ea39B_+0t*p{EqXT?%Pf+ zfwTd8w5###XnxyUWD+sRZ&f!Y-{^D7?G(m63lwezlM_b|HP4nw><>#MnMu9 z4{Q>9taLFGFj^qza+sQ)PKADW(KE&qEa~4v9@?GfPh?L#Hlj~6K8jJA&kio2BwRD8 zl=tC6DM~x@TC8U!hL5BezAE9Ta6XhwE$I<;ir%ze*Ceq+S;u`ctHKLwMK5vV1;w^7 zkU6$xVY6q*{IoOFcX83IB5bGyMhN}pB2G#Wh$J*MT+)RkQR~3l3b+l2EDo1OH49yi z@X4JdTFy(lc=z|u8uU(S_)DCdZ)gW`Y_9oftMB6q-I|u0eGnP49112j%;N+;yfWuV ze%YQjYyX(z;iW~6nT5KDf9C8>}#yCoj^hNTs}1`u4b89h zA#xl=Fodeha(=C)^I2DPVdvz}4)gO(eiRg^gTCq}r* zM9@HXM;8sugSY@d`Mg!FUW0e@zCO^zBdrHRclD4zbnm3nybmG$FsmP?|6JZRz=K+TNmcugbi8c2gXz$kPb2hHdvZt#ui2cP`>Cp#+gh+*?Xn^ z=1Kh-W$R6dz++%CMED)I6BE@=&QPW2VE#p+e}iFt(SxDy6&{6q-9@i3Gkyo&&{Ei( z99Rj$M84mSK!QN-3!Bc~EXfVvXu11#cAjO;>)bVr*jp8{Xw znCC<;Kuuj38w=tG6xHE{dBK&YB+%-lh=1bQ(VHrIwP~qkXg!nv^zqPT2*t0mCBTn% zpAQUVW@cV(dUUWErgHwSHh z&zy=`Fw1>xI1<*u|JK&5mMjj{oDa}bk}GkO&CPUZzp3lfB9Q#| zO&w)IHaUWJC4OOv?q)q|QBgzf4c*T)R#8E6?lm*gkz&7RGVW>hUn*7?avdQ;?_6x} zdv1oqh8>4|GenVY4;>qd)ckvWeY3PLLyaWaaiRDFZm5RO5=~jQ8off}e+{y0#XI|R z)yJcf#T zf5~G`E~V0K|F+Tcv))2vaGxWuZrC2w8IO2PeB-9JTFy7L{+744R)sQ|)W)-Nc)B*R zQ2;y%jNn$>f zz17dFpgy6)eA85nQL%2HY)kT9ex&3>=`=7ErLO&Tc@Q$96Gyu2FhJwn1W7Q_ibev0&|(y23yfNCj%KD{Ziw>NWmx7N&1zniZOD_sDYYs6L3!(hY1_0l8Io1 zu21f!{9pSIJjopJNm_n+Vx?qFY>3Y5-*EXa42wH&KyAAP&xvgucy3C1pJAO}ch8OV zI%vwbd&c+F_nSrckcQZsTW`|(TSz5unsTh_=Z_TM=`lezFK!>cf4cRep7%uPAr0Qu zxRkk@aV$7E4@f1eINsE?cqA#E7pyqv)EMR(R+ubq&$RdTk54MTVtKXgTAPrA29EAS zWkDG68jauctFHiX&tO10m@YXgU=P13>FraX#IIwhH%5wS03q*9B1soABQ?|mWo);N zFez_@*A(zS(j;i9Q%{9qw8@g#5DHS@V9+X1-3{$^Paz8Hp}GjU1ws!G?q=WdYfUlX z_c;BA$5Bb{>R`Sxdz~L;dz5LSp3k|XkbL?7_;^#ld%erta2v|?{A7}&;7s#DdEQXg z?(E*7qJ=1ZXb_=V%MmOL+lF3f(|#Au<&xu6l<}fYwp(f`1PgNI{ev^et;e{ViOOxc zamW20N5{G6N1tQ0rw+eWz8fgfNF9=t$+$M8I`>SeVxzV>jTskIamB!PG?Q zz5nZ%`6r*A6i%OR_;*h_+qoUhwR$Wejwdb8MDq`8H)IDr2HDYC$E$QIa7xuh263XC4y~QuCHPKJd{f3}>5V(slaR2fR9mvqr^+7^xgX}13U2gg z4PR$pkgs-u6SP$lsTT;*jtjLLFEOqnO1+zQ9*m9emcr!sIv&}!LLhH3mia}_TfGvZ zvF>)p_0y(Gck7u$?stA(lgG;*_ZZKucWER{pyrW0dEKdp%WBvAp+b7XCr7j~dYle~ z3O;Jfw|>+;nN&S+hGz^tZ+B%89lc-{P_3|Ujr`inw&2^&Z4DmNar-YVXzFoKI7H`f z@N9osl&wF`FFX~!xT!+-udpU8}@xl#ctz! zVZE-#ENvEkC)x%$k~30UopEq@+XW-boh&E+lV=4byCpEZadCunrk}?J$i^cqH@rrm zZA?rUQi0J)uyb`Mvr}U>(qyifQ2;pHODf2 zptDv@j{4cWaqseY?XD)!Q`-2`g?#e0fzWVY7OU#5wtxpP`p{h~mfWa*e%nzZn<%8k zBYh}*Z?LT0o&pLV{_;Gu?H)ILSH4Og0%`Q^LywGh-^NWjFE&0ottXJ-j7$FFQlV|2O32zRR<-V8U8tn^?CZOc=~it*32W@f-2 zbelIp&`ZCNr`z@vx%w)z^%kJX-=i{-(T}eUb5uCIlww*7JtEHa3nR#Qs^w18J$LDz z8Qfrc`1s1ZI;FY6>L9IhiP(1}-W`Txm1j6P_N-X|0Q8Dr5*sITg$ewJXZvR-p{5?Y z?+Ui34_ikq&(uyUrxYAl5VvD;{a-EN8qbGwx=J3WPtK(7$BE&`RKGunJhzVM?5}<_ zLUfA4h0QR71l~?LOqH+U>;TOoJE^94-7R(i%RGQ+o>5LiRcg=0AnXx+eq}8j+)c+L zXsX>ERIsSs^!(nfp>a#tK~G}@+40y>g_D`l`a76ONlE-dp3F$3 z(;lil(=v$vaAj>0XL!)d`LWs1iav+CeBN||GsSY-%1GV22=gDsu+FE>eO`;rdAr>D zlk%kwgeo}>g%QXCB3Y^>Z$v)R*i_#7evd~B()nYXW2JPmex> z(e!JKU4>`c;8^4|)DEA$$|wGDaF|ZmDtBu@K`;{3n?0LkU+6O|OsuinOl6$TE6df& z312Xfrk$8TS%{|8;2Y%y-fC$RM<6YGZA#dJ1|}R!14kz;x*z^9@FL6Yh^LvY<=EhA zjz9*py9^{8HkaAx9j^Y=Sh;R(&)2d{svsMw#_z^w+G#`5UsS_S0n3)+aCGD24nh`B z>qX@VZ3By>uEcJTQ1ZSd^}}xqA_Gc{_@u;v+#XpNmgLmlTPfBc!tL4 zmBEKYu`2GVBSY`!Pdsru3S!+8UwJ@TUJfQ#0|RIV?z^p@EcJV+_#c_H4$H(>yKVMO zNmdtRHLRp-7@LoF@I5xXMx2~O@L@lIIi8FXL1b>L(qhS5qEM#EL6{$Y1U(FG<5^tV zG4?|ChL&U`Y~c;0Q-FIQ>&!ygsRuOU-wXv%hVUuw%hNH=3kl0s?=lVFeeQ@(A_=s-0@vL@~{Up zwcq62>{Pzmqz@kI{pX=Q9-yCvkWzYkQS)ZOb5lY6H>$|g>Ci&MvH z-&1$X*%{RX3-Se>^oPQ9@sN8sy-nlgSZFc+G=+@|AyER-Dodorrut)6m$TzHZ{O%C zl`2|hdY>bDNXhyE0E-d7JnnB?z=8Iwik1o)XhYlXIFe$2PE8J%lVYFVE8Q?7$Kn0a zD`&)@-umTwZsH8z^l##YVTxklO%+Ld_|X1ETb~k`KciF8@9n`PDKOkEdeD7rTVcR- z$4NR+mU`^#eMOs)APv<0#j%)v+1NJO*bDNp8mTd+!e^Gf%C%ftFc@l1~ z<=%N4iyky^Q_;l^DmRl1<;1b&?*z*zjrz>SJ=~+`4LYw!{(dFnl zd~e(N^O5E1^Rj}@GAr-SrK)8Uw~|57nZA5Ih-h7v#m>z{Xv@Cr@akG6KK})q`4)5d z7!E7>$NAF_oi;l|$+lh$lqQLSDZg;)FJsIyChK&;YE>QOOl$T;lOHa9ZrHhGX%Zi}?W?>enp9{Tgj{AuhRc@)@(Ynw zOl7Sa1ya)dn=Mr!jVB*l@>81fv1bIhZ8ywIe94l^b$zt?x&G{&&)R%X%++1hiYq;O zGxq6n>INKcOWI9hKd9y=m5Y5e9+d;`Kq(9F?kLVeY159b(~k8Q?Z}eu4keKZ2esIu?NeS z`j0>ZQ;D46egduvuBSOORAVgq}CVs;Nz6T z#@G+Vh){MUqm=r2*hAB9Ggm%0b?!VTIkHB*DN40Ft(eZOH6Rrd<>Jx$G(t4v`QpZK zWhECHeV2RhjKY;>sXpls44J|UT-{GMk%kF1#ToYu0__YY)kZddW;Eux7vxOSt!Zhj zX0~`}*;K+7ZfhKKp}o1Tlg=g`(bZ8C>cDSmVcCS0&#+dM8CoT{_l1 z#S-r1WoJnvbz5jrcjss%Fo3+=0-trc^ zPtv*;%VuLS#4kqG$-}_5TgEc~Het*oL+|3Ncf!XDq)DB%Mh#SZnzima8VLJ>0e8{P zmQSy)4h?V}iI2t(IxP8Xb8zDeoxK@2pRaN|&QfL|lQ-jCleJ;&k!Mi3-2=5xPYf(MuuSh=XV30XiRPC5>OeSZ7uaQXi$VQq19Uhn8L{|vYxqslfcH$D z^wW1yXWhlai@AqVZW40c@0kUpCBmsy3->j9CDchXR9?N}y`HBFm_TKxTfvoIOkjyo zA9$whBC1m}uMaMgM9TekoovUWnhOfdrlu#3^l}GmB~eQBot=4?l10xxrQei##o?y8 z6f0gk(0tb$J}M`UxTm^uitScfI$``^*1%vu(0N}+SMiiRdTi%uISgNWRGyh9WI<}+@QHqY**ypPk)j}W>3%Z7caqbJ#N z2{yJzte??K%R-8>hdA|zujW6jvZ4jDa=G|(h`ArR1#bNj(i%Ns(n?1(dr&vDM1=}k zIzm!WZ@nNE?yhCk%B`4ec9*eOeW zGvMnPJM;YB_3>Mbtx8OJVJ3&cQBNwr3sI!in>W6 zG`Dh9b0#nG;&2WVyFo9TnVWLi)kqiZ+hf78zHSIvzMq6!@(MtWu>Xo?9LZF<>TYPj zW=b?ZRtD1?lgq_GYB0*q9AGFm7+S z`9Y?A($Afx+;eZ|EZs_x1w7v4Z5`&%@5C`^^T+b84Qi_y*MTShm z0+Gr8PobW_iO=F|bE#bcfwfjQg46q3&t%IpsoN89pPegQRfhElE1#0{KMebP?3=X~ zX(yt?stO`Ue`^uVeJEUH#D5c)4AJke#LMJ9wOOM~(7$OEh4XkwG@-M5XUzIja~g#b z{lCegc}IA6A%Fd5ha$(&K;vukf^qcS3SDO-e(be^sFb(Y9TRF!?+Kxd8KH0$7gNdZ z&}AG~BVNI9z}Ub{w?CY&za7nUJT>26*_`OQySMJWYVsTv#;%y~Rm!W)`&;XG$KndB z%j&X{U5@4BXnol`FUbm(-kWd5m(`OnT$QllQ*qj<9Qx(daU6NA&}7RtQ_}Z$jBu>- z^g5fhk-bvZjjRJhg}5KPMMk&;ujcTTj9#QB6zQ*(vJPK(e znN~P$VLSH283?2d7d^K!cg9N#U)%b?y*H}L0-wtHX&Y`-pS3UU1P1lrLpVN)zGe79 z$0b2%omWUy0dS7(HKZ{K@_kb|dtK<}@te^JFAI3gkC&n=kJ$~x{$on+*VdFcdDyJ_ z=PUFx>?-8jo<}TY>#3Z38eQZOI%)D=I`&(ZnvJM2H+q!M>V;j~5t46`c1j2B`m9ah z+}Sjvs{oiZlLq zJZ_+hxEkDu$cN4(JD3IR&?8Q+Mew^XV4>z8Pxs1Xm#Ao14rEjl(2*8(37EP!*5(Rw zX{XYdM1*p^ogy;BCD8&u`98EiK5X1%UW3qawZN~)GWU7QI9j~CUdm(;TEJs$uRycE zUe?|tp+&$fj~dOlt9Z@LU0KYbVI$v}5JE{c;dl6@z(sRiA=;2G?cn~^{|KpT%4z=V z`tq6!blibM3sswZPiEq!B7Hpnm)SPpyWMAB@I=8vzP5a7(YM)G{ZJ{0ym-&)?wG8j zgYq+pg6@%_^E87Jm~=D)3(J?0zZP4tSE{ODVUsM*nNokq@|9=&q)Rf?maETN+SCEo zr>NOpOrH?&5~f-aKRFi7@Wj5ZOfuH8C!GIDnH{gSMR}J8ebfGj-_h7OEuoXdggE}g zq3YQEN)CQEb%w0SA@%|(x^dhcC{(e%W^{;+J>xKb4`EN-;5FMuoj5Kd#3*EMHErVk z!@`Kn)mHh14Xu@#lvCUk&0vB4IJ$~i;UsO(MHEz%)gw$VJXC}^z+BFg&qk_7gbgf{1nPfVjVdBvT0=s zZn7o~;?Zj4l9ddijadl=ZTr5_Z9PAMrrDGyqC&0LI%tn0kW`Pm?Ny+P_rLzU$d!UL zwxlq;u8E!3j}A+a;9;~%Zx~tIb(gfi`#V(8HN$tttW}-}WyuYkD1^Uvw7`w=2DtKa zZSixcb<@p7g~6EWeKa^I;T574uM?+;SiW@Hv3ghrXqma;J^+>0-^AV^t+JzOb|Aow zWb`Ff%zk(m0|iNG6M>}i4Cm}Fk8e^N1D~Y~wni!DEkzog)rajJfHbCNyGjCu2k;N{ zdt-bI(d*zoCY&E1t?<0~OU8ypupY3+frXr`8Hy?tcx069Iop&am}Zn@8>+{UO39e9 zphB4xqd!iJ>tC;QYi~55GbQBa-;&|R%SRo{|8c|rG8K|Jr!ObolJX`%y?vB^d+7gs z>3f}*wEffU%Hgdi&YL@>5xtz$?PRt< zjF0F45YsaC=PT~%!)-a3Uy+r^i|-M+I8o1E93x6N3W);MYeh;u-?1QXXDj~|XMApz zGb8e({~;07s=1!7R&T|7`&;A^rqLzciy99?aTml2|7Q>|Vl*Ibvu4k%tt0FE_nT=` z8P<&XcbRufY{{Y%vpFWS1GUN1wpbz_n@rL7H;0DLg`U=YG`V<6gQB>UItV3T5xJ2hIwwTA*zkhiDXCFD(=UF7mW z3DYNq=b<=|TYkVY9*$+RR5EIfxjY^w*i{8IeAhhY=0~Y;mR^MxYhh^UMr9QD(Uz=IEVQw}(>A1V@qw&njMmnFBeRUm~tzYxM1N%joeEC~Se+n{WJjL^eqK(Gt$Z7f4NFV+qY@1{#(Z<&J4U&uvUTx| zn<3^MS%$PFvD+6QMh@P0tEXNP8`D=rP=k{zx=~D*M8$sD9yZQMA1dY6xgy_&E{v z9g`9Jz5QVn(9}#nr~A52SH_4<4~_N1n*Oo=OMB=6U#(Q58od=S1Q~OiQ7=KL*WW8+ zeyKn#h=b{v{C`pK|Mh6xoJJerRheZ+o14|KEPbYQ{(6J%AFKRQ2`e9qfV+2tMg(D+ zzXg2oZ~8O=R|i=43f9!VykgYS4EhaH{&9AA*cV3kpC;Dxo_)`)bRd7JdVM9mD4Lmw zO?_n;C~?l>qf)9t>ouXVan*II>8h9UYbk-L+(@*eRC6kGf8Hj~U@SXM_TC^z?zD3q zxMm4+Bl-WP>&BBL(c&!;`!vmx9?Y*^sXum6$|)ewJw_WZMWn{-WK>hSAjh6-W% zF*PACJ+xF2G?UW*d&4lgYj20xK3f{zSGNO3P*jqL( zT~CI7cLFWMklJnPgG=8E9y zJ<_Mn9b+OgJ=PLOgdnrIU9WivT1vJ3;};r!IPVYLrkUn)*go4^$YjjDyjy}oMjWM^ zp~ay4dI5gf5%X&|pp-W{yB}qwho|n*yL=gmdi#&#dH%MYaIb&>|7q@JWABbvck`s| z<7~p%5}uFMTanCrKFJSHu{&S>-&ERFxVatA;D}VnCi4JybhM>Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/async-method-invocation/etc/async-method-invocation.urm.puml b/async-method-invocation/etc/async-method-invocation.urm.puml deleted file mode 100644 index 6f5d0b27f9d4..000000000000 --- a/async-method-invocation/etc/async-method-invocation.urm.puml +++ /dev/null @@ -1,51 +0,0 @@ -@startuml -package com.iluwatar.async.method.invocation { - class App { - - LOGGER : Logger {static} - + App() - - callback(name : String) : AsyncCallback {static} - - lazyval(value : T, delayMillis : long) : Callable {static} - - log(msg : String) {static} - + main(args : String[]) {static} - } - interface AsyncCallback { - + onComplete(T, Optional) {abstract} - } - interface AsyncExecutor { - + endProcess(AsyncResult) : T {abstract} - + startProcess(Callable) : AsyncResult {abstract} - + startProcess(Callable, AsyncCallback) : AsyncResult {abstract} - } - interface AsyncResult { - + await() {abstract} - + getValue() : T {abstract} - + isCompleted() : boolean {abstract} - } - class ThreadAsyncExecutor { - - idx : AtomicInteger - + ThreadAsyncExecutor() - + endProcess(asyncResult : AsyncResult) : T - + startProcess(task : Callable) : AsyncResult - + startProcess(task : Callable, callback : AsyncCallback) : AsyncResult - } - -class CompletableResult { - ~ COMPLETED : int {static} - ~ FAILED : int {static} - ~ RUNNING : int {static} - ~ callback : Optional> - ~ exception : Exception - ~ lock : Object - ~ state : int - ~ value : T - ~ CompletableResult(callback : AsyncCallback) - + await() - + getValue() : T - + isCompleted() : boolean - ~ setException(exception : Exception) - ~ setValue(value : T) - } -} -CompletableResult ..+ ThreadAsyncExecutor -ThreadAsyncExecutor ..|> AsyncExecutor -CompletableResult ..|> AsyncResult -@enduml \ No newline at end of file diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml deleted file mode 100644 index 7e15aff73e3b..000000000000 --- a/async-method-invocation/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - async-method-invocation - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 0a387d58296a..000000000000 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.Callable; - -/** - * This application demonstrates the async method invocation pattern. Key parts of the pattern are - * AsyncResult which is an intermediate container for an asynchronously evaluated value, - * AsyncCallback which can be provided to be executed on task completion and AsyncExecutor - * that manages the execution of the async tasks. - *

- * The main method shows example flow of async invocations. The main thread starts multiple tasks with variable - * durations and then continues its own work. When the main thread has done it's job it collects the results of the - * async tasks. Two of the tasks are handled with callbacks, meaning the callbacks are executed immediately when the - * tasks complete. - *

- * Noteworthy difference of thread usage between the async results and callbacks is that the async results are collected - * in the main thread but the callbacks are executed within the worker threads. This should be noted when working with - * thread pools. - *

- * Java provides its own implementations of async method invocation pattern. FutureTask, CompletableFuture and - * ExecutorService are the real world implementations of this pattern. But due to the nature of parallel programming, - * the implementations are not trivial. This example does not take all possible scenarios into account but rather - * provides a simple version that helps to understand the pattern. - * - * @see AsyncResult - * @see AsyncCallback - * @see AsyncExecutor - * - * @see java.util.concurrent.FutureTask - * @see java.util.concurrent.CompletableFuture - * @see java.util.concurrent.ExecutorService - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) throws Exception { - // construct a new executor that will run async tasks - AsyncExecutor executor = new ThreadAsyncExecutor(); - - // start few async tasks with varying processing times, two last with callback handlers - AsyncResult asyncResult1 = executor.startProcess(lazyval(10, 500)); - AsyncResult asyncResult2 = executor.startProcess(lazyval("test", 300)); - AsyncResult asyncResult3 = executor.startProcess(lazyval(50L, 700)); - AsyncResult asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4")); - AsyncResult asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Callback result 5")); - - // emulate processing in the current thread while async tasks are running in their own threads - Thread.sleep(350); // Oh boy I'm working hard here - log("Some hard work done"); - - // wait for completion of the tasks - Integer result1 = executor.endProcess(asyncResult1); - String result2 = executor.endProcess(asyncResult2); - Long result3 = executor.endProcess(asyncResult3); - asyncResult4.await(); - asyncResult5.await(); - - // log the results of the tasks, callbacks log immediately when complete - log("Result 1: " + result1); - log("Result 2: " + result2); - log("Result 3: " + result3); - } - - /** - * Creates a callable that lazily evaluates to given value with artificial delay. - * - * @param value - * value to evaluate - * @param delayMillis - * artificial delay in milliseconds - * @return new callable for lazy evaluation - */ - private static Callable lazyval(T value, long delayMillis) { - return () -> { - Thread.sleep(delayMillis); - log("Task completed with: " + value); - return value; - }; - } - - /** - * Creates a simple callback that logs the complete status of the async result. - * - * @param name - * callback name - * @return new async callback - */ - private static AsyncCallback callback(String name) { - return (value, ex) -> { - if (ex.isPresent()) { - log(name + " failed: " + ex.map(Exception::getMessage).orElse("")); - } else { - log(name + ": " + value); - } - }; - } - - private static void log(String msg) { - LOGGER.info(msg); - } -} diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncCallback.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncCallback.java deleted file mode 100644 index 5a291f996d9a..000000000000 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncCallback.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import java.util.Optional; - -/** - * - * AsyncCallback interface - * - * @param - * - */ -public interface AsyncCallback { - - /** - * Complete handler which is executed when async task is completed or fails execution. - * - * @param value the evaluated value from async task, undefined when execution fails - * @param ex empty value if execution succeeds, some exception if executions fails - */ - void onComplete(T value, Optional ex); -} diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncExecutor.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncExecutor.java deleted file mode 100644 index 800bc2728fad..000000000000 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncExecutor.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -/** - * - * AsyncExecutor interface - * - */ -public interface AsyncExecutor { - - /** - * Starts processing of an async task. Returns immediately with async result. - * - * @param task task to be executed asynchronously - * @return async result for the task - */ - AsyncResult startProcess(Callable task); - - /** - * Starts processing of an async task. Returns immediately with async result. Executes callback - * when the task is completed. - * - * @param task task to be executed asynchronously - * @param callback callback to be executed on task completion - * @return async result for the task - */ - AsyncResult startProcess(Callable task, AsyncCallback callback); - - /** - * Ends processing of an async task. Blocks the current thread if necessary and returns the - * evaluated value of the completed task. - * - * @param asyncResult async result of a task - * @return evaluated value of the completed task - * @throws ExecutionException if execution has failed, containing the root cause - * @throws InterruptedException if the execution is interrupted - */ - T endProcess(AsyncResult asyncResult) throws ExecutionException, InterruptedException; -} diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java deleted file mode 100644 index f7fd9ab61e30..000000000000 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import java.util.concurrent.ExecutionException; - -/** - * AsyncResult interface - * @param parameter returned when getValue is invoked - */ -public interface AsyncResult { - - /** - * Status of the async task execution. - * - * @return true if execution is completed or failed - */ - boolean isCompleted(); - - /** - * Gets the value of completed async task. - * - * @return evaluated value or throws ExecutionException if execution has failed - * @throws ExecutionException if execution has failed, containing the root cause - * @throws IllegalStateException if execution is not completed - */ - T getValue() throws ExecutionException; - - /** - * Blocks the current thread until the async task is completed. - * - * @throws InterruptedException if the execution is interrupted - */ - void await() throws InterruptedException; -} diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java deleted file mode 100644 index d12ebbe19297..000000000000 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import java.util.Optional; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * - * Implementation of async executor that creates a new thread for every task. - * - */ -public class ThreadAsyncExecutor implements AsyncExecutor { - - /** Index for thread naming */ - private final AtomicInteger idx = new AtomicInteger(0); - - @Override - public AsyncResult startProcess(Callable task) { - return startProcess(task, null); - } - - @Override - public AsyncResult startProcess(Callable task, AsyncCallback callback) { - CompletableResult result = new CompletableResult<>(callback); - new Thread(() -> { - try { - result.setValue(task.call()); - } catch (Exception ex) { - result.setException(ex); - } - } , "executor-" + idx.incrementAndGet()).start(); - return result; - } - - @Override - public T endProcess(AsyncResult asyncResult) throws ExecutionException, InterruptedException { - if (!asyncResult.isCompleted()) { - asyncResult.await(); - } - return asyncResult.getValue(); - } - - /** - * Simple implementation of async result that allows completing it successfully with a value or exceptionally with an - * exception. A really simplified version from its real life cousins FutureTask and CompletableFuture. - * - * @see java.util.concurrent.FutureTask - * @see java.util.concurrent.CompletableFuture - */ - private static class CompletableResult implements AsyncResult { - - static final int RUNNING = 1; - static final int FAILED = 2; - static final int COMPLETED = 3; - - final Object lock; - final Optional> callback; - - volatile int state = RUNNING; - T value; - Exception exception; - - CompletableResult(AsyncCallback callback) { - this.lock = new Object(); - this.callback = Optional.ofNullable(callback); - } - - /** - * Sets the value from successful execution and executes callback if available. Notifies any thread waiting for - * completion. - * - * @param value - * value of the evaluated task - */ - void setValue(T value) { - this.value = value; - this.state = COMPLETED; - this.callback.ifPresent(ac -> ac.onComplete(value, Optional.empty())); - synchronized (lock) { - lock.notifyAll(); - } - } - - /** - * Sets the exception from failed execution and executes callback if available. Notifies any thread waiting for - * completion. - * - * @param exception - * exception of the failed task - */ - void setException(Exception exception) { - this.exception = exception; - this.state = FAILED; - this.callback.ifPresent(ac -> ac.onComplete(null, Optional.of(exception))); - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public boolean isCompleted() { - return state > RUNNING; - } - - @Override - public T getValue() throws ExecutionException { - if (state == COMPLETED) { - return value; - } else if (state == FAILED) { - throw new ExecutionException(exception); - } else { - throw new IllegalStateException("Execution not completed yet"); - } - } - - @Override - public void await() throws InterruptedException { - synchronized (lock) { - while (!isCompleted()) { - lock.wait(); - } - } - } - } -} diff --git a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/AppTest.java b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/AppTest.java deleted file mode 100644 index ef2649f8afd6..000000000000 --- a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java deleted file mode 100644 index d0e730344b6c..000000000000 --- a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java +++ /dev/null @@ -1,311 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.async.method.invocation; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Matchers; - -import java.util.Optional; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; -import static org.mockito.internal.verification.VerificationModeFactory.times; - -/** - * Date: 12/6/15 - 10:49 AM - * - * @author Jeroen Meulemeester - */ -public class ThreadAsyncExecutorTest { - - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} - */ - @Test(timeout = 3000) - public void testSuccessfulTaskWithoutCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenReturn(result); - - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); - - // Our task should only execute once ... - verify(task, times(1)).call(); - - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } - - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} - */ - @Test(timeout = 3000) - public void testSuccessfulTaskWithCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenReturn(result); - - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(task, callback); - assertNotNull(asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); - - // Our task should only execute once ... - verify(task, times(1)).call(); - - // ... same for the callback, we expect our object - final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); - - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertFalse(optionalException.isPresent()); - - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } - - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while - * to execute - */ - @Test(timeout = 5000) - public void testLongRunningTaskWithoutCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); - - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); - - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } - - // Our task should only execute once, but it can take a while ... - verify(task, timeout(3000).times(1)).call(); - - // Prevent timing issues, and wait until the result is available - asyncResult.await(); - assertTrue(asyncResult.isCompleted()); - verifyNoMoreInteractions(task); - - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } - - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task - * takes a while to execute - */ - @Test(timeout = 5000) - public void testLongRunningTaskWithCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); - - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(task, callback); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); - - verifyZeroInteractions(callback); - - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } - - // Our task should only execute once, but it can take a while ... - verify(task, timeout(3000).times(1)).call(); - - final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); - - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertFalse(optionalException.isPresent()); - - // Prevent timing issues, and wait until the result is available - asyncResult.await(); - assertTrue(asyncResult.isCompleted()); - verifyNoMoreInteractions(task, callback); - - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } - - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while - * to execute, while waiting on the result using {@link ThreadAsyncExecutor#endProcess(AsyncResult)} - */ - @Test(timeout = 5000) - public void testEndProcess() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); - - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); - - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } - - assertSame(result, executor.endProcess(asyncResult)); - verify(task, times(1)).call(); - assertTrue(asyncResult.isCompleted()); - - // Calling end process a second time while already finished should give the same result - assertSame(result, executor.endProcess(asyncResult)); - verifyNoMoreInteractions(task); - } - - /** - * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when the callable is 'null' - */ - @Test(timeout = 3000) - public void testNullTask() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncResult asyncResult = executor.startProcess(null); - - assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.", asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); - - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } - - } - - /** - * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when the - * callable is 'null', but the asynchronous callback is provided - */ - @Test(timeout = 3000) - public void testNullTaskWithCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(null, callback); - - assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.", asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); - - final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); - - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertTrue(optionalException.isPresent()); - - final Exception exception = optionalException.get(); - assertNotNull(exception); - assertEquals(NullPointerException.class, exception.getClass()); - - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } - - } - - /** - * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when both - * the callable and the asynchronous callback are 'null' - */ - @Test(timeout = 3000) - public void testNullTaskWithNullCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncResult asyncResult = executor.startProcess(null, null); - - assertNotNull("The AsyncResult should not be 'null', even though the task and callback were 'null'.", asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); - - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } - - } - -} \ No newline at end of file diff --git a/balking/README.md b/balking/README.md deleted file mode 100644 index fb5c83d5b412..000000000000 --- a/balking/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Balking -folder: balking -permalink: /patterns/balking/ -categories: Concurrency -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Balking Pattern is used to prevent an object from executing certain code if it is an -incomplete or inappropriate state - -![alt text](./etc/balking.png "Balking") - -## Applicability -Use the Balking pattern when - -* you want to invoke an action on an object only when it is in a particular state -* objects are generally only in a state that is prone to balking temporarily -but for an unknown amount of time - -## Related patterns -* Guarded Suspension Pattern -* Double Checked Locking Pattern diff --git a/balking/etc/balking.png b/balking/etc/balking.png deleted file mode 100644 index f409eaacbb951b01f4bbeb5b6b6f51bed1a86179..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21427 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/balking/etc/balking.urm.puml b/balking/etc/balking.urm.puml deleted file mode 100644 index b0296b925417..000000000000 --- a/balking/etc/balking.urm.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml -package com.iluwatar.balking { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class WashingMachine { - - LOGGER : Logger {static} - - washingMachineState : WashingMachineState - + WashingMachine() - + endOfWashing() - + getWashingMachineState() : WashingMachineState - + wash() - } - enum WashingMachineState { - + ENABLED {static} - + WASHING {static} - + valueOf(name : String) : WashingMachineState {static} - + values() : WashingMachineState[] {static} - } -} -WashingMachine --> "-washingMachineState" WashingMachineState -@enduml \ No newline at end of file diff --git a/balking/pom.xml b/balking/pom.xml deleted file mode 100644 index 28fa0db61a11..000000000000 --- a/balking/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - balking - - - junit - junit - test - - - - - \ No newline at end of file diff --git a/balking/src/main/java/com/iluwatar/balking/App.java b/balking/src/main/java/com/iluwatar/balking/App.java deleted file mode 100644 index 47b10cd4606d..000000000000 --- a/balking/src/main/java/com/iluwatar/balking/App.java +++ /dev/null @@ -1,65 +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.balking; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * In Balking Design Pattern if an object’s method is invoked when it is in an inappropriate state, - * then the method will return without doing anything. Objects that use this pattern are generally only in a - * state that is prone to balking temporarily but for an unknown amount of time - * - * In this example implementation WashingMachine is an object that has two states - * in which it can be: ENABLED and WASHING. If the machine is ENABLED - * the state is changed into WASHING that any other thread can't invoke this action on this and then do the job. - * On the other hand if it have been already washing and any other thread execute wash() - * it can't do that once again and returns doing nothing. - */ - -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * @param args the command line arguments - not used - */ - public static void main(String... args) { - final WashingMachine washingMachine = new WashingMachine(); - ExecutorService executorService = Executors.newFixedThreadPool(3); - for (int i = 0; i < 3; i++) { - executorService.execute(washingMachine::wash); - } - executorService.shutdown(); - try { - executorService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException ie) { - LOGGER.error("ERROR: Waiting on executor service shutdown!"); - } - } - -} diff --git a/balking/src/main/java/com/iluwatar/balking/WashingMachine.java b/balking/src/main/java/com/iluwatar/balking/WashingMachine.java deleted file mode 100644 index e4f1259add25..000000000000 --- a/balking/src/main/java/com/iluwatar/balking/WashingMachine.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.balking; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Washing machine class - */ -public class WashingMachine { - - private static final Logger LOGGER = LoggerFactory.getLogger(WashingMachine.class); - - private WashingMachineState washingMachineState; - - public WashingMachine() { - washingMachineState = WashingMachineState.ENABLED; - } - - public WashingMachineState getWashingMachineState() { - return washingMachineState; - } - - /** - * Method responsible for washing - * if the object is in appropriate state - */ - public void wash() { - synchronized (this) { - LOGGER.info("{}: Actual machine state: {}", Thread.currentThread().getName(), getWashingMachineState()); - if (washingMachineState == WashingMachineState.WASHING) { - LOGGER.error("ERROR: Cannot wash if the machine has been already washing!"); - return; - } - washingMachineState = WashingMachineState.WASHING; - } - LOGGER.info("{}: Doing the washing", Thread.currentThread().getName()); - try { - Thread.sleep(50); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - endOfWashing(); - } - - /** - * Method responsible of ending the washing - * by changing machine state - */ - public synchronized void endOfWashing() { - washingMachineState = WashingMachineState.ENABLED; - LOGGER.info("{}: Washing completed.", Thread.currentThread().getId()); - } - -} diff --git a/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java b/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java deleted file mode 100644 index 40a5b2f38e30..000000000000 --- a/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java +++ /dev/null @@ -1,32 +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.balking; - -/** - * WashingMachineState enum describes in which state machine is, - * it can be enabled and ready to work as well as during washing - */ - -public enum WashingMachineState { - ENABLED, WASHING -} diff --git a/balking/src/test/java/com/iluwatar/balking/AppTest.java b/balking/src/test/java/com/iluwatar/balking/AppTest.java deleted file mode 100644 index df104b901672..000000000000 --- a/balking/src/test/java/com/iluwatar/balking/AppTest.java +++ /dev/null @@ -1,39 +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.balking; - -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void main() throws Exception { - String[] args = {}; - App.main(args); - } - -} \ No newline at end of file diff --git a/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java b/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java deleted file mode 100644 index ecf81f409e06..000000000000 --- a/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java +++ /dev/null @@ -1,65 +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.balking; - -import org.junit.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.*; - -/** - * Tests for {@link WashingMachine} - */ -public class WashingMachineTest { - - private volatile WashingMachineState machineStateGlobal; - - @Test - public void wash() throws Exception { - WashingMachine washingMachine = new WashingMachine(); - ExecutorService executorService = Executors.newFixedThreadPool(2); - executorService.execute(washingMachine::wash); - executorService.execute(() -> { - washingMachine.wash(); - machineStateGlobal = washingMachine.getWashingMachineState(); - }); - executorService.shutdown(); - try { - executorService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - assertEquals(WashingMachineState.WASHING, machineStateGlobal); - } - - @Test - public void endOfWashing() throws Exception { - WashingMachine washingMachine = new WashingMachine(); - washingMachine.wash(); - assertEquals(WashingMachineState.ENABLED, washingMachine.getWashingMachineState()); - } - -} \ No newline at end of file diff --git a/bridge/README.md b/bridge/README.md deleted file mode 100644 index a37c35174374..000000000000 --- a/bridge/README.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -layout: pattern -title: Bridge -folder: bridge -permalink: /patterns/bridge/ -pumlid: BSR14SCm20J0Lf82BFxf1akCJ4R26ZZYzkE7zxLljJgoIVfu7S2A3v7pLRhYo3r3l9u6CPHwJjAH5uETllpZhKbejsqn86v1a-CExQwj2mdgqv8-oyev_W00 -categories: Structural -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Also known as -Handle/Body - -## Intent -Decouple an abstraction from its implementation so that the two can vary independently. - -## Explanation - -Real world example - -> Consider you have a weapon with different enchantments and you are supposed to allow mixing different weapons with different enchantments. What would you do? Create multiple copies of each of the weapons for each of the enchantments or would you just create separate enchantment and set it for the weapon as needed? Bridge pattern allows you to do the second. - -In Plain Words - -> Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy. - -Wikipedia says - -> The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently" - -**Programmatic Example** - -Translating our weapon example from above. Here we have the `Weapon` hierarchy - -``` -public interface Weapon { - void wield(); - void swing(); - void unwield(); - Enchantment getEnchantment(); -} - -public class Sword implements Weapon { - - private final Enchantment enchantment; - - public Sword(Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public void wield() { - LOGGER.info("The sword is wielded."); - enchantment.onActivate(); - } - - @Override - public void swing() { - LOGGER.info("The sword is swinged."); - enchantment.apply(); - } - - @Override - public void unwield() { - LOGGER.info("The sword is unwielded."); - enchantment.onDeactivate(); - } - - @Override - public Enchantment getEnchantment() { - return enchantment; - } -} - -public class Hammer implements Weapon { - - private final Enchantment enchantment; - - public Hammer(Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public void wield() { - LOGGER.info("The hammer is wielded."); - enchantment.onActivate(); - } - - @Override - public void swing() { - LOGGER.info("The hammer is swinged."); - enchantment.apply(); - } - - @Override - public void unwield() { - LOGGER.info("The hammer is unwielded."); - enchantment.onDeactivate(); - } - - @Override - public Enchantment getEnchantment() { - return enchantment; - } -} -``` - -And the separate enchantment hierarchy - -``` -public interface Enchantment { - void onActivate(); - void apply(); - void onDeactivate(); -} - -public class FlyingEnchantment implements Enchantment { - - @Override - public void onActivate() { - LOGGER.info("The item begins to glow faintly."); - } - - @Override - public void apply() { - LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand."); - } - - @Override - public void onDeactivate() { - LOGGER.info("The item's glow fades."); - } -} - -public class SoulEatingEnchantment implements Enchantment { - - @Override - public void onActivate() { - LOGGER.info("The item spreads bloodlust."); - } - - @Override - public void apply() { - LOGGER.info("The item eats the soul of enemies."); - } - - @Override - public void onDeactivate() { - LOGGER.info("Bloodlust slowly disappears."); - } -} -``` - -And both the hierarchies in action - -``` -Sword enchantedSword = new Sword(new SoulEatingEnchantment()); -enchantedSword.wield(); -enchantedSword.swing(); -enchantedSword.unwield(); -// The sword is wielded. -// The item spreads bloodlust. -// The sword is swinged. -// The item eats the soul of enemies. -// The sword is unwielded. -// Bloodlust slowly disappears. - -Hammer hammer = new Hammer(new FlyingEnchantment()); -hammer.wield(); -hammer.swing(); -hammer.unwield(); -// The hammer is wielded. -// The item begins to glow faintly. -// The hammer is swinged. -// The item flies and strikes the enemies finally returning to owner's hand. -// The hammer is unwielded. -// The item's glow fades. -``` - -## Applicability -Use the Bridge pattern when - -* you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time. -* both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently -* changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled. -* you have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies -* you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation. - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/bridge/pom.xml b/bridge/pom.xml deleted file mode 100644 index be0f5439cbe2..000000000000 --- a/bridge/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - bridge - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/bridge/src/main/java/com/iluwatar/bridge/App.java b/bridge/src/main/java/com/iluwatar/bridge/App.java deleted file mode 100644 index c986de6565dd..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/App.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Composition over inheritance. The Bridge pattern can also be thought of as two layers of abstraction. - * With Bridge, you can decouple an abstraction from its implementation so that the two can vary independently. - *

- * In Bridge pattern both abstraction ({@link Weapon}) and implementation ( - * {@link Enchantment}) have their own class hierarchies. The interface of the implementations - * can be changed without affecting the clients. - *

- * In this example we have two class hierarchies. One of weapons and another one of enchantments. We can easily - * combine any weapon with any enchantment using composition instead of creating deep class hierarchy. - * - */ -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) { - LOGGER.info("The knight receives an enchanted sword."); - Sword enchantedSword = new Sword(new SoulEatingEnchantment()); - enchantedSword.wield(); - enchantedSword.swing(); - enchantedSword.unwield(); - - LOGGER.info("The valkyrie receives an enchanted hammer."); - Hammer hammer = new Hammer(new FlyingEnchantment()); - hammer.wield(); - hammer.swing(); - hammer.unwield(); - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Enchantment.java b/bridge/src/main/java/com/iluwatar/bridge/Enchantment.java deleted file mode 100644 index dd0c172059cf..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/Enchantment.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -/** - * - * Enchantment - * - */ -public interface Enchantment { - - void onActivate(); - - void apply(); - - void onDeactivate(); -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java b/bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java deleted file mode 100644 index 8b12c6114e88..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * FlyingEnchantment - * - */ -public class FlyingEnchantment implements Enchantment { - - private static final Logger LOGGER = LoggerFactory.getLogger(FlyingEnchantment.class); - - @Override - public void onActivate() { - LOGGER.info("The item begins to glow faintly."); - } - - @Override - public void apply() { - LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand."); - } - - @Override - public void onDeactivate() { - LOGGER.info("The item's glow fades."); - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Hammer.java b/bridge/src/main/java/com/iluwatar/bridge/Hammer.java deleted file mode 100644 index 51bfda2a1b97..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/Hammer.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Hammer - * - */ -public class Hammer implements Weapon { - - private static final Logger LOGGER = LoggerFactory.getLogger(Hammer.class); - - private final Enchantment enchantment; - - public Hammer(Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public void wield() { - LOGGER.info("The hammer is wielded."); - enchantment.onActivate(); - } - - @Override - public void swing() { - LOGGER.info("The hammer is swinged."); - enchantment.apply(); - } - - @Override - public void unwield() { - LOGGER.info("The hammer is unwielded."); - enchantment.onDeactivate(); - } - - @Override - public Enchantment getEnchantment() { - return enchantment; - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java b/bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java deleted file mode 100644 index 8b08d155c083..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * SoulEatingEnchantment - * - */ -public class SoulEatingEnchantment implements Enchantment { - - private static final Logger LOGGER = LoggerFactory.getLogger(SoulEatingEnchantment.class); - - @Override - public void onActivate() { - LOGGER.info("The item spreads bloodlust."); - } - - @Override - public void apply() { - LOGGER.info("The item eats the soul of enemies."); - } - - @Override - public void onDeactivate() { - LOGGER.info("Bloodlust slowly disappears."); - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Sword.java b/bridge/src/main/java/com/iluwatar/bridge/Sword.java deleted file mode 100644 index 6f52943a6ead..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/Sword.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Sword - * - */ -public class Sword implements Weapon { - - private static final Logger LOGGER = LoggerFactory.getLogger(Sword.class); - - private final Enchantment enchantment; - - public Sword(Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public void wield() { - LOGGER.info("The sword is wielded."); - enchantment.onActivate(); - } - - @Override - public void swing() { - LOGGER.info("The sword is swinged."); - enchantment.apply(); - } - - @Override - public void unwield() { - LOGGER.info("The sword is unwielded."); - enchantment.onDeactivate(); - } - - @Override - public Enchantment getEnchantment() { - return enchantment; - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Weapon.java b/bridge/src/main/java/com/iluwatar/bridge/Weapon.java deleted file mode 100644 index a2d21b88f5aa..000000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/Weapon.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -/** - * - * Weapon - * - */ -public interface Weapon { - - void wield(); - - void swing(); - - void unwield(); - - Enchantment getEnchantment(); -} diff --git a/bridge/src/test/java/com/iluwatar/bridge/AppTest.java b/bridge/src/test/java/com/iluwatar/bridge/AppTest.java deleted file mode 100644 index fcf7e44cefe0..000000000000 --- a/bridge/src/test/java/com/iluwatar/bridge/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/bridge/src/test/java/com/iluwatar/bridge/HammerTest.java b/bridge/src/test/java/com/iluwatar/bridge/HammerTest.java deleted file mode 100644 index a650bae04d62..000000000000 --- a/bridge/src/test/java/com/iluwatar/bridge/HammerTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Tests for hammer - */ -public class HammerTest extends WeaponTest { - - /** - * Invoke all possible actions on the weapon and check if the actions are executed on the actual - * underlying weapon implementation. - */ - @Test - public void testHammer() throws Exception { - final Hammer hammer = spy(new Hammer(mock(FlyingEnchantment.class))); - testBasicWeaponActions(hammer); - } -} \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/SwordTest.java b/bridge/src/test/java/com/iluwatar/bridge/SwordTest.java deleted file mode 100644 index 7ffd0e492c98..000000000000 --- a/bridge/src/test/java/com/iluwatar/bridge/SwordTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Tests for sword - */ -public class SwordTest extends WeaponTest { - - /** - * Invoke all possible actions on the weapon and check if the actions are executed on the actual - * underlying weapon implementation. - */ - @Test - public void testSword() throws Exception { - final Sword sword = spy(new Sword(mock(FlyingEnchantment.class))); - testBasicWeaponActions(sword); - } -} \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java deleted file mode 100644 index 0e62374be71e..000000000000 --- a/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.bridge; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.internal.verification.VerificationModeFactory.times; - -/** - * Base class for weapon tests - */ -public abstract class WeaponTest { - - /** - * Invoke the basic actions of the given weapon, and test if the underlying enchantment implementation - * is invoked - * - */ - protected final void testBasicWeaponActions(final Weapon weapon) { - assertNotNull(weapon); - Enchantment enchantment = weapon.getEnchantment(); - assertNotNull(enchantment); - assertNotNull(weapon.getEnchantment()); - - weapon.swing(); - verify(enchantment).apply(); - verifyNoMoreInteractions(enchantment); - - weapon.wield(); - verify(enchantment).onActivate(); - verifyNoMoreInteractions(enchantment); - - weapon.unwield(); - verify(enchantment).onDeactivate(); - verifyNoMoreInteractions(enchantment); - - } -} diff --git a/builder/.gitignore b/builder/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/builder/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/builder/README.md b/builder/README.md deleted file mode 100644 index d255ec2f66cf..000000000000 --- a/builder/README.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -layout: pattern -title: Builder -folder: builder -permalink: /patterns/builder/ -pumlid: DSR94O0m2030LhG0mzzkC64KXs26GzlNZw_TcRLADagJwOWOlW8OFcNdE79B9wkN1ccKUdLWoGS33KwySMdalEioC89C7Jhw5zYIfNrIrFybhPUHNLu0 -categories: Creational -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Intent -Separate the construction of a complex object from its -representation so that the same construction process can create different -representations. - -## Explanation - -Real world example - -> Imagine a character generator for a role playing game. The easiest option is to let computer create the character for you. But if you want to select the character details like profession, gender, hair color etc. the character generation becomes a step-by-step process that completes when all the selections are ready. - -In plain words - -> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object. - -Wikipedia says - -> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern. - -Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below: - -``` -public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { -} -``` - -As you can see the number of constructor parameters can quickly get out of hand and it might become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in future. This is called telescoping constructor anti-pattern. - -**Programmatic Example** - -The sane alternative is to use the Builder pattern. First of all we have our hero that we want to create - -``` -public final class Hero { - private final Profession profession; - private final String name; - private final HairType hairType; - private final HairColor hairColor; - private final Armor armor; - private final Weapon weapon; - - private Hero(Builder builder) { - this.profession = builder.profession; - this.name = builder.name; - this.hairColor = builder.hairColor; - this.hairType = builder.hairType; - this.weapon = builder.weapon; - this.armor = builder.armor; - } -} -``` - -And then we have the builder - -``` - public static class Builder { - private final Profession profession; - private final String name; - private HairType hairType; - private HairColor hairColor; - private Armor armor; - private Weapon weapon; - - public Builder(Profession profession, String name) { - if (profession == null || name == null) { - throw new IllegalArgumentException("profession and name can not be null"); - } - this.profession = profession; - this.name = name; - } - - public Builder withHairType(HairType hairType) { - this.hairType = hairType; - return this; - } - - public Builder withHairColor(HairColor hairColor) { - this.hairColor = hairColor; - return this; - } - - public Builder withArmor(Armor armor) { - this.armor = armor; - return this; - } - - public Builder withWeapon(Weapon weapon) { - this.weapon = weapon; - return this; - } - - public Hero build() { - return new Hero(this); - } - } -``` - -And then it can be used as: - -``` -Hero mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build(); -``` - -## Applicability -Use the Builder pattern when - -* the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled -* the construction process must allow different representations for the object that's constructed - -## Real world examples - -* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html) -* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on. -* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-) -* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html) -* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) -* [Effective Java (2nd Edition)](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683) diff --git a/builder/pom.xml b/builder/pom.xml deleted file mode 100644 index 0f70791e46e0..000000000000 --- a/builder/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - builder - - - junit - junit - test - - - diff --git a/builder/src/main/java/com/iluwatar/builder/App.java b/builder/src/main/java/com/iluwatar/builder/App.java deleted file mode 100644 index 9fcfdb65ac57..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/App.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -import com.iluwatar.builder.Hero.Builder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The intention of the Builder pattern is to find a solution to the telescoping constructor - * anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object - * constructor parameter combination leads to an exponential list of constructors. Instead of using - * numerous constructors, the builder pattern uses another object, a builder, that receives each - * initialization parameter step by step and then returns the resulting constructed object at once. - *

- * The Builder pattern has another benefit. It can be used for objects that contain flat data (html - * code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited. This - * type of data cannot be edited step by step and must be edited at once. The best way to construct - * such an object is to use a builder class. - *

- * In this example we have the Builder pattern variation as described by Joshua Bloch in Effective - * Java 2nd Edition. - *

- * We want to build {@link Hero} objects, but its construction is complex because of the many - * parameters needed. To aid the user we introduce {@link Builder} class. {@link Hero.Builder} - * takes the minimum parameters to build {@link Hero} object in its constructor. After that - * additional configuration for the {@link Hero} object can be done using the fluent - * {@link Builder} interface. When configuration is ready the build method is called to receive - * the final {@link Hero} object. - * - */ -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) { - - Hero mage = - new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK) - .withWeapon(Weapon.DAGGER).build(); - 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(); - LOGGER.info(warrior.toString()); - - Hero thief = - new Hero.Builder(Profession.THIEF, "Desmond").withHairType(HairType.BALD) - .withWeapon(Weapon.BOW).build(); - LOGGER.info(thief.toString()); - - } -} diff --git a/builder/src/main/java/com/iluwatar/builder/Armor.java b/builder/src/main/java/com/iluwatar/builder/Armor.java deleted file mode 100644 index 0deb9712c2bc..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/Armor.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * Armor enumeration - * - */ -public enum Armor { - - CLOTHES("clothes"), LEATHER("leather"), CHAIN_MAIL("chain mail"), PLATE_MAIL("plate mail"); - - private String title; - - Armor(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/builder/src/main/java/com/iluwatar/builder/HairColor.java b/builder/src/main/java/com/iluwatar/builder/HairColor.java deleted file mode 100644 index a3f03abfc952..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/HairColor.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * HairColor enumeration - * - */ -public enum HairColor { - - WHITE, BLOND, RED, BROWN, BLACK; - - @Override - public String toString() { - return name().toLowerCase(); - } - -} diff --git a/builder/src/main/java/com/iluwatar/builder/HairType.java b/builder/src/main/java/com/iluwatar/builder/HairType.java deleted file mode 100644 index 604a0836d394..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/HairType.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * HairType enumeration - * - */ -public enum HairType { - - BALD("bald"), SHORT("short"), CURLY("curly"), LONG_STRAIGHT("long straight"), LONG_CURLY( - "long curly"); - - private String title; - - HairType(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/builder/src/main/java/com/iluwatar/builder/Hero.java b/builder/src/main/java/com/iluwatar/builder/Hero.java deleted file mode 100644 index e7f0b3cabbec..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/Hero.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * Hero, the class with many parameters. - * - */ -public final class Hero { - - private final Profession profession; - private final String name; - private final HairType hairType; - private final HairColor hairColor; - private final Armor armor; - private final Weapon weapon; - - private Hero(Builder builder) { - this.profession = builder.profession; - this.name = builder.name; - this.hairColor = builder.hairColor; - this.hairType = builder.hairType; - this.weapon = builder.weapon; - this.armor = builder.armor; - } - - public Profession getProfession() { - return profession; - } - - public String getName() { - return name; - } - - public HairType getHairType() { - return hairType; - } - - public HairColor getHairColor() { - return hairColor; - } - - public Armor getArmor() { - return armor; - } - - public Weapon getWeapon() { - return weapon; - } - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - sb.append("This is a ") - .append(profession) - .append(" named ") - .append(name); - if (hairColor != null || hairType != null) { - sb.append(" with "); - if (hairColor != null) { - sb.append(hairColor).append(' '); - } - if (hairType != null) { - sb.append(hairType).append(' '); - } - sb.append(hairType != HairType.BALD ? "hair" : "head"); - } - if (armor != null) { - sb.append(" wearing ").append(armor); - } - if (weapon != null) { - sb.append(" and wielding a ").append(weapon); - } - sb.append('.'); - return sb.toString(); - } - - /** - * - * The builder class. - * - */ - public static class Builder { - - private final Profession profession; - private final String name; - private HairType hairType; - private HairColor hairColor; - private Armor armor; - private Weapon weapon; - - /** - * Constructor - */ - public Builder(Profession profession, String name) { - if (profession == null || name == null) { - throw new IllegalArgumentException("profession and name can not be null"); - } - this.profession = profession; - this.name = name; - } - - public Builder withHairType(HairType hairType) { - this.hairType = hairType; - return this; - } - - public Builder withHairColor(HairColor hairColor) { - this.hairColor = hairColor; - return this; - } - - public Builder withArmor(Armor armor) { - this.armor = armor; - return this; - } - - public Builder withWeapon(Weapon weapon) { - this.weapon = weapon; - return this; - } - - public Hero build() { - return new Hero(this); - } - } -} diff --git a/builder/src/main/java/com/iluwatar/builder/Profession.java b/builder/src/main/java/com/iluwatar/builder/Profession.java deleted file mode 100644 index 579eed787baf..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/Profession.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * Profession enumeration - * - */ -public enum Profession { - - WARRIOR, THIEF, MAGE, PRIEST; - - @Override - public String toString() { - return name().toLowerCase(); - } -} diff --git a/builder/src/main/java/com/iluwatar/builder/Weapon.java b/builder/src/main/java/com/iluwatar/builder/Weapon.java deleted file mode 100644 index 86c910a44634..000000000000 --- a/builder/src/main/java/com/iluwatar/builder/Weapon.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -/** - * - * Weapon enumeration - * - */ -public enum Weapon { - - DAGGER, SWORD, AXE, WARHAMMER, BOW; - - @Override - public String toString() { - return name().toLowerCase(); - } -} diff --git a/builder/src/test/java/com/iluwatar/builder/AppTest.java b/builder/src/test/java/com/iluwatar/builder/AppTest.java deleted file mode 100644 index b30c50cda493..000000000000 --- a/builder/src/test/java/com/iluwatar/builder/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/builder/src/test/java/com/iluwatar/builder/HeroTest.java b/builder/src/test/java/com/iluwatar/builder/HeroTest.java deleted file mode 100644 index c111fb853b7f..000000000000 --- a/builder/src/test/java/com/iluwatar/builder/HeroTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.builder; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/6/15 - 11:01 PM - * - * @author Jeroen Meulemeester - */ -public class HeroTest { - - /** - * Test if we get the expected exception when trying to create a hero without a profession - */ - @Test(expected = IllegalArgumentException.class) - public void testMissingProfession() throws Exception { - new Hero.Builder(null, "Sir without a job"); - } - - /** - * Test if we get the expected exception when trying to create a hero without a name - */ - @Test(expected = IllegalArgumentException.class) - public void testMissingName() throws Exception { - new Hero.Builder(Profession.THIEF, null); - } - - /** - * Test if the hero build by the builder has the correct attributes, as requested - */ - @Test - public void testBuildHero() throws Exception { - final String heroName = "Sir Lancelot"; - - final Hero hero = new Hero.Builder(Profession.WARRIOR, heroName) - .withArmor(Armor.CHAIN_MAIL) - .withWeapon(Weapon.SWORD) - .withHairType(HairType.LONG_CURLY) - .withHairColor(HairColor.BLOND) - .build(); - - assertNotNull(hero); - assertNotNull(hero.toString()); - assertEquals(Profession.WARRIOR, hero.getProfession()); - assertEquals(heroName, hero.getName()); - assertEquals(Armor.CHAIN_MAIL, hero.getArmor()); - assertEquals(Weapon.SWORD, hero.getWeapon()); - assertEquals(HairType.LONG_CURLY, hero.getHairType()); - assertEquals(HairColor.BLOND, hero.getHairColor()); - - } - -} \ No newline at end of file diff --git a/business-delegate/README.md b/business-delegate/README.md deleted file mode 100644 index 8e6e3456c410..000000000000 --- a/business-delegate/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Business Delegate -folder: business-delegate -permalink: /patterns/business-delegate/ -pumlid: POl13SCm3CHMQGU8zUysgYCuBcJ5a4x9-l6_Fu84tzsgvYxf-Zg06HyYvxkqZYE_6UBrD8YXr7DGrxmPxFJZYxTTeZVR9WFY5ZGu5j2wkad4wYgD8IIe_xQaZp9pw0C0 -categories: Business Tier -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -The Business Delegate pattern adds an abstraction layer between -presentation and business tiers. By using the pattern we gain loose coupling -between the tiers and encapsulate knowledge about how to locate, connect to, -and interact with the business objects that make up the application. - -![alt text](./etc/business-delegate.png "Business Delegate") - -## Applicability -Use the Business Delegate pattern when - -* you want loose coupling between presentation and business tiers -* you want to orchestrate calls to multiple business services -* you want to encapsulate service lookups and service calls - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) diff --git a/business-delegate/etc/business-delegate.png b/business-delegate/etc/business-delegate.png deleted file mode 100644 index 928cf934645b8447540ddfb344c04220105b3db3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24283 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 diff --git a/business-delegate/etc/business-delegate.ucls b/business-delegate/etc/business-delegate.ucls deleted file mode 100644 index 668a6579eb47..000000000000 --- a/business-delegate/etc/business-delegate.ucls +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/business-delegate/etc/business-delegate.urm.puml b/business-delegate/etc/business-delegate.urm.puml deleted file mode 100644 index 40aa2d6f0997..000000000000 --- a/business-delegate/etc/business-delegate.urm.puml +++ /dev/null @@ -1,57 +0,0 @@ -@startuml -package com.iluwatar.business.delegate { - class App { - + App() - + main(args : String[]) {static} - } - class BusinessDelegate { - - businessService : BusinessService - - lookupService : BusinessLookup - - serviceType : ServiceType - + BusinessDelegate() - + doTask() - + setLookupService(businessLookup : BusinessLookup) - + setServiceType(serviceType : ServiceType) - } - class BusinessLookup { - - ejbService : EjbService - - jmsService : JmsService - + BusinessLookup() - + getBusinessService(serviceType : ServiceType) : BusinessService - + setEjbService(ejbService : EjbService) - + setJmsService(jmsService : JmsService) - } - interface BusinessService { - + doProcessing() {abstract} - } - class Client { - - businessDelegate : BusinessDelegate - + Client(businessDelegate : BusinessDelegate) - + doTask() - } - class EjbService { - - LOGGER : Logger {static} - + EjbService() - + doProcessing() - } - class JmsService { - - LOGGER : Logger {static} - + JmsService() - + doProcessing() - } - enum ServiceType { - + EJB {static} - + JMS {static} - + valueOf(name : String) : ServiceType {static} - + values() : ServiceType[] {static} - } -} -BusinessLookup --> "-ejbService" EjbService -BusinessDelegate --> "-serviceType" ServiceType -Client --> "-businessDelegate" BusinessDelegate -BusinessDelegate --> "-businessService" BusinessService -BusinessDelegate --> "-lookupService" BusinessLookup -BusinessLookup --> "-jmsService" JmsService -EjbService ..|> BusinessService -JmsService ..|> BusinessService -@enduml \ No newline at end of file diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml deleted file mode 100644 index c6ceb7e43f0e..000000000000 --- a/business-delegate/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - business-delegate - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/App.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/App.java deleted file mode 100644 index 945f09c0a52f..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/App.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * The Business Delegate pattern adds an abstraction layer between the presentation and business - * tiers. By using the pattern we gain loose coupling between the tiers. The Business Delegate - * encapsulates knowledge about how to locate, connect to, and interact with the business objects - * that make up the application. - * - *

Some of the services the Business Delegate uses are instantiated directly, and some can be - * retrieved through service lookups. The Business Delegate itself may contain business logic too - * potentially tying together multiple service calls, exception handling, retrying etc. - * - *

In this example the client ({@link Client}) utilizes a business delegate ( - * {@link BusinessDelegate}) to execute a task. The Business Delegate then selects the appropriate - * service and makes the service call. - */ -public class App { - - /** - * Program entry point. - * - * @param args command line args - */ - public static void main(String[] args) { - - BusinessDelegate businessDelegate = new BusinessDelegate(); - BusinessLookup businessLookup = new BusinessLookup(); - businessLookup.setEjbService(new EjbService()); - businessLookup.setJmsService(new JmsService()); - - businessDelegate.setLookupService(businessLookup); - businessDelegate.setServiceType(ServiceType.EJB); - - Client client = new Client(businessDelegate); - client.doTask(); - - businessDelegate.setServiceType(ServiceType.JMS); - client.doTask(); - } -} diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java deleted file mode 100644 index 32b2bc770c36..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * BusinessDelegate separates the presentation and business tiers - */ -public class BusinessDelegate { - - private BusinessLookup lookupService; - private BusinessService businessService; - private ServiceType serviceType; - - public void setLookupService(BusinessLookup businessLookup) { - this.lookupService = businessLookup; - } - - public void setServiceType(ServiceType serviceType) { - this.serviceType = serviceType; - } - - public void doTask() { - businessService = lookupService.getBusinessService(serviceType); - businessService.doProcessing(); - } -} diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessLookup.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessLookup.java deleted file mode 100644 index ae3c54b864d9..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessLookup.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * Class for performing service lookups. - */ -public class BusinessLookup { - - private EjbService ejbService; - - private JmsService jmsService; - - /** - * @param serviceType Type of service instance to be returned. - * @return Service instance. - */ - public BusinessService getBusinessService(ServiceType serviceType) { - if (serviceType.equals(ServiceType.EJB)) { - return ejbService; - } else { - return jmsService; - } - } - - public void setJmsService(JmsService jmsService) { - this.jmsService = jmsService; - } - - public void setEjbService(EjbService ejbService) { - this.ejbService = ejbService; - } -} diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessService.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessService.java deleted file mode 100644 index fbda6c67eabc..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessService.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * - * Interface for service implementations - * - */ -public interface BusinessService { - - void doProcessing(); -} diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/Client.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/Client.java deleted file mode 100644 index e521426aec71..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/Client.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * - * Client utilizes BusinessDelegate to call the business tier - * - */ -public class Client { - - private BusinessDelegate businessDelegate; - - public Client(BusinessDelegate businessDelegate) { - this.businessDelegate = businessDelegate; - } - - public void doTask() { - businessDelegate.doTask(); - } -} 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 deleted file mode 100644 index afe53600aaab..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Service EJB implementation - * - */ -public class EjbService implements BusinessService { - - private static final Logger LOGGER = LoggerFactory.getLogger(EjbService.class); - - @Override - public void doProcessing() { - 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 deleted file mode 100644 index 4b112906efba..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Service JMS implementation - * - */ -public class JmsService implements BusinessService { - - private static final Logger LOGGER = LoggerFactory.getLogger(JmsService.class); - - @Override - public void doProcessing() { - LOGGER.info("JmsService is now processing"); - } -} diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/ServiceType.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/ServiceType.java deleted file mode 100644 index ac82d7daf628..000000000000 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/ServiceType.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -/** - * - * Enumeration for service types - * - */ -public enum ServiceType { - - EJB, JMS; -} diff --git a/business-delegate/src/test/java/com/iluwatar/business/delegate/AppTest.java b/business-delegate/src/test/java/com/iluwatar/business/delegate/AppTest.java deleted file mode 100644 index d02109d37d71..000000000000 --- a/business-delegate/src/test/java/com/iluwatar/business/delegate/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Business Delegate example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/business-delegate/src/test/java/com/iluwatar/business/delegate/BusinessDelegateTest.java b/business-delegate/src/test/java/com/iluwatar/business/delegate/BusinessDelegateTest.java deleted file mode 100644 index 48d576319acb..000000000000 --- a/business-delegate/src/test/java/com/iluwatar/business/delegate/BusinessDelegateTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.business.delegate; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import org.junit.Before; -import org.junit.Test; - -/** - * The Business Delegate pattern adds an abstraction layer between the presentation and business - * tiers. By using the pattern we gain loose coupling between the tiers. The Business Delegate - * encapsulates knowledge about how to locate, connect to, and interact with the business objects - * that make up the application. - * - *

Some of the services the Business Delegate uses are instantiated directly, and some can be - * retrieved through service lookups. The Business Delegate itself may contain business logic too - * potentially tying together multiple service calls, exception handling, retrying etc. - */ -public class BusinessDelegateTest { - - private EjbService ejbService; - - private JmsService jmsService; - - private BusinessLookup businessLookup; - - private BusinessDelegate businessDelegate; - - /** - * This method sets up the instance variables of this test class. It is executed before the - * execution of every test. - */ - @Before - public void setup() { - ejbService = spy(new EjbService()); - jmsService = spy(new JmsService()); - - businessLookup = spy(new BusinessLookup()); - businessLookup.setEjbService(ejbService); - businessLookup.setJmsService(jmsService); - - businessDelegate = spy(new BusinessDelegate()); - businessDelegate.setLookupService(businessLookup); - } - - /** - * In this example the client ({@link Client}) utilizes a business delegate ( - * {@link BusinessDelegate}) to execute a task. The Business Delegate then selects the appropriate - * service and makes the service call. - */ - @Test - public void testBusinessDelegate() { - - // setup a client object - Client client = new Client(businessDelegate); - - // set the service type - businessDelegate.setServiceType(ServiceType.EJB); - - // action - client.doTask(); - - // verifying that the businessDelegate was used by client during doTask() method. - verify(businessDelegate).doTask(); - verify(ejbService).doProcessing(); - - // set the service type - businessDelegate.setServiceType(ServiceType.JMS); - - // action - client.doTask(); - - // verifying that the businessDelegate was used by client during doTask() method. - verify(businessDelegate, times(2)).doTask(); - verify(jmsService).doProcessing(); - } -} diff --git a/caching/.gitignore b/caching/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/caching/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/caching/README.md b/caching/README.md deleted file mode 100644 index b48d060f0012..000000000000 --- a/caching/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Caching -folder: caching -permalink: /patterns/caching/ -pumlid: DSRB4OKm2030LhG0m_rrWyWaE0bc-6ZxpujxsbMKUXwSrfSMCVq7OFYKAj5oJsUZIuCr2bq3fEU3WGOdthWTx59rcnZ1fWu3_GqGKXEjm47VIzeeCqV_0m00 -categories: Other -tags: - - Java - - Difficulty-Intermediate - - Performance ---- - -## Intent -To avoid expensive re-acquisition of resources by not releasing -the resources immediately after their use. The resources retain their identity, are kept in some -fast-access storage, and are re-used to avoid having to acquire them again. - -![alt text](./etc/caching.png "Caching") - -## Applicability -Use the Caching pattern(s) when - -* Repetitious acquisition, initialization, and release of the same resource causes unnecessary performance overhead. - -## Credits - -* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained) -* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177) -* [Cache-Aside](https://msdn.microsoft.com/en-us/library/dn589799.aspx) diff --git a/caching/etc/caching.png b/caching/etc/caching.png deleted file mode 100644 index b6ed703ab8b7dfce5e5d82f097dac534828fc93a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114847 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

$0ITcj(KRIbdLxc zm|gWeiNF4Rh%U<7^^sA`3UNB=el4CTb#R*YWI>(ck0&j4kNyi7{}X(@g1}OF8+2K> z$@SwDz}?3*z)n1Ge^Owb)AE+0V@GiojRN!yf-J+;HtgasfB?1XYesjgf};8}=%AQ= zdXpMGP}aee|7cqO`Sh=`GZ+XCa^8ibzNS=MqLxZMrxXQpbKrSLuUeR(0yke6xU`XtYOfvdPYi(k3w1yJ3*2w7yTE1o z<8^yF^-}cfE^y{80miAqM0=jZY4!Zd@(NVSk~e&7HzS$pj~=;0`pruSlFI!P68FG8 zu`1_dHs4&NeJI+2YN6KCi-;j`xw2gAtx+Jg{xVAoJr3S%dwX+h`tN*o5j&&xBuAC% z#_347^}8aSMaF=Jn9c>k zqW#7f+wS7`a*h2CE|b>9*LMQWXS?_c`uh5Hb#+8UM7b&j(3yySzmt(nY0t~8?9VaV z<9T;Sz0CJm;3qDl2I;4>-RbxBE+{W}#`^pFJ3BY}Vp+|pfvwW2Kb$6JGLW#fu|X|K zgOqCAAD5?6AWX^4&Hd^X`jypW;d}@o=VJ`W;UlSMxVX5L`t8ul?V(f=e%G_HW1i=S z;tA{a)ps1zjh?X1(2(WMyVJ?|*G?LIwg(H7pJRcUUe*p0L%{kFyhf+^u>Rs7R0Mu? zfcBPx9H8S}9rsZ<*W#~nai4&dZ#dhay)o4VY@hqz^-%D*pFsvlNpPEbTj#40Z5L9J z(vG*e^|$56Akg}bgY~?wtmQ_T@xPdlKojD(#Fv({9O-~^Eo~GRlgh$I+Q0}E4`Wvrf66zjDKf$Zhu0{OPG?=8ln5QaDS`r^$_LuLJ)bx-7P;24tp10nm z=N%M+JkkoY-%&v%Lf96SVvAG}rPztZ*ZT>A+MI6!Hw-o+dVb zpE=u5rLd*{GV^b#Aq7H+7t_(kV57_FHm~D;x#c_$9o;t2x=YDlsoyPtt4>Xy!SC_l z{ML^MZTa~&o&zOMhya+Jc%sa?dKSQxr%Ym&TP9ZCMM=UvY<}7 zI0_mX+Ojs(6^Nva;hicC*6w^#s`1Z9!!26tWt{GVvVaAQqhX zqDRnbfsdcrHwx|~=SH#LDC2T=0@8>_QziAl4*i}f>5Q1ux}J5nSM}J*bq>$)A$ET< zNemMNTxUY}pwxUR4SS1$L3Xy76g!V|&<_^mvEP)0zYS8?l5dBIcu zoU?uR9#riBKWi@FEA`~VR1lwhVlB3^);kN@$SnxnRu3#JBq2K)V*L>*1EnwhdG(h? z_bR_kt)G!gyXK9?{TpCVL57-koPC*%`-d+*Vu5WHXpE05gQC`L85{>h;FD_K41e$S zKK#p_BF*;fFWZSAAi>gvd(SXqx_UjYFQ7{Ezkhq&XKp>ugu8+h)FrRwJsj0nt8xG?FAPHUi z(DZZ)X>OnSfKkNhC{`^1(q2sgalVoB`e3iXv)+f{Dxt$k>&A(?x zGw(s)XN8s3(FUI^AsAO$Z7qGU*`K)I>h|2erA*9q?-K53%!4^8^ZA8Py1N?$Ty#r!OE)4V-5^rZCEY1VNJ@7rDJ>=44c|ncz2CjhdB5|AA6yEo z8F!3(j4{1piQj?Za44nOh{=HqNKhJbgApV~HL@s-TFqKXwP*kiutzowJ0KH`E^BR5 zE9@AHU-X=|(C7Z{0}omwc75 zP*89H;EtL_uX7>-C>9P5x7i?Gg4@}S78}fCdvJxFKyvcAzfClSM@A+R^5hlPZSlN( z$*T>n>4T20FFTSt+cD*0v%yRF`Be76PBbv%*Pmo9MGU z8+P-wbFDw#kmT_73l$(edA31Zeh=VQ%}+^52%ua1UQ8U08+CGA62lB;&L8Lim>93_ z=l|_BXc7B|8y~4YnAMbJS26E{Hi}-2eu({%tOL%002tO+VqpcBakVp;cEN(P$Ge09 zeURk8z1V#CGj~AS2}~(Qac|Z^>3gIBH)N5zr9AqBEjAh%psww^sQ^S%z^QBW_9Ahi zl8oFT#=+@i2aFMau$S3SV1j~OOcxc6`V&Wz=hcOl-ut-f)FM@3QO>Ko$v&Vv`p9v| zfc$dwphN+r*A@pdeL1M-$jTM9AZK}Z5}Tmb3Lx2q`ODF-vBgM8SwBj9i|aR4zd&tUd%k7whwm$nhlc>pE4efpFMD20s%!l! z!`^2U4Y@uFrfuthJr3&IfTOe_0Qx0f3k2nYylY(V{+cz@VK5>xfMClZ29Pf9*S{fP*g z;D4d50CjY9^kjWyV^ew(!RwgB?_Av4DjfcBpd=#+d;frEp!D|gI9?xuLnUrU8U&-1K2csjtkIWr2&ArbpeDgZ4Y%yvKr9Nx?Q!3hd- zk!g)6J{YJJ0*YN8xWnoIZ!sC!1Tx#q0-UE9e_Vn_myZ;Z*?m#XS0;x_9#ou;lm1Hj zbPU{sI8z%S^e(jb@((F*C*UBpcNtWfd`NWDXs{eWgV)@~WAnqxk^BN+219-$0I+{AqDaK%)bz1^H;l&;*ifhjc|Z zK=VKheb;kk<(5SqP8W*(vZO^Cl?c%B4WhvaBAYZ;#$7HKef+mdUJmQ&V#mo=#@p@5 z4^&mKScTtkfDx8|PjW8i2U-%C-o&&Uvu}mWGJT9&&(n+UpHWne3l~%kr_W6njHC** z{K5UaG6n|peP(ouFpARrzbu5R{M}wFywCLu+CRclyQO}-gsvP+yb@mPi`}@nJO=0v zJLQWPo*?!DQz2|l)SxF%p8|M~B6SEJL}y+B0U9bQz27Pyu4{3zk?JD z(z;nivoxKQHmletVITcU!!}f*i>1jjoht)Kkb0N%yVT@s>S`M>N`S|H98(u6#awN7#!Sm$e0$ve+PgjnTIB$4#9r9Ax^r8pM$q;eW{JP%`J|_QHp?(eR}WukRlog* zA$oBOQoNMdtzn&tkzB5gcU!dOOTd*$f&`$~ocZ#1-jj$t9!1ICea&JKi8tm2$iBeZ zNv2?F3G;2{x2iRBKz`fWls+6L5f-8(x})`&f%&QwUv^4-jYpo*omNyzJV z(_aDdV>L_U)xn=4l#u~kIgylI0ClD6MTW(Wdi+BTe~>v|1r2p4EBfd{Z|eiUM!8LO zu~BE!g7(~nF+Jm3IGO7_sa`Xp72 z4~4>)XjCw3RhfJ??t(?a`}PKahJnc(=CgBixGegF@Nc)qsh~Z70jYq1fK+ZS6zm1NCVE{FG_C^mcFW-L1B-N@=#f9kuVF6?WxzVO2Z9t!hRyO(- zMrX@GvFg8cp2OUR`Zz^GEbtM+rx(&5KYT#u1!Rt#bWr`%*<0m?fx<>@z27vPJE9;n z0;U;!>_>^`<9SRCc4;>F03!z@Lm--K(pmmd1aM7SdQU!8rLzKV7GYfjAk7A(v=?WO zTCvJpYwxR~*|0dR_M3jj>bzq?kq~Q8_lz2Qq*kOXG1??Qm+6Q44ND!!YN80j)Dgf; z^I&_*6%MY>c*Fs_TdaS5%I7&6w1-x1rY*F}<0VD7j3*E}i7nyW0DmXD`IM}5Y|a*O z;}uWCk8dF;LQuFAY|G29UudQH-zhgatu05b3@{56E4$qLlVN`7)puFrh-V7hageiN z@Xq`W`v1v@&q~Ft3U?x}|AA0FxGqko)bPKP)+miOx|9hrOS#{ae`(J_sQr7EmM<(Z z@rodH@MK(EYT=^3m=*fXGCZl!<^FgEI21y|LvX6DudaTpu%dAH&wPPQR-2DZPiqFe zFZc&UB@KUx_Ol8YY=o%*FQO+JudaMHADDhMl02O_xQuv_Hia3AiOk-;BjZXVe&m(x zs;A0%kmJPZ8d~^3#S(RKHki-8%*4%?d-G0i3PlwN5%?3Bg}(F=iz7nYr@)#8S~rK> z0d;>V;2>cnBcT{gx)BeKFLc;4!D~^i#E=nP&t)Q?g#M?Z%B)$pflRymvc5G{3kYGt ziWy?eZc*BF2Tw1>IkJ(0W$ruLo_(p;tG$7UI1L4FAfz0=ZfQ~D&~%F*FoalP3S_(9 z^v;`Wh?8W5z~j`g_cp9<`i`;f|K!^SjEd;YCb^f#Y~lHhOm#_Xs}tDEP|TsWUJUM;PWnRj*Dp};xgMvP|L8jGyIsaOu#8M ze{~NMBG_s(2su94m*WE|8u{O-Y0PTH2jzOzL;AUl@kUr!XFt-I9Xo2%w9nMXG{v%c zqo#?3J>BS>dd8SP5KPU@&tu;nMw6vK7J1N|rzT=zk~{wKEH7Cc6O`=LFK=tH43 zs)6Sr-8hZH4goqkxy9W~8PFfmS)yCVn}FD=kY#guDL(N}XpIjMe$UdlQz$cYOTgI{ zx?`##q@q_HX@T6+sbz6UHjKq3nKoXo7XbM4OTU4Dp`jeM^{&A#?|CjUWW1+5zGq*C zp-Byy0%uC6gx|4ERiYRc@+4$hQ~q1uZ+9)5UbP|PT{ud{uE6RFFs# z5+ql@^!k$;**&cOgbbG7DMV0Em~K>ckeL4ee019?D zH9x<(+HQ!qQk--q4tAjjQ0Ggqn`Pa;TgYF~em$TV!#>@g-4Iy@Gfj z_$m=&V2mw;Q9LHEz+6rgF6TTqzhS8w9wuF?!M)|nw-N1e&U7Z{q!uq;7`_6h!P9IS zkj#K&SJ=hoYi59dU>)Y$-h>R?Zc@m{Kl#&CQmub)F%v<;gr)H)`FD!57(XEgz^V@i zkP06ydd7CAdB*)-?Fn%hT2`;Bb2F{@XS0DuC?qTWy^u>84a}hxspbr;v14;hF(yyM zKOgqrBsDN=xDSM1++2tWi>2VIZXsQ1<@rePd5w)$ zh;u|ZPK4N0Xe63Do)m3VSlpkmu9w5=j4TnCF7?a`c!u_m;A)gT-~VMYk|~7?^BIAE z>9N$nh$$Kj0{=QvjJ^xhPBm}m4n~w3Z_IfnenfSultR0M4S+yLvVMr$zkm0_o`p#k z!NPE@iZ+>41YbOCpjqO(e*kPZF0@k1|0yBE{0E82DJVja30zjYk;~rx8{_?75b7D5 z&3Abu5YMw6){KE5gkir=m=paD!DiqH3k9f=Rc-+lbiX9mi* z<*;S4xd<`qyIP!REX>5#94X2r)PMHN#eqL*bguj~PCe*zuuyXO>C5Oxnh zZS;8wEiW(6%E~gvA^$hFF9%iJjAWVq&=8t*`%DU=JfcfdMHNF7d3kjj2JG@~E;mp* zfq&B1cWR6KbJ}UD;!u&=N^1_3f9~r99-UIOOgl(S9qsL%jAG@*e??yG!TwS>l&6EI zWK0OU61=vpw+Wf?$Aih!adD;qKxPrrzcwA%p{!AguCgHHfQg0K>a`)rCgp-*L!7aw zqZgSq5loRjLmxA_w~yCYq$28=5)EwvRux74{Bwgb9fQc|FxK#eW=;JMh;e>wg!qHg zgv5-+x*fN*fi%?I?cB`L=Pzh&muhlXoEOD@RBKh6h%AUmu2p5TsRjNyj;Y=TG#x^h z+6P>Lp=4lA{Cc|5$o+V|tKtbvGxB{IAn9uNKT!SF0WmllV1yY45eD8fA5MT0IrOb$ z&kGyui6F$oR~gh4>0U1afTGICcJ{mZA&42oFX}IV(7u=AQ-c>UNAUA&X`j0knO^u0 z99jDuEHMC>U17f&AY6R7#iSy%n!uu0C_DSr9jE${$Ku(LE>pb zN8>vqs0{Q4Z3}v00x&0_Wpfm|UU2QEdm!@MAo^8dbz-5Tw+kcd0!GhaPb7(uTvg2w z-6uBeo;A$2p8q89K?N8Of%De1G#DEQUFLQG|B9Fg)0kJnyU#3&^yk9`*MToD#kIr% zfCK=~j}I&#;JuKLjBuD6&nN)Jh2Q_cv7)uphFw6QL-7%yzXid!t0pt1%l~4>pN0Ta+4mZ`ySHUC@Pgzv>n$pFlsfo*D0D&U`uQpLyt`@U+p=2qNX!T$o<?W zslaHX^oivc`$a{!^9}<(r}ZSxqWcFUQjsS>!4)os^+-TkD)fbqP&r^jY;8n2!ubA0 z=yuCs1PrJZNa9G!^VVj*p+gqE9T4fp5}wir)B{$v{{pzo0K@@$KhRcO zU!5XY#y_QZ^YG}O>;{wBX}N-F>`Z^9p8r9+6w$QXsct*DTw_0MU%SJ?-LaX1thA9|nuTLNEh2U_RO6D@9G-pWwXD)myTOn6IWowgE-{fCpb<|0{}V%jxr ztk=Kv`9ot@KX#N_!P`0OTFlrV{D{~}(T>YtHgx*?$ML~|#bV2Cv&T8so0fN{#VQ2~ z9A<;8Cuoo|NH2{|4{ZW6Ix>87EOa}9_hQrGaIDA_=nfOc|1$A_(Cw?!ADjyDel?0< zi9Yl(!XYSCJ0D~fL1TVZKq6-Jh{Lqs7Yvxf&wX(|5Uc~xYHSE$Um4Bd8t6*-F zU=>KR6Sst3!*72J%M3u{wC6k9igjU7f;(DwmXXn>wD`%L20Q?RYS^7jO#(Gt_(y>e zN_Mshu}5)?zgt%jPn0$Tm*FjyGt486zCQb4v**9e@X3O135*nObn{=`=jzm%F~-#F z`@+@MdtKwc815_yxA|xNk&3VWfL3nTSFp%E>4R{bDu8`CEU^p&IdwcuU$yN@-#>0rW)%&)|{n(5d z=Bt7|htr}7*a1c>Q=plHmwUqA#|Qz_MTQfW&F^oOMtvXeetTLKC@zJ{qX&VG+oQ zAe2l3Um;*_Si6bgR+z&C!Bx3Qi#v%S(h z%75K44Y&$mD5*`WgZrGVV>wfWVmAaz%INXxg8N|P*q+E;E9ha+dGB zCDml!(Xf(Ceg&;^)flm&DXZ`OnI%f0cL_rjfaQn)u7H)}u6cDD1WGB$nI_cJ+6q-;{+X;HE@ zXtO6%D-pn&2Ht<}YM4b1hzwHk-41xSwzv0wcECn*L|J+S%ULvwpU!~CahFTJtQvTP zT2;hnJ^`1|x+!w1Qet?TL+XG?cng9E zqZT`4$xnNTb`#8{bDjLokn?~MoFo}e7uLy~JwmAA#_>kTvcqPrrh*NFohT{V6S=VF zPYz%-#)&fc;J9wuya2?vl^g7)$T|ok38eIK7z6ujnz{NHYgi}+-dt>3nAti&Xf8Rca!I3iQxOIu2g(I z!8N*AVNazG-#$aeJ~`~+;C~BW?_!JEohySq#bM6fVdn5?27wJ9eCrqe1&N`A-7+bC#o-_S(VrqC)~0k8|(CoG5Ap$$+TZTJ%|dH%+R-q+P`EGXWV6 zQPR4u1>-Cd+TTKE>PLYHx0OwJ{3mL)nPW5brmuMHzO&QpI>t)!UTf;nQ5BIQRsxjs z{&w-+w8wRSflH8M>63(aNeO8mW#DhB7V5Z{5D?GhV3LjI8@6x?NofN& zK3P+1K#@YT;1dO02ABDon_gVBD)7#55U_3?oX@+$Rc4ftPJi}J2js+WuY!(zv>?cui4Y9@#YJ}bigJbO*TIM* zPxu7{jAkGN#^Ob58g|NJ3f?6Q7&U*k-m~;Sw_bHyR#UTaD0NZz?Iy)~SLKW6tfWZn zuuLHWI4Ouc)XP%EHT_j%w8{o2sVxU@tj}fL^x`~3E z({Ft8%Jk8fea|#J>n&+%#yzXU*wimxhDasqwrW*n4VR2ukXxDUgz^F0nTP0&<~R!M{Vk|vPYMqXj^ zMyRcA1nV8d>Q}pjK&n>9)j6uXd<5Oy(zF4LxDR*1NcUK36pPm&mZwq-0hNP5lEA;w6+Tya7QOh92m?d2xj`U~GW1)g zUGD$f(K>>Ipx8Ghcv0xQK^2qHZr5i*`qT-N%*?|DuL}Bb6`BrlY{X+xUuzY^<335$ z@9;&`fWG_i>fvUl>$YsH<+ZP~;*`?k$Vu zQWe?jpQ#))}2uucB88A4Z^Iba;&;<-IpM)S!{L_oMG6Juk(aYi#+E<=ct&9T0sf~OI8 z;CJ8zo=_8R8tirATQ*A{>|dOMoXiZ&-Uc@mdr>`-lqsgx-+Rp$Tf}cxqsc11b;#xm zERb1~A-e9R1yDg{`o$PuT=>Yg0o^YJq2X?ui>GwHj~`hlpGqTuz(=PuW5$D6QXr;GT>2Lu>uNoSO_3b(X zp{voQ)r7Pg-;XQ*K}~z;aV8sMo_;e8&8x`H?4eS`e(_WX${*UMGZvfsvN3W7ZeMGz z^SDU{&w~4J!)I-vN?uoiO_yf4F2`98|F6|=Y;3Gb)ww&)c$J<;ziA(@2xFP_a3P9F z1^$VB2Q%gwHMVmJL>p^sTvp$u1X^#^&=Riu1s365V9Wj4Hq7|2CytWm%^hYpH_I^P z2%}mrLdB|WL_=C;%k`YxR_E%@+kDhZ)PuT0;~8i|0-v>?le>H~GUkKaM}_**QY23z zFloOCvR|`~3Jml)N<3h%wVUUqv;6XAB;LUz>CN@zO!Zc8_g(yA<9YZ_>l-T`X=Ao- z;`k5Dm6E~Vc5~V^_m>~ZiyOXiD(UpbFiAeOhFw8lT0DwF5HPP)J~Tf3%CwLno| zPMf689DKafh!E{?(`1o9W%58R$Uw_#%vO3f254de7>>KssJ#3-R69k%eAo@hzPQFD zARv9YH=%o4@4Bx)l)}Zq!Qsei_{~>3miqI_?e)1q^E)-~Z!cS6(3vuC)kdQ~B)8E$ z#XRezP9kpd3s|Cxk>VT(Hhi3j60)_k^J{y1XpzNV4Rd^Ey`-|zWw3@>mluU^S?Y7J zQhAQUw}rU@K94i_b?oqp!$3ZR^QPn`@9qh`c@W%2qwVq&`;M;|L#-FnElrDuOh$;3_^ z!E7aUp<>pH1g`cQt5htby-%O^GzFUuyJfqSpjSg0ynF3OKk{Q|*FY*b-y3;NdD(-_ zK&?@<(k~X10$FjA=KE+>R%OHa{yXk%euc|dt}AfjDZ3s5PRt0-Wx`Bo=&K+5flb0u#kat{p~T58y>rwy5HV}+S;xJj&pca zl8uzcTIr0L4ZRDQSJOA6pRFVtwmG2;dc6IP-(LZo(fO6sbkRq9nxks8YFuV^h#BtiZ;x=U zQjJ%7y3w>8xHW1`1<%)Wo$7a9JLkpa`ZG#Ep?+tg=R;9d7OU-6Wt+0kcAqlqqBS8@_tHzfky@>G`x!I+C-Z?7HEX$dEM6?%!XAg!u4FJ}N^a`{(Y5$yR0qT&Ex}d9k+JA`C+Qo6t2Iy|9T{GgSl&7=Q$8DXbfCnuR-Ca$@Jo z&-Um(R~qyh={Dk1hDwO@IaQDgdRjzokzMn$nqF=*+_!~$bd^4JJUFii&5N&1O@&O5 zW0Z}&$@LHI#K^kEb>XZCdsqV`#5@2sFIU|#Y-Y4(==D0cx^r*{3(ujzs;4F1@bXH- zpv!WBFJV-o%22Uvg^v(+Mo!hy*Egr}axk~fz>fK=kPug+tB?Mtq~v74qnw(Xo0yom zoiV?iStX&G5Fk6-)d4(6;_o_n?-@4t_JFu^RX%k^D;UJYWd@!)nH`<(iGqnh7hoH< zoRm}tv@GW*6GBV9F-z^Nq2A$zLH=nc3r9JamTWyDz~a8TUo2qQw-({$1Ra(I$$$ z3KdWk>9q>EjORW+JiIrgYrXgW*41?x&O+P_m%K%IMhu?^F$RP)Jdd`|!4Lp+konXd zmFZ|HC}95@p>BR-O5-DP`}>E=?d`Tk`AsLs$P46}4h%rc_7?%#%th~OE>4UsWP(ZW zjr1up?N45l_lx%nfiGxY*%`910CTi?-^WH2l4k&g6(s$}!m>X$qP4X}vh+HgUq39Y z10au7L69eNUo0DpyG#g8%vttkIPlg&LR<~)qc`Y7HF9k<-@bk3Vf4J-=brq7gJoJO zR%NIQX%Q*;XA=t>?A$|CJ@T;yP&#U2HLz^vajky4lw{9sRUI|B-2XWP_^v+|y$7z= zQ&nl-!=a*7pWt%@tCwzm&y!8PJk9~!EX+>^@-Wb5H+OfbC^a;(F@KoXc$XyyfZ}<1 zd#-aqM=N=!@6OkH&5V4tG5wi~$Ig=&8#~fWiaH`Nzg(B^a<)crzEK$PV=d0^Ohb7* zVe$@tmk{N(wvv~M1RYHjpnmmq@2NBrY;;BxA%E^G!p@GNkUootw>k2hbYH>So7?1L zbv0(-&#zASfW}awF8|fRNJmV}d=hDm$gw}z>*f$C9|8JBn9lMo`0S?MWbgJDpm=!K zB?&!tI;(^U;8sz+q8M}%yz6b?tcPIOIo^Th5vMi0+s4NB?bxn6OqdHr5ow1=kw5c@ z*3g}w|5Hyn&gO7FR?{St28!Xg;|7-xy@vq=j5GxA-tim^uxNZBoPpzitZlsaQ;AUt zERPtJ3o6EjjrDw%`$f~!Re}8`W=?vkpaiDdKm+iKNY^L2_w=OnNx!GR(6zW92Qxl3 z={sDt&T{(slm0W-m-k)_8qkN7G`F+UHI#BGlYjmk5RZeY$~D=v%Kb^*05u)y_NmA- za-wDwh*cYV246M4yZ7BCM;=6(duMNchh9xLtL5(ISP{I#1TKgE^Nsv@oa~8w4a@}18xs6ukj&Q ziI&EVYtn~m838r@@5$3A+usl0o&JavzWp+>^5pAK+elSe2%zTy>ZnnV#~G#8VGWs# zRa1gkJ&CHh!IJ2*^aHnW3-5DZEX7QZ_0$X z)b-VMo)2+9k>8zrxx_7BP0?=Di6ZY4GyPY?n9r$(XDk zj>Oh+Y%_P36&}vv(e9T55&3j=YAr23gL|@DxBVG!sZ~fiKZL4sYI@c1_xCmjAwc}J zUlj61NUEOd)H!FTT0k2WKbWm>i9DkD;fH-{^S9_P%P)1TGo(o@g0LffYm(Vv8*tD%{k zWkRFMXM>R)(dLdG_Q1`0h@HSFM3XKLT@9^Hq;%cLzkjPNqo0emQ_bZpr!0BW%RT$! z^EHO^fZzKAK-Mu|XK$WRZ_*d|Nig7ZoC%5W?OPmSvtJXUyzaco5E0@8@Yc(M-9)}+ z%oSMcqev{vPl!dr1>7~aF$xgL%#&hLaF@UV)C|>h$XcVYf!io=@~>5d;>azpOlZRz z{FVZ-d-Q;wc>i4LC(%IF@*|QVcEGJh=Kr-h_TvEcp##ZsAw?LU5QaxON!;j^+$5CN zgAo@G;(*CBfVn-CRLGNIK1vs{wB!Ivq?nA1=69#xLGAVuV4&NRT7XCYt*t$1^}^O{ zW5j-_S1LM0Bnz^#_y+rn<7>jj!Pu1NIZYG_!yq;V2iKbR90aZn2oL6{Li>ZI^SfRq zGTR2D?t{lu>XrFhRVaj~aNpBy&`zSI?Ss3$PYoNV zzSnjiPVOzXCQZS}GW=HOBriBsLwhmHQ1RBVC+TuWK`Wg*SGSauyam#Fl6Wkj#UO44%suEej>gF z#=?>t>&&8_Mq@@GYTC$v8V;`-Fg-(zR}JoGL$yKB4_!s4c-Pa}WaHT~$$KzvW0`%6Fbc($U?Q78_gZdz)p>@0=)#x|Y zIX@$7&Z+waXuoh6U4HEMR?NDDT>Co{h_wF!7Jp#hc>D`kL{0GXjrn^TmN4Tf`cy~3 zb&sgzbTsyv9lLmz9oR>{`q%bPV5?^Tuk1s3m<>UxadbU?pFgu>?Qx-L`^p+Yi zqVH|zCEgXB49g=={Ep#wF`TU@qEXNNMg1o{!JixC<;vO2)#A554s8qEj6a!2PyBTE zSZ2C*SJXmQv5YnlK^MlGzgq3rFCMBD_RmS7rvy*(n%W+)!uydo^mX8__itAjGCYp~ z{Y0VSDyGESbneblG;g@KE-vl;>lcSLrL;9S{Y)Q3Qdc=up#5bLZ|24qQfc=yM~4H~ zWa+P=LF*-xiJ+fN!J6GmAt;4O4A9RO~1 zwNaBhz4GBjJ&qo-e#C+yoR`@B|J)jEE*yd!T3aBNgascXL>G zW!%r7ri|3>8`Zt-d}eY6s%^r>wh^&#GWv-yI%A<};wlgDAn_QesN2aK6bL@DsDm^M z+A;IGC$jYG3_l;jtiqo#OIydZ+Z=X;0@;<*Y{{)6QMG8X@=E5~Cdz%4%8geIZYcF6 z01H828O(zez-7E>kKt^jKw;osM+r=3n#Q2tk&0RWdZ2CXDr0+;YD>WMoy6}iQrPkS ztMwEqSH}`XrmbK5-`-u896R?|WI%FSXjl(lsg&Tq*P1@mkTdQ(^NMnRqigkN_+%k3 zDdQCf0|WcBxvC!s73`jFEWBuE8APe$cl5oM?<{oHb#GcOB!7}bMM=eNpzpPc)Gy!j z#>(A)>Sz$zQzhU!iV+?$?2Xo_{2eW4MaYlO4~WrxwDeS_*_GfZ*9LuvDawRF>^?{+ zH6R%5GUcnQO`e!Uz_Ly;s1lWU!Ovg2ybJYmuH|TDPd$sC}2WD(mvgA z#qFj`lCu98T>7>-3iNQCJ}h?aFK+M4+?T%1RELJ3c-81NuJf*)?Rtft0x_78t9pel zA0H(pS~5B!+FLa0Kyd^$MSXqx_QkCU%Y!+v=@;)F1r1~@`|-N{>g`w~oNLbi%oSOq z?vsgy0;6Q{EvST4u-o;_<{c<(c0y7XnhlWP4<_tI&FJBijqsns1{Nh(I3VVv46)%z z!yuefL;gm4tG_V;_k;)&yd(4bChQvsHsD4HkjH%)KPLeSH^3T^3^9?xZ2-1mu$B5+lRyhWQefI;p{!cSvoHF{;^ztu*- z3$Kq62Jq4TTaAxf?(Yu1UBL4UOv)NsSj@f0PG3q`zWF@(64u804`n|8OhBB?qF?3+4Y8#^3ucrv{|5`6J<+R61|kE^E4v9xA;s^>RS zoRugv4(lHPE&$fKryn*z$a4JApVN4B=EZ1AuS%Pd+9;P~V2hYDx{eo~>rXlMpGPs} zviLO5<9vhdhZ@`sp;S4rB@A0-$k!n>1Ti-7GScK<@7aq{^? zhLrew8vEXo5G_K;Igu_Etu_Bd(XOG<{DYbSnf zLu4`40u#3mf7R%Ki933DB&|DzDN`lcDvTAE?xlyS*kY&k>Uc!7-%FiQ{{X3-rmUKV zwpRrluge}1J~I|V$=uhjrn32U0tc@-Aa&h+Iy$sW)9=?68B-u1-{O(14y7jdYg}XZ z1alrC*0Ivt4jV(xsZ*Rs^IgokS`PYDa${J2o6=iJo{Tsx*QjsDb&IpjaTiaJBrADL zSY>Gp@zP6;3sx|-j2@vg{}$KCnLYhc?_UdVFH^!gm%}JW_dU;|QYuH4`=O#I#s0O# zh>ra%a+W__@H-Ym_x39!M3_Hm~&$x8FSb z2q90f0$(s>g8_^nmj3VyrnO+8g@7R3vGT^@!Axe_iEe*!L|*3k?)LQo!gV{3BX%`2 z99a>maS`<&5JrkVRO-95GBjA+v8g`{bDNx;AC++W$H2g9yaxXPZoTPWNaqa|Kn^@? z`8A*b8Cu$x5ppn;R#Zf^w;!on^hSO{&ChQ;1NX)E#OA#%h3F zPMeoWO2ff{?_=Q8jLCllKsxZxBs|*NXTfW2`z00XRSl!VkDs;!+YpuJ29KA%2Koy* z8Bw5L`_{wn+=PJ{0tO!m7o2pj{}Z;0DD%%vO%6fTuz0-k?X626$lgW|C?4&w)noRj z1+S7u_peR`!6c=BA>338lXZ3lDO0$9R)C%zvFP+Q(?{zwQPq)O5w2o69lby9)$a@SH=l1w#Me zkly+)RWj=JvfVlJfkh4VERoBti4d>{fMNP+z5#R^UD=QE@ev9XY>`0w*;+G`1&$y) z5P~0cM~qxb64#T>My8rDDl8A-oI{DNE@YvS4oe8QXFtkGz4e}xJ4rc!Nx*c>Jb*{cxdg{JQcYn4tNBR5&r8h3FxhlN|)DwXWd{OtlJ*7_|17~}s^N#VbGt4>H zf5%2!ovd}wMg8F-;Bjtdoz5ENJfI`T>k+k?i0!}o^;y}|9$X2n!3vif_*@vD-rVc} zQN$AFX@n!y9O$MrG#;8j9WdUL(0tS}|8r5GefSwwYtfGhCEwZ8K#<{lB50!ye3 zdU$HUU+nBZUEiDR4@vk}%VIr7` zn~(8fu&EsH47!G1K8v+@f|mrV0VUj#BwNN(pRG)Bri)0{DSGHLZ=|x_ndm%&SjG9! z15xDh0)HJRuBSUcM3>P^ozeI}$}C9xmQHQcJs3SqPt%?~MZs8BW<}py91$mP+?6l# zzdNmnh^POW#$SWpLm_bj4!SJ+{D-Swu|G226{Gl!K2gtpv*=HUFprIk8}yWx#DWG4 zG^WZ0Zz>o>&H(lGdxd|w!D2vmRTYkYedTTtu68V>s@n3uAO!EfAc2Fa5t&+X{U^Ta z%R~d0(yxUTZ1 z-?z@85d7eGwi^0`-d@{RrpuSSNIM3G#Ux&w()IXJ8U>T#RZv;g=-NX^d#dESpqXMd zid(a1IZ94ci(ZMaBW^p>DFi%1Jx~1gDA(?!*3~|rv}tG}e5MMoWJW`zPP?14*U}V+ z3bdgkrWV^mtb(j{fK{LW-huscTf8YmUKgOULTz9(5+qchJ{eQ%*Zy(GBD_@blX=|G z`gp5C(t-9U2Ym*wAa-#NomxsKi+0k^4VIFab-kibjL*_(*IP(KaRw_IoSQRUKvmE` zj)@u4*wAos@m-AEtU33ng>+D>o>aKCAuG!^`Qzhd9Q}7&K5p3h`ouRr{vRB)0HjUM zFM9U9!XSLU>Txz2Ww`-Ki3*G~wQC5*s2lIg5U*;*u)<8@qStWw5p#~l;xcv^CIYFg@vyiU+5`qA+ps|-No zTqF@Q*DvEu)#MNOb(g0E;k{nhP6-I&%r=~%HfE^GAklMjapjLG4DE>1z4xBSK5`&zxpvJ_D0(xx zP`(^~AgfY|y7O>2Zk=O6#8Y$g0>F23M*#3k0P2)MoTp?m!0aLj&dtCyNw#lDulpyj zF~op&);wo6iOp*a=JFyi#C5u!4F$c{dMf0;9n-FR^#_87l9}e8Zt_=n@Kd;iO7Q>% zj;ph|)ADlW9pR!6yx<|3>m(w%bbh?VXMA&YsD=Y5;0S+p1de>&BNfajfzD)tl$4e4 zoLzrC&PoTR(cjfok)5jwnqOXo45)HAR^MhGAxL0;>*b6Dk)seSsIq3_Xwp!-uk(Md z=$~_IlJ9S^pcV5l-zzC3EkTHQDUr|AmaxfBbSy zL|c>+h$G>`^T4Uo3_iT4kj=mEBn#|Icgc|uI@-WT!assMNxRGbb*?NEr8WwNVi!ci zps``+@m_A{7UN8?$cV7=x^@8~i;qn>CVLY!zkq{ssU87E@}8dZe=nWG(8ZPEK*IS< zHnaf$Us$;DzO|jMua#$rZ9y!+3SWd~SPd^`l znIMS>OoS@8+8kD35U$lsJGlKprp3wiGv12-MB;8GXaWp&7P2g4TRGM14MUCbg;MI2 zj6s$hy27(8QA}7e4s5aG;rD+sp(Ko6a|3}>zqW+G783NR0~OzeV}L=!rCf`HiO-$! zTJ7f_9ur67$kLawF&&yDUSgj^^su8B3>pe32nd0%Bz%1-#CKkDI)Y?crN~~E`OuCF zCIsxlb+mzr4md-E=)XWa?lAVyj$13G|I>hz&w~a$6cIGw^#qd3z~4r;YD$8uR5*%I zi@C41Z~kj_s{#>AY59!P@1WE}H)pG6S_05JjlcE;kyo@&x2YZ(XX1g0!0pr~nQg@X!#%>f=F{zOr0>XXgT3j74C+?P(&WV@* z!3|@y9Hd=aDR84>lx#&^{u8yI22cJG#RM;XFPJEsb(n$JIkBd0)pd}=T@l|RvMCsc z3Edq1eui-1OF!1cuofGXi7DaMNc#C1IAXxZ-prx@TcF@)gvQsHu01QHZqk$(Ywi$` z|36Kampw3E)*cuy%(y5xb~mG0QJM<1BuL(PZ7>C-0oB#9fJWA78}lBcn6&RpV%x+7 z(WmY}DQ7>>EC$f*h|d^~sRDY@ zQ#j<`k>bM4-5_;OXG2@X{V{3IdQyn3iT=Q{Hba3mFzOskI#*nllMzr^P^C9*W zTyrFJ0N!aZ)ZCtwPvr49+d;3t>CeZpg0x3k=(xC?VHmky1Y#u=)#6Ur2p4+#k3C~$ zjK~4=1$rwL<$q!yc1P4Km=Ags#nbhNk%kebXrrzCJLCW9Lt_dk0vUY@wyO%Mv=AHx zUOV_kwcFUB*1mw*mR|Gbxb$WeH$US#*Wi<+gvW$x#3I z>2S;1f8|JUO_bUE-;V~zt16(G;#G=Yu;q+vz^lXsArhrT+uVV8&HNCrbNva^s7`Zt zlyuBLhor1zcEV*9{?j>Mh@zK?)I?bA&cW%{8@8UW$Mb6+>&<%157c`fcreBw@?$c=+#1loc2U z(i)5BPY4vQGn%JROgnF|V4ww#Y0r&NqzeWyv2A0 zEG0xnKDDXa-+=5FMXU$h^WYj>eOfX}dv@jq2Tee=1I#o4MGR>9@4*Q1hN=ijS0TGa1 zAc&xJN_R*o(kUU`A|aiEfRu<5Qqn03(j_g@Ak7{NyyNwG_IrKTKKeNDL|8HZbB;O2 z_{9j#^u|WNgNRg?S6B)7vYlpIE^tb?(Hr#oep+TphPsH?bhAX^vY2Q`N!Rvx;!0f2 zi$H$%d!$BqHhOjU^jQLqY3=vyC@;gfjl1<7S{S5d49jPiIM!Z_HA!;k<4VgN)6vxy z%F+~m`ZNh9^=zC1u8-SeJcufYnC`7s9l2alMo&VbwJ&kKlRrIc(AZiOiiZ-ZES=6+ zzgu7br`~gsgH;^q1WrRUCnu~J-8bH;pX8|1%r*5_ zd4-tjFJKF;h`4x50Xv%+&oZceEmw1)7H{r4FnBWV+uiay&=vAa8`S@JRUP+d;OQ@3ilJs1*pZS&)jR1$$NEk7zqV03I?@TU4J#TgZ;t!2@XNmsZyYU0y=wxO?B#pUu zyVvm!^%BY@ps>)RZ(Lx6D*8f4d(2(5CBpjTXvG$aaI%z;&6b_I1qm&W?tL&`Tz! z*RA_I)T{*CF;8|k>LCIn{yNa2mIE5Rj1&<8gCISB*0EY2(1VS+hg?&2>bI5)S1f%v zcr1rV#;csgV^HuSzc+tNcY|`94Fko`ofZE)r9C|bI!2jZb4&O;#I#wtmin`85wlSWn$3P`{)dzSK*`%Dyd0VozT&X6;4tOG@w$iU1e`PsL(}?&tbFL9 z@@b%u&aNaIceP24jm7FP{1h-2;9j5psBh;mUJIib?;Hq|@=}2nCkOS*Hxkn_n~Sw? z7_Yra(bbN*I39NKxMqpM;hDj+zB&R8iYe+F+1H0!MbhuUV5aXE)26hv66I24pC??f zDH`e65q?`(qtnQR-CSx3O=+(QW@cG=FH?N%orl%lX9!JSkNew}?*kP{TU(n5(@Ei^ za8hRnOKJ%)lN!yxRCQq3++Wl}k6g@9$}P;A+%umReG789A6&~9+b0Q9?1w}|I$hnj3=%Z-7S)3vPk?QEAhT(0Ckazjnakbg~Q+)xW#WH7Y@4HWo|7BGFeE;T|m zU^%iYak)WXUk z*1EYt$CjB&XZjB?sZ|DSfg+L*xZbvJR12gFb&}$6!Ey*$(C8iTjaAr_2}pcwfOd{= zAHqibMXM{4%CxJr@Vkd*T6>4&67P*My$|tgF^_H#hnWrn8v(UWK|V1RwHqj_xGRC* zj}PXQuDrs<#y{DRo(GXixlzFf!l7^9#+N<(CTd~FcSG|A*ZJw04f}8o zDYLIPq2Juo^Nww8eTD}3L{%3gD`)Ci-pZvh8?z%>FmILRo9UQSDwVQ1gq0CAKGPR0 zr;&%e%^eXUb|($VKAN2PB4=v9&}#x!CKzWtzgKhav5j6zpv|n6^yrB44fd2lcg$Cz zVPpJtpVoGQk;rZxhD2>!+k*go&&g-~mg;(HQocz=#q|26y1>Kh7+>S*?lA1f!E^9Km#SD68d;2CFgS&Vcq8V~Xa*V6*F`aU zXc|6VpZ0?+`!kILZ?HrAGZm5{jUYu;LS=MuPh8Gg%IdlWvPr7d!vS5EJhw2ZCAH*EYBEpY7S{}8uBF*ey zpO`Q$DJ9>Kba8qQ#plIl=xQz9qK+ehrdGOR5$oF&p_m9q=fgeq!*g1E$;MAl^QXt& zxPpuf{01V4bO-CO@3I(P)6tqg5(M538v#+(8d6@z(Z~>TRtg{y?kbUfUS{2;>7?&>-INIBp$TBe_X(?Jrb7#06Ov7K?XUYL@p)!6)ubA*_*+Y7AIje8Rn% zFSru=sv%*NxQ~HD^K8`}VRF_mFfwu!8gYfc8rrJ83a)${8IJD#kgNZIzI}Y5g3aQt zs@O;u1+=I%{GQBlaou=6xCUKg3g;tI{19C_**{@ z68-_4;SWsl$)R20o!ItQJQsaR+Mg*J3d#tarbAQcq_j^56NK0@;)hAeE`^*8n0KMw zeSPk^uYH<&5@$%cmgj)sEBWXWTx1dTfTiWt?u%){ncG1RO!8dOSi4A)!o&uPjt<3@ zlni(7eBjl4JNoI{Do?-hU7@S4U;8zd(z5yFJ@7j5HTc~3hyv7gbyolt8rElC>V`lK zS6l3P)M7yGCIyPsINy;{Syt(y{48U5HIj^H#rn6N8m%VdL+DIU#Zw)X-IzHSWV&$gr z6}2$=*H51*1Y%KWqQg^?f8!+6cRr1#|49UY#3hk~2>qC@{`_~#VKn`p5`pud_4#c; zRv5C{!X`k)WjU?OFq}!TuKY$0A;`h>F?DHVOPsE7Y69Mit?%>=nRAF_t|FIjT7^0h zfXS?vCtnf;gVX@22W{}K3i1Ka^91=s-Zawkk=7=(!dht<0cc+aFRc^=5XivIi@~l! z1Ai_Z@oSl;>hbp{M{6e)m!;-6#U`ltL?4lm+{Hi~7nRapjIJtYIp6;J`?b8oUO+V) z((|vW4Bq~dY|Zn)F6LT{11Y!F(8Tf4uVBsc68WTq(fiOwL9&fCkohED7P~fo;46?t zr?z}SnszrAz?>VsWQvuuugoMp3 zt*F8WO9`3Q3utKxovs0!5&%{1E70kD6E1iEy_)8ZJQ;01)$k_oFqzR>z9kmZP2_W4 z%Jz;s)UEl5byF3XfZ+E00fDwcC_O#CHGucmXV5c#sc zp|i8Cc9FZxbnyHnXB+G#3?yP=V@6g^Us2;-kib!9j|NHfYOR-c!zl{ve^D4=e!~R+ zEa6J+db>)`-;xD%>J_L(ZzHj3OnhwD{h!}nt2x4~>$$Gv`-B7@+1A>HAD-OFRl$NX z>FvXBf~}jHKmpw#*Ueo0D4zBG`pW3hVX*VCJmc$$7hyn*e}Rb(mfk{&>;F^6pkV-@ zJn+c}s_<|vymB}#)w@A#GFYxz-W3#tYx?sx9;ZOh8uS>YvvWVaHoOFOj71)Y4?cfB z*MxJrm{64xVeKnOQQ$<6X?5OU5#k#FS{(?yAe#sXKlXnx&+^sZ!XN7_sS(1m@`-6p z(cpv^nhX&Y=rGQ;4sc1ur-u;1&hwagaYujsN1}y1KKgApi*S3vfOKg8Va71 z+wT!;@Bu84?p^LpDt*krc>!thUvr&Q1^3QLVtP@jZMS-;@lCn~97rY7 z_+(TjqhwsmTz(E&zwu6$qoYquN_rHueJ~YMm>9Q;)-5s~Rfgq(e}vfE-&4Fb%2dh5 zFM}s@8{d?XGD|Syj`pMxQ ztuiIaS8w-VhxA1t8HA|$>)64y<{lhIb!9#Rmw|{HgAxIcUZ5?oBX%y|#PJjGU0+0s z&Ud~@R+z7=yZJD?dV2_O={?~7@$s$oP8mPN@y-(Vhgw;5j{Vl3oC_|38jVHC_ng>$ zjH^D+2RnKGV~N|A1ANNV3Lae8!}6s=VE)`~WY@jLxiZ%2H|xcPAcaYrKELGOT<^@L z$|xXD%6j&{08yK;Ig>(w`$_B37L9n%{JR#5#m6ej`U{0>u>Yn@a*dw>RUkHx&P0%C zLkmO5>5&tNF*tA%`#!p#xq&v|_wUN^HD2qH1m;Bd7YUUe zdTi2Od?_zSOk^cghrwTja$*cMd}%2=vh>l0XIYiOAiDqtQrn%iW(=N~!>$#J_UT9tC%~>_Q^~3P5_<+hz z`jr#AZEiXGY6zhU6k0!188&C7yK`pipac%1)plQ>#(dPBysIvm>SoM7B>c8#Rc~}4 zyMO5!Uh`Ul1>n#xBO_Chv4W(FToRZ9-6|1WeDS%dC6o~`vfaw0+_5_dG zX8*)jwJP@T1ERhKiF?IcZy1)VjhsMVg+pZzVfrZ+IZ!R-~em7=fKV?W-u zbieWG8IiIHrtp4azCYsg>uhgd%t9!U1Fy#GoZUQSWps6mcs5Bt7a*FkEA37%ecN-y zV)kDvyS5Dyl4&}@zCztRNIsD07^@gsgVdv26Xt|8djT`PPH)sdHNwtsNt)zrkuE&B^Fqu9vOxS?x@P8N_|f<>`D zRsf8IFLalbjEs^(gK+1LGaKlfAZE{@IXgSAn)=_qZ8uvU-~)P0*qm-|7U?t4`iwa` z%5=idef3IU>MPJ)js9Np+|@oh!nw_}Xq0`&wB|3oprxjD1_PG$ zb<=KIl$zZ9EcuHM%$$l0ER`OD=QYLPvNuYEP6NiK>ZTHF?Hv~rs5KY>ZZl#x!6yHt` zBPuyadefdBV|3}$&yYG4VcgQ10{Y`Ofv`NWEgt^NBC6 zth{w@X*xmgMKx3CwnT2RK1tG@3~wHGM(GW7P>~5yI|! z5r8Co{5ZDMngb&zQOK_itQya3cLPLh(CP; z=tg<-X@|)>c>U0v`YdId%0PiT6I8COa_z&?Jt-RIh>IRA95SXqWCZe$rQOhj?g9>F z@RBSt$N&Ei1z<>%uIFgp8m{kuVs9$}?tfH*B+EK75hlW;lCoL?wnSEUPSHdjcPIL~ z`KKrYEpOWfWiUX`7gtmK6X2zbDKA0&d%eSXRWE3r=8K@hk*$tuwqO?D^vW^Dk3Lsh zWUu`e@bmkIho98@dRSa&3R!U7oL?OG6nQF4Mlv1eo^YaFC%@$6QX#URe+*nW7XN_H z542eyBk8|%eAq$fm5&q=;cG3`1QbNsUw*}7;QyRYpHzS5)g01MIy@AJ$Jh*dZ3^|> zcH&c{?<1dwMz{K)cbftiHWK$FqQ>7=KmctMo3yUHG#n|@?8{T~!5kyMj;nJ%tH66g z5WN2AuRni9@_bJv!ry-wND3C?$)`o(lGAD7*Ipy>5NztBUX;mmHPWGT0YiRlxKSOq9jK|&9SXbVJP=nsmrKxR^BrFPXvgX_* zN=R2EBBBYkS7B-fQ>!om>NiEO2Bb8%aS9{u&#ATtJo$e^&W zi8`tH0IALO_U_j910=9j|5`FDKprxnH(G;%(ZpB!L0rpYYm@?t+|OUDs_q<@YF4|v zuJJrn27_ zP^WQn^wc1H{ErFtXJWO1@t2+51T14lu99H@fiHcr8q2{RTL&!nQ4QaZ^6`=hB-b*O z#E8$8XY{lJn&g?R(BL?Kd3_(xDgMz1wwXW5r6<5xjR>GnK4mbc3N`p`E%mcw2O@cX zhfhw+yKpFmZ$Yx+bj>?5FRvYTT51VD(P->(N}kfIer)}ds!S3e3rhI{xCM7%w$Ra9 zvz$85SP}@S0B$re7#sTN&a;wVbg6!g_wp%_)4m*Fh&5783ytB1UpR(n%puqQDN$<` z>IFbk9xtG(f2*FtWOnf9#HUV%zZSc}KXyYkHG1^`pt6wm{@Qa1e{~OGe+af65UVOI&h0An~-^ij;$L>qLi#js9JfUGIMdu5PVfRl=S$NUMYhXa)HM z?HBbjGn|2w!ZF7NiP@8^X8i~1G`RZb{E3~%Ty5x%15998eYofCX+Xe*-TCj+iaJZI zpLuN=_~;-M^b2r!ME`-8;${?H(`Bs?H({2|+a7yd(<+LMy#p)-KnBhx)#8!IFox*c zc3WRWMz*dlSs-U^M1zAI;wp{+^OAR!iiIKYa&J04a@?Jf&(4t$rWHo&`&1%I+L3X= z`*A8+QDU}#lW}9?O0egr!! zf|o&x;0KhEQd8mj=B*#DWNZ`-!4GPLkvk~e5BDXI1)wa6IX=OAVk@0*5PQVAdMx{^ z6($dX!JSQwcKCN7O#@?FR8isY72*$&V!D|1(Ouv=bTK{e0ds+)M>iSeBB$BqFs-V z;)*1{#&(CIVLEwKSayWX_Gu{PZp+1?8-S(3n5dY02>~7azt^hl(d7HN6r0xdM3EW* z>=E${A#Tixc*)>nI0xXUF+3gAIzD+kb>Y%|d|4`*YJ2a%?`z~pE+|^c!t(OV7iC1W zTflL?fkogS@(G|sjzR)$lvn@b--^i7vK|7;Lr^i%7J-`w~LGiHAp3P96(!VPpe-4N*Pao7$MseQYGuEq5 z9`GG44y-hMOjN~mKG0-v!sExcLY4A2YRbxd!+f59y5m%Tf;Iv1nN`&eER?${ z?7z%h>Hul9^JkDe0YAuo(Wx3dqz*8#jMD*B=Hj&qn!EZ>A<+Ron0dSUPI@~B;1=?d z+nnRcEQc==?GAnopeUG9w17a!q#3SLq(g|aAQFGV5f8YJ#GhsYFerq!YgNXQpt82d zlrLN3r8^DxP+d>Q|F~hI6&O-={ucJ9waCi_9qaQ7i28vuHCIEft=1P-^?KcEgW3uZ z{Y&8t^|hx5_TiOlA=EuQ^VpQLCxumL%tnU^4T%HdjrZ3kX|A8)^?@E9_Mgcw|AcC= zh1X2p(N~e%5WI7SSOP-N4<|f?BnR@Tvy>>TM!N#qu@da9(gDL4e9+vu+aE1!VGb)? zjptEekX$W9(v>!1Y`J3J)QKFmD17A9ipx>B%-~&OK_3aJ;n6T8eYfHMkE)~5T0(#)Ztd4N;Yh`$E;hD17vNlJmlP9!3!pZOJ1{{D zCBSVcqGfnp>~Ht*6|xXXDimk$Wga{wJo#*k-@jv()R-I{iZ)a3xMK3H;K$8>ii)*_ zPp9b8;=yhKpY^!#L_LOPb@&^SP?7&xVcfkklRWxB`N2LgLy&@?jHaYM)(OE6SwFfmq0xske-H6kd8l zwRSQt+eFytmFbDv$~_>j-mUx!GL5aZ+`;Pojrv6Jnpyqj$Vxm@cwl1OrWDiw23z2$ z*BJJ{r2iJwMkbf{cl#tv{(**O%s3wO1S9JLPB!M2;?&amMPEi6_LCw2-X7IUl!IU? z^@IgyQTIB@edH8&q2ylu=%lc!$Y({0zV>K$oxnL>Fe?t!AA*7-&@EBg-v$ds5TKgg zF93pqYQI=3(?L{}m8rZB|4S^M1Vw?;qkNPhe3oFr9-|K5D=(ImE|LRNIl`s zqo+E5{;2hQX(@TR<%0hwFkvaw84Zp8rn}<%09jPJFM(_5;obn0@t>NHeaK%VA0ako z&q6pMrJ@y7p-ikOq|tmuZP6 zVq<^Je~atOd$qU!tx#(hhh)D`jrAF1i`GDGgRbz#MqV&}+hQ%qp@2hhCEg#bLnIyyyRoj3cQ)fM^2Ld1Sl{K z=9ayMA+Q&rS8@aiHJ{Y|P%wMCV`Nm$X}Bkyt<9Z-@nZ$f)i`vvz{nT^5z>qW5CTbD zu0)}P<%NZ#)+>QMXXNEA*{|K3F1KCdLgq6vw;ZoEjE>s(y}k-#eS!n#M?h@IB&MyL zBk!@dNpD6-B35pVkU9Xy%X|u4btAwhwL@*s1rqZUo6$B~d;44N{AZO_vC{Vs9FtG| zu6zq;f2Yw5HqO?|T)-!R3&Uz$IN_I!`T`In>Qar3nDi3S&|ogl>TGN(q~b&({{l!X z27W7g_}HrWC+VKU$v@eXbkUEY1^3^jEs-|E+mqFThdRBVOm6ee$X-1dQTh){-} z)!lH&y6geUZ0Bp(7+YWD1fKN)5055YO!&60#|HyoG*VnL zqe^73*_~`?S0HHzN8mQ;=SUjbfs}EYv!t%x-RW(kGZ0Ow=n431PyN6V5dP= zt8c9PTZ_`FA}=MSx3#zow+aF%W9QB#Me;!l9$>%x4yb34PyVYsB15ve&cnsPm-3c} z8~bexPyE_%x`p1$^>sd2{;yq082_9+!B zk4`6B3*#zlBj3MFn|d&{Php*RK!thowXo5}F8II1wS7rT z8B0oDbN%StujcQJK;B>9D1|}PO7an#R6MsxQ)@!HNZhA|++-ITXY(I^#IGx!LBRp6bsUAd7ntOv zd1`W2y_t38<8J_PGJVNom747xJ!ebGlutn8OJ@|=LyzprPuAZF35TrWHTcSuDCSTK zlOTKYq`z%lTOT53h26!*+)CRaJNmC*>pz@Pos&;pPz^K)bA1}Qm5J;kLDpMr_;A35 zrUG?*ioyb`jh=oo1=^vKOHE7-oIz2)*}KBIFMf<$x7u~HMrjL zw-tc8nO36XlvbvNfzSYU6E&6@hwIKK@Gu2yve!r#gpA0dq(4tyPHrmwg&RIfn3tCV z?+?%EP*Wp^b{8|u<>|CYN5w^7 z%rlm$0h6l^;1f+vgG*aFXie;+7U*q3^E=4-73ouI#$-e&87Oo!q1+89L`f_GII=ul zz?H44q3{GbM++^rtFv>F=@&0J7rV2p`T{cz%+$`vbpPZg@-4v+{cpMnU{AnsOg87X z6i-?M5to)$vLBQO-@~c1GjQ*JWhSl{)hLT-ae!yTN&c&CG1Ur=_={KIr&y|M9>h&) zn+)#Jw2UZXTL`n_?`Nr|Iu?7!We#0}Yve{Ju#=nY%QV0>x%$vSz2*%B zZs6!F-6Hq`{EjN#UXVg;&ZYQ2;wK4M)ocj?jM)f~pEa=U1ojN9SznjfEYi}l4CO=! zog;v3zgv%0eRi-uqj2S)z>DuYm6M80Hom}I@Htp9*j}#N_WIYg4W0G1!o5C_wA3&9fIAa&LYjBmk$%K&7RgGf0Efe|9e= zOU|9e0Wb6K4vFfKQ3<}t`lQx|Jwd=x8C(})oMt;rn4m&2UHbl8z;A?>iBZzp4IB;U znKrp1OWSi(lao!zq>uOEY_Ja$dr1N!imJ%&7Q-~?P@(i&-`@N|UST;{X%hNY8!ccD z#4>;HPzX))-Lsp6d@dVnS>f^CNNVV$t-;qEUTA=~f1#HJR$8zP64)j#x7zOkLsH-b zeZV#!d7rH4yZVa6?N4m`p6~QD+t#nb>o$Z#t8nAabe5X`$9vMfT1b1W@px^2>f&Qh zL16}kWdHWS-}?4IP=GM&ejI^TE)aLnG56XxzB6V9X!!!SOZ2MPd#*_aqwh_8@6568 z-4E4gn1)9OT&S4X@ly}+weWYaEk*vdEzxh1PX8$oG#Lb1wCA4rm1uETMHtF736+c;Q4YO>%{HF`s1fiuz$cg9t1EG^ z<0F8(_aQE~oauwxfqlEj!lNJQAT5FY9xTkVWW>7C6MvLePzjkM9VB27&*M zescsTI0Ka+qwh}fD5WUULF9M1Lq|jG-yO_&*JU8r)`Y-$llEVO?L|R8AgAPkkMtCb z#yR0be)!{b25s~!yRQFDadZX5-PuJ)$D-@lbVa)M;rlU1>>B0sci9w*qm?7Ro)`P+ z%fJvb@T}=t|4^*DG&X&7)3q3jeENV((a}V=6|LA+`Yaa2J`b6*lXe_;3fUih5t!5A z<&8}Eu;JdlKQh+=b9uYsUAqOwUAq%)6jev6K8ReCJvOgSG(S^E0x=yP`pHkbL^c`e zZTXv07?FSd%rF4f(}MCpeo2xgAOek!^tR;hpP1kfWg>bkQI>#^-#={R7jo&u2%ahv zUAPecLOofK$H>Si{w6-POt>}|mph~Im3EZpr5D%e;J<@9{f-2fh`0!;s4DiKM@E{D z24JcN4<=*Ogh&5S#(C@5Q!A@eN8{?U8tql^Du6G16S z$!r5K%|ZXQaz#QSluh@e-TwARkz;BbCZ)YX+@QetsRfOuy2;SRK30w_7-+N4u4z&d zRq4^pbC`TO-VIO-_RJNjnkt5=%~Uxo$;Ckx8QLPDq+IuNCw zoe0Af=doo!y*_Vp9^VVO-WM*ME^DZA1W^QagTLcd)qJ9_?cpL#7h0z$Sgx#OAm{`^dJ$bCqu4bA}N)dGl~N@v}xgI_=l0TSTXC z4YDRbx1s9&3>a>JT2D=2hdzpUH8sT$VtW41N8LiSy___j>Q!D@IXu;9NGp7gC#tnp zr6-u&Tq%3AKt9cGZR(lAd&NtRs&pJh`j(b_+;>Gqh3=9ch^mK74%_g;*y=R=Zs4x1 z@XByOu0OfE@%8R=mk$*cFdQA9s{caCop>JuGr@|dVH2WuK}lk9cZt0JSZ&bOlZ}=b zkETl`g*4*NZ2L117zozB=6k?&UHQwxvJUE&d;wL z|NLbIZs;BI=`Fk)IDUWZ{T7l$;p(u!v&NU--v8bt?0M|&w6%B_+7yyU%@@PXhTo-S zCghoqkHs3JGAos2vPO6KVBM7rdd#NH|L$J=lxbIftljy>FQpx?RfsPQYDEVCnZ3%g^aN+~HhUos!?TWUq8EQ9v5V1wT^=_=l7#HzY=B0x^^wMyK-iOnjL;*ObFxb2KI|EgWi>ng!9$rbNvOk zmBy+Kr8&3TQt$Px?yQ}wHv85_EvEX%()^bY^8YE${6GE@vl8Fq%LUCZ6$;3<-U#Gr z*Lo*QF*Z*XFiZ=chS_t3QIV0k15z0AVXM9pL?S*sA=sfQwNLFrS9w}I3+CM6h}1uO z55qcRUPvbk-$!BdI9q`EM-aS+o*CBtmh200_L5-f)_h|_uE@m((|bd&&2hd6Hu3fn zi!Co(cXbhX9u)HiUm30O^omu}ph_AXnmtRfeZ0}#-I0fTlZ1WIa;@F$=AU5g5!#;0r&!mSWXEpiN;*;PW;}j|CooyBQoV*RxDJDG#PF3hZ2NS}Nyxx5&`9cV?Gq77g7$9xkDe^%j-CVX6FMB+m4< zMt1G>*QWl)Lfp8|-odUq)#&YrA|bhyY&b||rS0Qs;)d8)qBnmPHaH;8=@T#J zIQ*2B;(oY&?O0!2iIi0}N9omNc4;m7vPQ*S$iDxOAvA-U1`jsn z0o)So0RU)1w6!7#Ip6gbMgh`b=Jh0~?lW&+ZLxQYEDO5ov|2mqL z2cm0vW1;i4KNeCd1KRkhjl-f&G^Zca+vA5AmBhOrA6!}vn+YF%COCRzXSS3X{+uh@ zZ&~Q$xZzd=LA#4*kuyJXO^cnW7P4?z6w;Z8p)TiA1Dee4h2HIL2SQq=wFa0JLBpB; zW2U{bs9ftq6kN8NZ*!`RS_cH3k6tML=zsRuIpaWoV;)<;v8&PK_{b_UEQH$I4mNE9 zZ(-x(wJDyzS9JFqiY-nF-Xe|05Vs=Y132Kjh1sB|4601R^{KCa$fD|&C-$uO%mL~4 z`S9pyQkB=yrB0qW8vgyvam?)`iG0szIX^1AnsL9}BzL^lbjf4u&FHb=SY0E6bP|uNt?oFbs83Z$go!1{I=-ADT1?#8-|48sFOJlJIQIc0QSDTZTRu z-B}6W1IP$=ea|N#*4J`d2)w#-HOtorOR1O|SmxWWf1?9ot-)TQHGEB{R0 zhUoXLL_+<`lVxHLN$y1(Gi0ym$Zv^@)Pz@Vhg~?BT#i4tKQ~Fd@P>8o+sktS)$8^5 zF#29^$pS@*8v5+|EG-ZouD9x7k(@tIagMX4Zt^TBf>-?|#bi5QCd=Pud;1NhQ5OB! z=q6|Q`Sa(wix+XorsM{_Sk;Tr15yw^LtwkEnHwd*NF>gJ?fUtFK;^;rW~^|kUmpc~ zQ0uV2%8;nunr^*RM497gWd218V}^TqTrMbxQsblB0+_fs6RGQGZ|b%M2gak$p?OGd zEs|2O*UJo)7++=u-(0P2iolY%gRihVY{o{qpMdXHrHyVh{DD$`L~?TPE4hd7ui8{^ zUB>gt`!ku;VSOuE2Z0MsvDr09*WcK^GJk2@Si;kdA(UDOhpAc_;j-O+eNCDaUFiGN zR6s}h__booLB0>TsE}Ra;Y9P=&`PC3qyg~%%>Jw0#^AT9sk1g!Ya-K(b@g?Jn_pCy z_Kx;D<#jDddt6ug&fHwP_)Z=J<%+Bu>iTVh+vEiLpGmNr(sa^`O6cXTdA&fKMknUE zGag=^^7-oY@_oNk+Gv063A*!W{X@N?bLex?4hv>5|L%>V5+)&5&*fL5u5h%OAwk1 zUYV~BulRn$X^VN+=g}-AhssCqF49Aq`SGz~3fFO+57X{z`diCmLJ=BQaO^gJjr+5E zJnKW-`N%?zxR^-N=t8cByQU+OSn=XyHA(Mm{HJr7EhhHK0%ZyP=2?UT|Xp< zvUMIO%=`Isp^*THQ`%b8Hsi7+WZ%!osT3^IpMHGEiZRu|bMW)?D|b-z39$IRms6D< zKR(xV1E&z}L55yB8)_YXPAqf2Ny~E?y%*QKPJ^XM?m2+mG67%|4< zC$8&MNhNS)**wF|f`O|c^@%Um zS;~|F>)4(0O7`W~c9=OhIH(T*`~;tISmu5+xwhz?M|Av+vh=Wy!YAtpnNun}$86+t zY^?FN^gsPb5g3n_)a{_u2qv=^_HfJMc+wbz^YELj#OzAVN>^+*kC4!%%O*jPs62|v zbRGMZ6{PIHbI4PN-(;jygT$&koGMr_#v~CBUm$)b-JsW)` z9|gmDT=w>jS`Fj&3W+=ZEKd}b)Y8`Gy{kO_KJXHBaVYSVw$37-63*`sNCrLi9~7m` zHxNdlRQoWKcCs(;%8TnM=c2d2hu?W?H7wtI$ob`C_4Rgi`E0l>ddOU>#^gD}vSgZL zt|}dL#BW7~g$oL`=Rdfq5Oui5n6KaYvh{vKzuWc_9~Xq_v))Rxse@)!V++3VzTa>Q z6gU*fy!0^Pu=n#L4?DqMhh1{yV-lR@QB;hj#3UN^+8B|e0q|lkwooC2YwO%OAGjY^ z1J~hT(eQJdm@_u=iHW;Lv#RyBw$i46$B+@>#V2jV$fJ%*i>?;KG85$IrSk%rMx$f? z>s=|S*Qd|tVE=UikVA^qgO}&|LpA-X*Y^FZO=E-+xsk4KLu**_$e}CX}*s2)+dR^{moDUa%zbd-73IZ8nA^Q&wrr=#Z-1^aQS#H_N;Sz`- zwceU-KD3ye?Yz+xPN@2Ba4J^T9$vgB;>xtiA1|%SGnL{QCgc*GC_!qsy@dHLanD{f z*IPY--D5!+>;IAUI6MAle^3+27eac}+S)F!_iH)4!tqzb zSlf$nosVvU4mZsv+?NK9{qyfj#qmCw70vbrX_$~{m;Bvd`89<$_DnB%3!y(S$0ySm zWK&Fjb#J$C?|XQ)b_KW9muv)#Wm34p_1RA`OY7U4B$r>yDAn3<5la|?x3c?0ErWi- z3;%i2r?_I2hwIzhJDXn!ofAHnP3U>P#lrGfZ#BC6Dy+i(;qr>E>C(V5>_PQ|;a02v z%ZiXSzr6W;f7>eb(=)uspFgJoh6FM-`)|J4)co{SrhsIM=Xq4j=JKd?Z*^#< zcBSM2Q5vqx4hJYp0Q1Gf+6UX)C&TYF*dKg_R0dTA1Y2XtLYnWawU40}?c@|4WyB)& z0dHoje|5f0!#O|)#SY~bn|AiS$KXn>{tW^ht7iY%K##*ACZ>+(c7=XMmvC(V_?)&R zSGqE{)Nj1*OCPg0EyGjqAvT{@uTnvO`1|9Jf6O_@SRq~E90etXcwSL!M9mRD;NNwd zn)p>H|jW19Gck=A>nU(nksu^oFQr*!59f!q4@JfVms z=Mg1}n6=NzLqOxd0@i;}dBal5%4i<$tVO~ga`9;=S65LcsgfR47o-?h7Rae%Pxyc<}jX%FSv7^R`zh0LfEiZ^}b9Tq@9sb>j0=s z%&7EBnnIT2<8wI48|P^8RsLV^1fV*u8+DND=1WdNZ%7=W zao~D#64g5+x}(+3@Yc>|-GZh?HZ>Jhm)~}QW?;)S@jF{R?zN1rlyKvCrB~a=x03j8 z7Vk(D3I7$=(f_EYC;nAWGwo#GpWI;(6qLUI^6SH&L%G_OJPq05a*fU5;c<_*J6_W< zCzg-7l){C#yWtO0R2{dM>YO)bVUES|;ku0AHZscNb|z>sOrJT8)AVo&x~)`Gf=&wX zTEz!L7Qy9L$`RGK^=ZU~OLb6`5bZIcn#BfUM$<$&be1JIZ9zV?G=PC8S<+Eq&ss{Y zh$uw+9mQ{XE$2yY2VU4QACh*6Bs?gxnM`xWF?D1(93Is*T?wxpgAzw$5*l_D@ApVkF;yQtjKRWb z&F!8Tvh>DdTUcD=f(?@b4kF#%{0^3iaMIRiWV&D8j5{pe{HE)_K3%*!e!Nb@|2CQw z4vFU!Gjg(;&EFjhaT?Yj#Rs*LPN<+PD+YSw!);- zXz~O0Ai>G4Rfk<0L}nwt?CTO(&+q4!U4;q-*wnG_Sk;FbJ%sD@!QKyoY;P!s9v&S` zcA)5SE@#EE!pBi2JFCe2qt6w}@^4rIRR08eys(Dcez>(Ye1?8U<=vnwTxE=M`jXJ5!-D z)!*>-DBhV**V>CewPxK*#bipmcyN0Mjuwv&NI=9o{|P`$dXB zhh9WXoHHNPMKlJHqRx0F6n)Td;J(}ZI0Sdx{agF!=-I%40K^he5k&&$oui$#I@4}z zy&^wUoN(&H|vL$6BfzsnZN6%7{vl(TxjcB!>8n7Bqh4%)s`qHS?zj5_LI&>uZ-HqbOP_R&VTw^Y)CAb-QkD7&~o(Qs!kP$C&MyCOmWJ4zkU=7 z6y18*uV=|)KE+s_$wRT(4Iv+fK^o0#`7S*>3BUkiEMCI>L9rgcj>{B@3jj2&t${)I zYNeHQ8}4+Wwg9QQ857)Evt5U00y8r&`Cyja0oJ~T7RCizmYtXB#8-stF6Zfg&7ouT zciZZF)j{Yr5@qLs%~R=Mb@^nCFj!Y{|6U#s1)(3^1o)vTp{#DZ%PQlyXec|avGN7Z z)oj^`^(^YMr+e?z2!kEir}A2zgDamPg#Y;F@1;935|qk>he}0Gu0PMI%cF)SDeeMe z;s@|?aH8$xO6Y;Emi0NK62-Ev8#4A;ECyu%VYc%jXH{)CiF>(?fvDr@-)HS^ruX8v!XTuYwxqHkIGC}r{d5)8h7%pWUs26y$oxbV~D zJUxuRt`VF~P4Xe;67B9j@nsQ@r@?Nk{u$ziSKJe$*RJ$bH~(_Yr|s3(SRv$*Gkvy; z9xN!Y2#5`%q+PX}Gx@f6qi6u!m43HdpEqaQEf_EtS!+|o^0sldW-vbGycH=SNr0$u z+wJYSMGbR!_NRjT#Qhy0#IY6XAMEHwQ{UqHUO)pg)too*GvSKT;N<4h6&^l5yngZ6 z$Nx~oXj+Tx*dm|sLB@pOv55X%NlBB}`V;CdOE1lNR422H+E^neS6NM_h zMy>EjSy~(>B}1;q=90hhe$?)#R7ZkmJ!ng6)RL>$3^S&REM~fV(!>WYX0XM5+=SYa zr6qzeb&f?H#gf|rPqh*%QJnv5+>{mmt8pVp83K8(+d1gZ?2Gh#bXOSY05IqUYb8t- z(93YmQR~G(h`lT(Oh8N(Zk7BU?&=|tapYVFwXQ8wB zE(Vp5(}pFkt`cR+L^B6*C#-z5GZ*NE$YfAD5Q37Y!g{^hjo}Tnn({Hl=Sp_e4Bb!q zX6LX?ME|<2ypoYFR#BnQm)R9JCcpOS?sXbJ$k}6zSg;o^-*;0l202rUN(B8YZ<^qJ z0fCGW80LoED}S5M7i0d;AsnD}lua!R)~CO#VgmiWWegRO&5ix{4_D&qE-oiuDE6ck zj$E!t_bj;JHNbiu-(d$Xn90f&+@YkjUBts}_5I_O;VP|(olSGx;QED$RY~A_ipud+ zm@alDYJ^vlvVMGaKhayr8-`tC7Q48_TmXDc6ZZl+IsH`wM@oKj`r)*H9T|(0>nYoN zu`dr5QeOiX6HsjTwpX$rppR@e)bAC0vWV=N#ck@6e$pj|dnX^h`C}GvzZdsE!^Wr7 z8ubRSm|Cj|L`~^`zx(Hlj|(E_M<4@CicZ)W&V7)TxMj(9S3~yrFe$kmcUDx z^K;a(+N6V`mO=TWQzRM5*Mm^rBY!t0ivPpdd&g7#zyIT9WQJ^&z4t1~%ApWK_TC~X zqq0ZYdu2vOWMq%5j2xSc$Vz5}kdZxq*HN$a{(S%V{oC!PbI$Ym7}s@Q*SAB!bZ+lB ze9(P2VG=x7w`0v0%Rr@x_z*;r8pE4P??6{$haHkdx5(n6Tan-OnL^^OzifBP^~ZE( z{T5xVw`(NJja3(zXPJgPR%eU;X6JmDxKxxU;r*TF%#b9=$!-InnbU ze|U6gJ>3&-T4k}bFx`7EY?fo;!}D8*I4~PeU{;;-E&}?9ucOd)uguJhWCjr?6$9z| zY>;mAEYL4HLjb9WWDxSHXoVFwJBfNKNFk@D2LSD>0!5yeGi(@#x{U_QzcYZ#H z;o3)~j@Konk(JiZWOxm~`U|mjO;-P^7Go6`pWB&qO4`7slb&ZVr}$Tk40U^NzLxRj zssl)U>kCB>6DG@|bvSS|RsY<+yDL}WAS@*G?P&D{>rPyJi7Tz-|Df={!IL!l)TG7< z)7g2g2Opj}g1rXR7u*wXlYRdKh0i;5?(Z*A)~`AJ_*{S3y_7}E?7OIO0b2^%9EZKg zVPU0I!{N6YbpR;@Q}F7;O}HKGc;^qY_6PTWeBA<(r~keJE6B1peC%-NDQ(te=9^h> z8HjwL37OrXSMC%3Pgf@#67zJneZzI@ZB;cHl~@(}02x2O8o(dI!nJqnT>T*N&?mXf z@)`!_)zv}H4}*hmpqW5n*`k^{syfrvkCSxEbHd!ouT;R!hnvpmoizie`|esljrd{I z2YM6{s=1zF_XB!80@{f;b|$R0wh^}VI=n?czIPvypVVDY$A!M%h28fn{vY5Mt?@0~ zFG7B$9Qa{m-ywyl((3L!5SWuSu_HB4k8*ONZX8o$X*~Y%`HQHN1R)O2=C3^Fy3p(^ zuuoUUg3!;E`w&TG6=#-89ovkJzsFL+!EJ8s$uVl+cyNY5zu1_G_}4sPe8bHIT0gb< z?j*}E<;PITK6i(UJf)UHZ6=E7^pOK0^gsB;8Yg>~myA@KPU<(c>IYqMiOb{OAK*w; zPBnA_3Id)*u?tMmwMyX7=)5h$9?hG|9pb+^pse@s;V%gn2X$>#9r|IxL;i{Y!WTfs z2fRfnm6-bZ(tn%dXm4qWvS4B5%~S6%c+EP4Jqozi|LdVB>4+*Hs=CbHBW+^scXexO zlHT8b$ldF*&hW4^re1}vC4}M;B+=v&$X&3tB{V#D@jKE_*yOf_pFElG6DZzct3s$o z&fN@a!R=Rqca zohyG5Xmn%7Ie@hRhVP0$(F&g80$-)n_svCm8#GyXQR!me-@P(82FNa?84BG=_cFU` z2WFQvKR}~9rKu^k5F2l?F@6Cu+E*1X#e)F)=#J83?PO9-clXJ*$y~o{$m@_ZiF|eP2rjYO#auTkG9gZ|Ph#exr{$Uli!$ zKm0I2`@QeehC^VJmpw&;x&ZKAknGzm^o5Vq+MChpv)$e)!r4U&8X2+MR_UH@QaIS$ zJ9&e-v1og|L&(+(EY9CRn9qjF^`3r!clC3?lxVWr5;8XR`gZ9J&zSc@4{_t&%sNj& zjSuhFpw=JRz!|zXTP9%$Jp)1V4KLw?5Nr=Fo&Ld@$#4zmjFO*r$}1~Z0}&{O^nKGl4r-p7 zxPzy=0yW`t5tx;ISp8FeP=K2VvfsbGI#Iwho) z)e9j@@2u{M0z1yO4E-lyIX2@p#}GiZw#LTX!KRGD&1gmjADqH_3uq47HBe?phi?2Y zZYDjmI6$fy9k~KKcK(b-2djB00lwX?IH;;TH)eBMytpyCrRr{`Tl4zqqjh}w*PHP; zc#Tp_Egq9n31*1~1|9uchyERxj3Xf>1(}+LIahMx7OFBaR8V&AymiFK7p!KKbGJo) z*nH0U0^4Efb1sIMb0o%VohrMSOval|JNSjyogR@0;{kG}LPI$qcZ#S+-oVJ0b>T`? zGX#lGr^3)yn=%UX62@X%g1dsUdQ@W!7*i0Y?gMp2ev(U6jt>XJThzh8^uP({&(UDW zD`^ec*w9Ts`t;gS_sb8!UN%?8E{1+zSve~cX}*NL#kPt9$Of=7YV|6K^E9_WQDf4Z z!ae%2H1pt6mRTE%+_P#lbiw2C>#kR74C^@R+$y2DIWGsnQsJP4@@@W@h#vc1cy3+r z$8W51fPEEoP@4>NX%jhj5z9B2q$;FQc=?~c`fY$%HAeKi_ZWY}19b~*BOf~zCeL$U zkNgJfYCBrirDq_U9cfTxQ?^DVC{>>z0r{+Y=T)Pnr`za&F3QPrRU!G$-vIlb_gtgquP@=7e6FR!wcuYxIzoD))7auK&gpN0{&xkB zkWPtA`cr4#q|+ult&ya_Ev6#M`+yb2!~8$keLdgO(v5TJlU|cyLf5ROxOE(}HINXM{tk0;UJF>1R2Z> z1ppkcqoZeCr(nf%kzgTL=PiA4OW$>ig3J&u?~>%^WyqaN~J- z3S$-L=S&xmk20Y^0;yOl6=;rV9+s7Lc`c7Lz$GZ+Y{xGl`qbKcpA%?|-8F&F1Em%Q zIl}5auLoWq|4)6k=d^Ey0tT@Uz6wfQsROv*x>WImGJU_Tt_FN7$5O>`zyY^n1l9bD;!P5gq zjJpADebx2JHODx>QjKb>!ct>$>DXw2?B9A&2I!X>0(q`@AdHsQ{lIYsczilv?YuO- zU@}e&gkOg9kqXP+#^}rkKRj886C{Xp0h;IYGie|hr&{X{ zTt)@V9i=CEC{qNOS8r-WfzH5-y17W7+%$korHWfxZo&Lf461Ll=Af~pHLNbZG!yo8 z8U*dPf`wN`__2cVN&}#O)54dGI7eU;Fp(aiFMFZ%!vFL69LjfYq(=4G56$nY|NK&F zaSuv`vMc)A1KGoW>o5(@SZ4zeiZqQpkJ4oHfb4U0Vqu|AnYXY;jGRgC85{E%Rw+(9^24Kgal>t=N0!RT=^9&H0HGiQ5^){u zy7Yz)z#T3xZ)6nfW3H3kaUg4c{|iduQnU;iOh5l^<3!kFe3{h$c%t^nG( zm#-AXpwt&;*5)Yd$HjW}DVZ9=zmRg@n}g{Ys@iV9tNn37UX z<#R=1jWwqSXvPAzxw)o=uHMW0W}lfImMEGOe)OM=z6bnme=Dza6E3-#Z;WQ9D3#dJ z_E=c^=(`6$MOS0U$Y03Hf(AI+M>*vT5Op;vF@Wh{b8(&v^Q}*l-Dpww zwF!W+O;^83A2&p%d5zrVC5fy3PKix^GLaimbm{ccdx^(Dl#l!Ww=~atG!@>I&1+O& zUYwwUiAa>pGgj;G@Q1#Nf81fAPnCup5uKX`ZBz)UJ(8VHsS1|$vjV&?6%WY;vXu#^ zBjP&j_cukXSgYu)q@A6yiG@Wmk}}Mm!*zf6Ll4ght=IBZ15A`0{B3k}oPKrbd#ExC zy(4{a=Ya9!#znHIA#%Dw;{AADNZczWc&M}uvtjREU0GQZ(6kFS#>Uc+)TV`BCuzhb z5uQ&2+xVAypF-J(H?75(_l>nps?LJs&xC(TO;xj4*04K7rzq5;cdf>3ecoT<`+r&S z;tQP)IEDqjhKX=++l|tj9Ud)xs18tCThG;g_ckD2YZO5KNTTK2f_0{lTDEvEOa=d% z8+6g%+O$d)A-@A^vt24s?xbPW0D!#cj{Q9Y`_i+4y1jcQ!X%)Ilv0N@p00MnGb_33 z9pX@yx2FhL1efKEp3x2e7b>HTLjvPCy8x=B!>J_1OV|xv6IDIN(o#7l%Th0Xl0Db zOGa`J3*+-8{?~a-YS{Oh^C?>EEuE=Lb|34}KK?JaEW8whNr6~pCs?>VcVHdU;``xM zQg@v>rtA4B4!`SES!con-O+-lR~rbECj6lYy8(BZg6*ilz;LCALhq}CMz9(S&AsI) zYJ&5Qt5v$fh+pa+R0i!axHGLRe%dO#a08R_EPsA|YX#y)zXhCs)$1K7_nK}sF_^JP z?C|)ANpGxnqcPBZyAoRq8*)ZxdP6wO+VC!YFq_O!yl1waR}w)^%d1PN^QAmLhpxj- z_Sr$^OIu}+oevL>=x%|vodF7|2h$Nr`L&sYHh@0iui62yVE63n_&D4pC5IqF(K+-c zDg_zjEzKcJ6SlbyGoRE=uy*BW7SzJviOgfrtxUP!0HA5C&Gr0PBIw;vn-r{bH@Dfr7*# zlOp>Gze~ifx46;NFQe{T`6UOne>O_NBIIcuaeU0Fni;4Tb}_}W=TI~tX>0CDhOCpQ zi@-UvqNhvy#zY~69B7SCpaFfC=8X+!ifhnJEXRWU!WGh{Y$fa?OI~;U`e0kYIli^l z_4cDU!ng|Ezn)dYkt5@icy}T6``e1Ss`S{Xm$xQQ#zYm^VoUAu@i(SnQHCo}F4c20 z0YY$5WnVk_v4mGjjd7!#lT)P)l@Pr69|QA~PChV|gNE#C|BO$tBp)@LTBsZ!lwzh< z6>~jWimcfK{|zqjIhSkV;k9dPK-B}M_M&JkC?tdp6rY!w-bfL(hEoWAASGi8{rAVu zli15>wx9hs!iIS`qw^i`z@@=F$ayhenc-rY&a3Vq_YY8dFj@+a82V97O+3l!bs;l+GbXh|H}7B+ zRRh+-Q=wGQW5h5cg}Ejsj!$h8jjW-waPgDH5!7MOrU8Xd;|1M!)~}gfvR-Hnzeb9T zYN?MGpb9a1=zMc7^d?FTs>?n|0r9ofow zEmJyd3MvAk_pY03w!?){=EmHwG7pp);OtR{Or9JF&TACdb3i5kat^OO|NepCcg02Z zmOOFegy!Xy_4N3i3+fnv9)t1oR1l|VL=mGy#uVgTYsnE_%O@j7bn#0DNN3k>uU)q{ zRo-UdpML)&25h%ipS9En0O`c#8N2;y=G!eikVVJgkUe>Qi&4Biyo=4)-0v$;WXn$O z0M+GC3vpD~BzBz0J<~KH%oY(LH@@DdZc}8(J>GCfWW8f;+JLTZ<9l}#gTV&7`t(JK zzRRsNU8I_BTh>xg0&K)#VI7n;T*1cBK=oOt{-z(y!NcOSeu#-JW47?x^`<+aPi$S6 zcNJUehjnSWF;Q5D?mcytfpZb$9$Z)svzVdzkyXzt$Zv0#ghKi9H#UeiIg1^NAUeW>R#iRADKTL8dR5UUb~`FJQBv zTE)M<&R4$K^DR-8ELQ0ezoh`>A9K=Vw$j{bJa_4({c)|;l?^|@dre4SH#D@Me-U}A zJ>A$~R%jh6GK!6@b$8Knch6i4TSmTn0s_WDodGpZN1NA7VDh-?u7WtMTSQtz%HzuN zGF?%HUgdYtj2G`#F%T*GLi5hab62Q70IOE3&J}aI@Y1#I^e6|E02bBB>Ey>rw&Q|w zPKRn^ZSi5dy2WlMmxT5e0gxRfsvwNi^Y-ix%MTuU)0X43vi7%s;xx1J`}(&9h7`Hd z;Jz1%le$_T;%6=5B|*Mu(j*e#w?*=n4xX9ZMRWgv0J`UQ*w_H7vhj}P&L%0GegP%Y zJ2?stbs|H&)eFsoAP%Yc>&uQ{ThtL>&-Dg)-F?d%t&5)QX0h<^uZMwLIu)*S3v#sQ z?XOS?7ViA?sB@w{v&dWfmOTVVs~r*dA9U=r$~1g>k?bn5E~a(cWCOvKP!-JEuirh% zmwY4t6M7G+ZAsUXoY82T>#rQnrvkIk5Cc%FDY=~`yG(HE}r)^Tdh+y}-%L8EzhM9o_;na_NQpV4CAm=&{_nLrFY3)U- z_W@i={~DZLOo_Pr;KZmfDf4`H1n=DSq$y6yduVLm@YxNbt59I(RIKSFF za|f0WNYr;@d7@52eZ$Kn+Oi$ue}DL0V*N$}*(_+!M%dv^;ZwJ0MDoSFDb{677r;3c ztAYjQ4~T6s=Yh}+0lopuf-}%kFGuL1A#TA{eJMNt6{}~in1f*OG|BzCx-6_Wq%zeo zU-bY5;H-WAtN}WjXr2wok}iPi(!Z2clhY=)#mfd`3lOp>D&AY2*ugQCxX*llT6Gz@ zct8EG{~}B+POpK|P&NLz*Koi`6*ohlNB2t2t&lJIBduWrcTlOBdphY-n4*q0NcG>} z-XxFf*o-lU0uB(xT)G8X$Io59|MU!~%+6ELMTRZp4#riS@#m(y>PlFNG%>1_a~nyv zL!zRhDDfDm!9bYS6o+rYo^hct8F{>-O=&EqvRR{x~&V!a4_nVU-V7120UxA6kJw>#=8f*>R(GOveu=ulvWNv zqUQTvahZiaS^4sgN(=D^1TI_1rNd77 z@{V(z(!NtA&i^f0YdI6qM<3T9hW9Cfg3_3C-APy((QOWj%F64TT)%2Gi129r9#e}| zRXMLC0kpZQp3=a3w<=y;rRTqdn-Pfx&gs*Z@OZf~g;3S(VgCKQa}?3&%TPU;Jf{6O zQynPpTJv)em-&pY=NW;TMixthMV6w=}?)=uTcN==!Zk{w zZ92}og_eZm+l<88`!#k9J$B~wPKIaP5V{%yoKKQXlJww(1=`!2@B=LUAL8nfAQ$OU zR5ENeRe;XIUshxf$O-segj#RY1TBZ=yDSf8ZoTAlyy3;5RHZd?$D{*}!3+&h<@ipV zCBF4zxE0j-77@6n+gro@V$1o&8+GnyY0o{@)@}$Un?&*$@2>IqlW$vGK$hY0yFRG| zbUJj$PYbQ)K7dXmd?9ycrj$8I;CTAir3oL+nLeO`pDIGXnOb-HYap^}-s1A*i7GpK zB^^OEgk0^3CtglG3_9HWL3W1LpPk&~vzrUoaZ&w#Oo7x*bWpq$e+253kBmu7Ki4}= zu``C9XVIP2V%f9M+ZXlFV_lmAnHqStaqS*J%y+$-f~1Q}4dZ7MGH zTJ_HenP%p-@T3huw*hPt7LPM^gTnM^tgzD~wN#0MxjDZ`tx}Nr0xg|?{5!(@S;5D>6t7}?28vo+bktG(FvF9hK|aC8us6Y9zv(SX!Y0T|x437l1b z-bG~O2N0`AKjM!NaJ;dj`1>dL3i_*MXJ;>ui_&(7gcH2^`};GKHHY27MMxEwaO+=a z-`T))zj0Daoy=f#&*^C2kVfxzwJG7C>7leR*mOaaA1P~bHx48GvW_8KYu73nz{hun zovl{_a8HdqmQo}LQC2=R(c-l84W0Ss5mki1Fp6Qj8?#QTrx^6oMOdK^*Ghqy+kG}W z^5)W29AM`DPuA8_OyqFw;3|mPArzPKa^}Z?(ybWbrou~J0nV4E?=#B&9?QYRcc2TT7#~j(!lB$Bo zG4o;ln@=M)P}pYDTH3_16x=^Tqy8zYIeKX>iTbqZHa^EAH~%;fNNDdpXVg+g9uwT} zZw|N>Z4$z6Z`7@xTKiDjY_guAp5*neI?Vg{&ex)wguFN&RUyrd~O9 z4&|zKfS6F=S;31aQu5PqWR;e z5=oF|E{_VPk_nN%pPXz^s&}sdHGb^raqd{kap z`QnB_FgS^97e913OG5hDeYDgbgqWrbOw1OT5$>k7 zysjKpn+uOX)gPV8bLw^91$Yk~P2hXDFCOh4yYK&5+g}0>fh`1>M=5E@3+^It3gh7X z;+kNR5|ToRQQ*6lzWPp^LMrjA@1vK!GmB6ZJ1?UaL8p%K8v>V8^Nr}9UI)}`@-b}t z3wKNHT4>%rbttt|&N$v4Qvz7TU!F%tAnwMBe~s8M96kDmE4E4+F6<`WLB=S6@H);zfL2Des0nnCSb#?RNEF51y;$CgrLzp`|6371=h0KOa}7Ib9?p9$v=-GY+fP z(6eA1(+P*5H}qQ<-)fF>pwYXbxV3*uX$BFgfk9e~d|aIrQmXoE_&7HA<^qruYy8Dp z=N1vREi@ENok-+6k3QB7$pd5=2)cl$q3oTkvUjyB_R6X$zOPml6hLXTYh_i(@;s6q zcHy2!v;AnSf3%fyDCOV|^f$M6<{o?ouUjec@=6W%MTmHGYqxQ^d5Xj8#q z-5PM{ML#Z@&^j^y{6Eb`9ORx!(rI4?c{TcFyx;4A6{r5YF@e+O-9F6&I1H=sN|>7D3eSx}q0#<`4h1Y)`%s|jfI z^=qA{Ux^B8TEL}uOxrlWJnHjc&{b9&CpYc#f4%IMuS%z+DRCy)WQWkNrbs{+s^NcHkl5Rb`jo`P zpokS9t&b``81YSe`J0a2quL^XflvM@{eRdR^c}jY1-dSALwJ*fWa@?b9l%uqWhVql z0!HR+_+N`Y#sKVraRLxeq&ES9t$LB+G}y2y7vIU8I+D7AabG_Tz>q3LRSCyc^ry;h z2F@k#Sqbq>G&O?%SB?zQYD*ClVQV+uUu2X790X8{{zwY{@djsmz2B{eumK#TPypOM z$FRr=Q^4kb{9pj*aoN4|{x)X32D2~vU8fJyy;U3_HULFuB^M6{AqQ{-_sB>LU!bVq zW0czuMFkUGTzu#F`XB=9Z*WB(-}8Xd1~3YKGL-PD&>#uaI0tZZ{Lqo z04{L5&|R9O$n=fcxe!J(zB1bpdPWUU^KQpWF7i_uuJ>s%_SOBxwCJOjo^`o+JJ{q({=yQ#d@*7#jbGJiQiAfkomVHEtW9@p*Y6Ky($GyrQ@9{q!RdS85LmnX_A^UMJp=qeLf{pi6Z6 zrfIKouw5y~>H>cz^mfRmSPpE}0+jM-Ca4Mq5=#HjuPHZhL8N)_HaVQxe>yFdy!HgC z=-J{sj4_@n@P>Ckup4sc5~nU~>x!OUm~(}!GgY`VAZNRJ-GxfQa#c?)mQVczgq8c7 z_roy6c7d2=Vdjo{Qj2qS=4VQykuih*H7m-!yKL?&Us66+m<(jC0g1MeJe=+gnHDIY zN2IM%eZWoU*xxRpztCjETyN*wZ*b)m^t!1xp-SL)SzEX(uqor}+Bs48%U&-uoPbOw zZ=M6CfvCbHr0jb%Tv)A-i6cFYCtc9o>i=tZ7d#gHzZ*L#DKsDNmkPLK7?RZKqn&tY zWa?mWkAv)9=gXMcQqCeKkPeG{KujXo(v`Oi<>5_&!dB5$b6*oaQezp$(_e0J`}BMO zC?8a|X|QK@KY=gOgoL91wun-${@%mT>AM-;p?PUw)L(DJdPR53`tzE(J$)?epxzj( z{(1JGI9A*xEHtzqC9IF88^=cHZa6MaJ`Lcyhj*&^SUUGe+})YV7T?-TF+O)ID(xFY z6A28NJ-8f}Lq{_F?T~;_TM&fNL+i8uSaUR!HP)!)Lqa%)kqB!LcS+ByZ9M= z*SbAH@t>81OET|WD9fYrHVx2x3O3_57Jd;YPr^!8^Fkd#s!C%vT=SX2^Uzaj!f1P_ zR6!3B%WHJ8@)q>K>1%$jXTF?^Wo72BcCc^)y*8@TwB*3<#|*-wm?7u6?AMw>12(Q2 zs1_X|hG+sLFeVi5*_ZrQEtkCM?)81nRXZq^oAlSs`v^dd^Bsv}XN<>ZRIayt>= z4H2C37Kv(zZ`<7MH|i_~-_%7x$Kl=Iuj#{xMDBy+QqY5*S{ui=)U54tRgc{y#AaO~ z3>WnmIduMR*QIRj{xFrvjX=9f?5_5WXW?s9p`d}8?XnDc*(eJxS|6CBZz;elaUfh+fCn$T*CuZGL0M+Q9*nTy9xB9ao`0wKDJtcu67U#OLsfW4sP!vekG zh~SI4ANh|qaNmC{BCbQ*IL)#6vqf#)?<>rsPmWgF&W|8f~*gT(g+N|L}EYw(f1!1~nkbuGO zbKGb^`4eO84MjaI$HG4iAcr6Kw+kss3G59moJBYo2@%S-oF4%tz{qeeJt{IV)0<2D zX1jn1AoCB0A{NQ6Irfe!zgDB5qh}wYMvk>&oA})^k_(6qyQpC%OFvMBi=;GL1i5VK z4USpXtMwJi(bbE{xgg{|R3^{lUR=XT7I1f_xQr%CYZ+tS>)LUNQ47IR7-5c0u#HlY zPhNTLt*Af1ZcA3|xbm5R`eNCYg+=JlJEsE#Pt|yH-OIumfpu}w|NfatLNxm*UK0ZDoco8G-d06YCM(b;8 z8j&kkPS!Hl5(DlXhcpS61Sz^uIgi;qOpZzPdjh#V-#Ia_JxYFL`UImIcZQX$aD}AM zpOiDEGNShzw83(3LTJUh% zZm&*~o2vf)B@5wT5$t%u50okzF$slKdwMjKW~ELgXCW{%I3hy*dx9q%C@f?#f^c=` zjWaV4aY5w9Elq#1@_?2n+5YF_$7gOhU(_*|64bzqO&NY;`?dY<`_?5sg4EM~`|FsH z2mSc9$^3wifXERX+ruURYJU2Q#I&`XbQekN7CI;y%+)&V_U$3z8=H86!1sBE*;ye` zeC~C?Ywp0Ie2!02$78+4`gTRDJvcKU^+=`zh_-Sth<#}yCrGTyQk!@Sm04B$2IulO zHTy>Is7ViskUa3@a5?xx1_AkyGV0Y_-PGoLFHg?OzT^*F36TYadou#s{7(b|tf!-I zjP4n3w^)=SzTWWYIbM|85omd;G)XyD_y64Sr55rEjxP^K99Qh%;mbCoq zxgdY_Nbqt^oSW5pJDUQgg3GR#dtTo|KR$jMS#AIA2?@l@osIq(rB6X2OWqMyWba$? z+_kyoW9sA(pgQp(6hanvvJZ*rOTaw3N0xHUmU2Mw?p;QEI@hpzzWdo9`PVlt{t$RC z@BWl!`YDRX~yS0ulDjLb{fFbJfOc?<@ z^}4}GnK)LCvk#kwrtKu-*qX!z7fl)PuNn_z+0{Mn;LUP)nh|s7fymyQ7Y#2zsPu61 z7F{s^!Exau&`ZLCJW;cCj2}EyyDPKn-KMtf%Zm7(gZ~c<3AhY@Y#0I*>~774)m*AV z#325)z)aLl*`2win;|m@ZE`I7d8@t;2c5CWZZFsy_fZCtac1j7ooiWMuRTK$40?qX z6J8iaIFK$@_jvvnAlPX-z=Och-9Ir0IxY|1N?484k8<8o%VXk3yA*b}_zsIklW_Xue_%Rj;$H#5j4zyq%(^F zmhzadL@R+i2u;{h5eBOYzq%rgkNxjj=kL!*R7JS1I#%vl^lCtG72QJDOn0%se|jXl zdm52&MWv$(TJf7o5Zywrt_u33;<#v@9$7H7F^z|Wf>otc>zrXjeSAZ{IG8uGEvcYc zh2XI>@0tW)s^&lF>@yX_@tAG=?v#%b?6ds4O{hk#*c1>z2!XV7bhLte!ePRo7LI_+ zrqf%!DdT-*mR-|L??Hw$3vPt&YfDk15Ye^y28=_(L@9S5`Q`EV`{Lg6fI9FgW7b_c z67bK`9{u=sari}p$SO36<;CFR{?O4e(Uv_E$1SKsB_nJ@aSqfeSNBGSo4~{>(*gD5 zTq49%y!%v_FSay!+~^Y`E++pxDwxzB4fFXX{?>l1TAz&Z?5ov#AiMqylBRc$3~nq@ z(5vws?feO6_(Qa{vOoA*k7>isNF2=|;;n-D=1qZrI}YAbd?cUpvFa2A){HI{6Hx1N z5I*E>gD@k+35-J9{w<0)f+(X2%rN!8<*m)#qL7=ZPShg`X(Y=(J~gEV<-z6CculuK z0@9$xL18{)%O=B;G#wT23gy%+zkhVs0YXm-bO)usqfAV!9PaB3=acTd+%0zA$M7Zs zsA<`QK}op9x^--2Q=RC5kU?A=(>3FiA-l)*CXR$a0)}Pk=M9M>zodEdwJO9tX$ib{ zJ*RV^Oi@#vXcPVA*=@;qloyrZD+5Vq^Z0nTN>P|H;!@j^3IagMA0s6=l$7yooLlC& zhn*;+a+QDQuA#$!))e&J)@7cGMO7tkJ)Xp`YR=%;bfQESa+rvY;&K(thZABMkasgp zWj}2Bd}=js^%UdU(wU0=5c zjYWRuf7GW6xP&aiBQQQBi2UR#u>&{kE?D_rM>6}syt()BBg{1dQOX`^o;z_Bq>$L$ zBfBVb{SsGDmb)KEAU%UAksD?;%`{MZ<}qlW^R#XqS7PeB1ITH$Qfl$d*`yqXms_9% zsZB)s`LcoC)2E1}Ia8b%G!c%!Q(y_>0PsK6RGX=uPj#2rTbs5xR84bWRO^fW`EcXk zlIh7nT;w9OE})E98`86tks&Z~i+wS@!Rv>a0Az+2@a!Zko5^7MDblnpHAwL3yvsdn zgc28WL-@#D2(PvLf7+t9|4^N;*Y*GZ0URs`@f03maFzdHp{S8r_w#|O5e zU{SD%)?3MfuUOB5r|UNuZKlS9FXwe~bT2Le+O9`&e}pEBFV@x~Av>f?`D~l_4RfT? zo$cuWkEwwvNdjjnt1~a8Q8w@!$qf+-%9zlU!e9l%zaP4e4n;Y{FC6n}%=fIqtn=rD zoO?`ssXBh@D#wHj$s1Q+dvC9Vcnd@s68Gfm_)PBv_;0gm6*756J3{;d_^iJL@R4E6 zH9fu6;Q3G`As2M3Bly1{!@%kTNVOBZB6vQe^Fs7323h#bR&N479cYIxSN)|Oaw$?% z(^^+BamT&*kVp6PbqR@$!@UuxQMOn*!gA7p3%z2q;IX91K)|KlcMNK1T-K&Jqu@-p zfpbbbQwZYEpWx&&X39^t(fTfV01+Tw`-=e(q3^Hx`Ji*wsE}Q7r79X7tD;Gx<=xzi zrux4!^(2gQ%1fMiA9j{cc?PqR0g*=+Pi;|I|EPVr+K_0@ts48j&> zo`NOmnJCZCQ6L7n+IB+{w$vf}pj#_H!Fb(>k$xD3TYXj7`!~#iAvE2CyySl=?9-2# z8SF+nErdI9LIg{C2G{B9m@1WaFcua>F805kBYto!W1m<6Hp3q62ft`>=Ve+YIoyqAZ^V~L&*qr zmR=~cBo(4^mco#9;#Y_x@fH2M^w9DRMBf3@!F7HD5Fd4=3eLxUjbJt{zO3HElR;0m z*_r4V=aU!w0B@u6B}C(N(U5KSD~hPpkMy*A3my)QG9blVY?fD6v_<&s5m^i$?~%)x zUMn$vH&pqBm(%{K-x5nB%V3^X`*b}KD%r}PE${yl1qo^n&{_)f;8S7)&;hBU*fh>e zYsS!~_KqD)Vok^KQ0qa^P(`LNNVy-4EUycGeK2ZN%m#D)Z1*;(GQPcEHN6WVCM9x& zr|!X270gC%A20tqnZredO)H7lc~FIBk%Ca6_Zd)Uc^$5=(!RL*z||8f%aD_cIMw8E zSpN%f$u#;CV_duT>{)2T-W*3DA#*zJOj#q6-H4F`yIx{JO7(CB4NKh1Q!g^KG)fVZ ze*O4>JBd5zy`~za**I zxU>+5s+6hTH2+{VJ}J0Tey-G^ft1Y?c!ZUfe-qHgx3KA_&8upe|8yZ}CTQR-@CIz- zb%&!xPv8ZEJ$Z#RxeKgvjMMQ4@aFWT^>6Dd>uc!iJ-7(*lXzkm+9<{ntIm|Dvum+A z#Puw@2?^jyZ~Z!bUCNzO`UcZA5Xc_)d-H5XM68AVBuf+)cR1O+evr*L{l4}Z9AF7* z4A;Km&2eCV_|UdOuJq9tM|@7{oLd@Z4d!VqTFUvGfe@+lRztkDwsXca0zGl;`MTdF zv7cX|B8J2xQlK`kJ@7TH!uoa-Vlm7UfhM6k3(|-54agEgX!bdPM#z3I;$%%la1qgW$~cf=ygP?w z2K|EY1ym35j9gMS-ys=0pew_e_U{mB1lQkE`+Mzf-MoJGUm9D?^Zc2{y{>f@^MgZ2 z;)xaeB+3xAnUr}j5OB1FLH|7Cb%wMb+z@e+R{+3%B}RoFjE?G_YSW45%-;)G0!@=9 z8;73F4EF=C-0s}P)ceYJ4E!Dha^7d!4nZ7v;X>L&k8+Z8(>P}kUsH>{63CnW8$z6Nm zZovLN0c5u4l>q4rRFA}j3klj1`>V5p97Yv3mmN!z*fYJq7EN(1OgGJf zu*eSg>t^+D>A&~2h>wc{(lC=YYxw|#)M>9IZ}urnPt(giv!f%1q&>bbCUrsvnCXl; zxIDB>@^B!4Ni{$N`$!Xv^vg#}MbeS4)@TzvpXp&|<5|i+n7##LcHq|Fey)c(DLp|A z0oZmQVqUBu7oDIWo+^2kXm3CA%K^zdysIc$NK=^p4yEk;t{!PPqEq)2VfSjjr+ZBh zG$6)j%8Ud(wRbY8xGvyOV5$guW{< z+iNf3KUU zvabmOyTl^Z=VveceK9t2$#PzyW0BvkxlW5M#1;v;L!)Xg`I4@#xErI-!GdBDtbUz} z=R`Gfq}b$TEd@l~nYqfK>K+(y@W)^e{Sydbm61{$XqdpuCBN&+H{;g*?2qc z;VY5YDG^@XD;EXQZU()!(N(J+30D@t)oQUnq;)ewGaUGI60w$98gx@`nV#eAO^vz> zdRLvza{I`q-`(Ue{Gw~hUcgMOn(iq7xt}Q0yL?EMIQ^o5r{r#UC1eRa?i4tU%V+!)`T%HCW%RC~}^{djSUmPx{B1Y#1Svz%3~PYGMkU3U6n$e@3(^RoSP zp|Ioq+tkl35&8dqn88ge+Zj*Z6&8+?tC~DrHUb%;_E6#_q2}A<>cM<3apHKQd~edH z8A+RTMFun&%ABJL=9#)Q$H&-}fZ)XIXAsRxFbq}C`+n>Ain|9dFQG_?OuKhXz@;9p z+s(wd&EDm!&q;p%D9apgZnh>17+aCG&&uoCwtD%Ho=mgtIQIH=cDi5~@H{YpYRo%llfXMAjv`vR_uR4Yahhshc3Ro8>3#-Tyq8 zf4*h9vHU0jooJUa>hJuB@&+$t78Wu#TCr5A>%SItBKV|hgai@H9y)GFE;+niUwFIb z2;y!0qi`;>b9zd5t_FN{VnfIK!R?3eau+c)klli3(cW|94wP*zl4etnqJB*1g zEh{y(va+&mKpD$(OCwlB@VSx1+Y4TY_7He51X{!IBn5$66c=}XT0n+LEcFFVQS;7qA$P_GOV8ILweykmQi)7D77#)!)z$1A z3`(5#I9#hcI8n>Ob<0FN&cng@T zK04KC0Hc`(i%nK|>$Rn=H&~VOX|LpT<=pkCtrb&ws-zSg8#g;=p;2V$=ZNm_d*%8Q zwhml8slhZ$D@ffRgsoDt$z|jbi`2a(ijGBqKL+!w`ZE!NmdEjAZfjExpBLum#Z8;> znl(PNvt4fS#`O=VtaHC^WVf;KX_iKuX2H;NZ_W+$s%4w)?(uQ^IsA0XUsbem`W2#z zEl&>#IdUfYX_ex~B>G4$E2J#meNIM(AIjh~SBT|^?H?dfekK3#6GP1fgtQZRdX+>9-1JWt`jX3c=esZY*=TC_9jx|RjR`G$ zc~{4V5hnKdUfG%sNC8`P-y|@ps%)(`SU#hMD*siFwe+{BD(E|7hU(mwU@BmaTF)zm zoi#g`)jHHv%ZR`QUnLbqOT{vuq)#@E=85}Jdpz7*cg-Y6s?&>!GvgUddiz$}1@1+{ zGDD`Tn6m6nHTuxg(|dY)GRlPRev7yf8J(PbnUZqh$B+HbYRb=7u*>M{4C`Er>b7;~ zI%88k_ZMwp;%2FZg#`?}E(fJfo$FQ&bTr%dVCrLUcIc&KA)7VzT$8s_hikJ`vGtY7`4x*7SUXNOZd|-zCgz7qp$TxE3k*p#-;e3vLshn z0w;@29;)_yEx*rldz&+>2{p?kTdA=LR#`eJX}G3Ab?F!}p6ZQK{R>((eMLnqb)-0M z{+_aN{65@Va@8d#?NJVQ&fHXVia*{_mO@UkIgq&T{2YJxV7UHpqid|<;laUb!>^4E z0%{RRqo3o@c$=?N_8r6w5Sy`u_U#WK9mOaNz_k%mW zSr%6F@@N@r=@E>({`vDKJ3D)Ibu|ntGHVMToDfrB;k>s~E0Jp^L~FE8bi3;2%#Dra zn~KT8ku$J`Sby?cbP`2k7#Z>Uhfq`s##0+g*yFU!wm~jXhdla`onxWh{*#Nn-XrV! zVtA$kILn7TCJNvK+jjfa-MCEbrF;S|#;Y za*9|`*QINZo~>NDA8kwWdGv$#*RNmMm<0u2NZgT^$0Z=BzmIF#lZ=Cp{~7flyY9Pc zyUQGY{Fq2+XUxJA)jogwPFQxGh@`wcmpx%5)wb@rswel`jt*oKx;&?mj&}I_RxtI4 zTNh&kbB4I`7nhueZuuIi89czF{inJmro=`HknSWPIB60u9k87sa#f!HA;Uh*JBFiu z;@txpc{%x)Y^X=*e3^n`K123}a>`fik7iH!DuOSdX0n@d$sM&r(ZsX4ly`qeHD!D}Vz<{jHTnYkmISX2&*++W{g!;P(*I^rDtZRxF#D!6Bm99>c@TOgts11_Su&BO*lMe zV_wo~&m&iP`OXw^N&m2G@EF$Sl(@txY8F&`yzXypws9Nx#n}x}VA^n*`swCeWp2)eN#(pf z`n_5F19PPF@`!HBO}Up>atXbt?fZOEy?Q9l#<8sOE za=GWhErCO5+qH8W%4n0h`aPC+rnlzRvQ?u59L!foM&bwAor$!D+djN99+;VVeZTJO zXqjHr%1q0OmGtUFFD53YwySx)0<$~~YV~${SLyx2y7}WLm9>WuUc_PnbNmLw zE)HJhJUeMVYdgRasC-$Z9IN1jtHq19nyo@{fw%<&RVDbVYF}t0HG6kRu5C(OSbMEE z#*SJwMzf$!ug@#_jpvJEte8+7LpbY}h6>m{j}P}YH#cWzXJx`JdH_rzH(K#%s+#Y>R1V)w!0Xktm4jp zOjn|we0kO5bw(3ahf&QFu|qd~WYEdxfD=1E7gv?L3oB*7_DX7Jr>;y89VJvbjMN0; zo%Dk?aV|~%!eLzPstQw+&aO2u$S@*;_5Q%~vCV}~y?E7K4lU{@E`GjR z4Od__Tkv_3nw$IxRFT=pLf(v4M~aM*xgmli`!FkeBaMX#ziqkaL76~{wjsL)_q@D{ zLefjgMP>sYys0A-2MIDe`r>^~(5klUvDTQ^mt1bXG-eYA#;Aa>nIr zIBt?12~)Q9ds(I}!P!c$q}*rQqe@Cje$DqnludxCD?6a$Md!|6#4f|pQ86@32?)UA zxuAUe_Wl0Mj!CbRf)Zv;Ma_k`!!?DWhAB~$4V>f`^j}&C|9_mlbyQY+*ELM1(v1jG zl9D1y2?A2m(hVX43MwVdMS~y+Qi_D6Aky6>3ev68pfu9WyDspY`<&-~pKrY58{_s2%{fjl{nsYAaD~Zi0WKkDUew{zSnG3z(aZ%8Z&+`F20eWk+-by^bjbD09eG6Ys zsNJQSm;C4*nCD`3mA8tlP;)O(<1GS|iM&1iI16)u1zC!ET-DcV{>>GHLg^pliok@B zY9{`|*O{66pTfJkyP|g&XEX^kW(x0-vOzdQD6b4ZMf4j{^0c;rExr!lwTEQwodGv8 zQ+2b)J0eZ4gsiLZdEmNvpB^9$I^7cY?tk6EY*6ork6OJCmkd#WFBP%u?(gYEmxo&0 zuh}#d{I9CDS8z};8|#`4$vM}@L>uWzy96K`df+1($=o%d}(qih}@e}Og6j^s;JDA3pmo#r3OdwYT1SV!@#9m@kX?PIM!?PMk)SdR;tIL+BRgcfTv9gr~(4 z8wx&uRHDq>_h+Ar83~9D8o5_SuX@#EV_yppr~z#D9Hyt{bbA_Yck_ObB9MhIj7M~aTGG|m7*)=y8K{WAWOGf+c-U%XBC47lPgOK^Rl`J2DhY8b1){HIi}sO zY=+j;Z=<1Eo3&4vDgPYtJRMTbJN4`od}!O$q(a(e8*6MMxIhIw&wc*KY2hF zYWBZ|w2N91qyFA|-{124M|8oTu2J`MvE8`w#xooP|Gi!bKg;pjts8|fxf`}3#D=}~ zs{NX8DpvOJb(4Qyb({ta`mo^L*7s1*yQPVZB~z0y|6(? zmu*yoH?M%3V}2s6c*JT-h@=<*ADn{meEt~;o588=#XdW6iHV(`*b_Wca+3l?_-LOc zF*Jr#W%%N5@u_hT?qJf1SEFsr7e7!-3;(Lqz5GoVY=Y-$`WtgU>2x3Ny^~MIVXtv5 z`IH&rf40peR^`}E9Ms4jNyX-4|Mh`r?%khcdx!C4Jdkj;#mGv>Oi~GX##_rb4s=`? zW*exq_$(YJMC1*W4!_-7?M6pYHN6yASHwNR%erv*oJ{-u*AuiNXvDS_pHs&&G4b3c zKqWfKRTB_LFJQonyP;p|ZuYYi8~>mI!FwC_bE`CAjMO(5DtvXN#a6y?c2?F~T)%!M zIbXFK%YV@44Ic$=pW8kRil;|KPj0{6-1gcPJc$&=Vf524f|ne=CO0zD=o4n7KV$GP z(i(`>re;&BeueUIW(6A=H*LjFdh>Amc=ssfBXPLDHxLe2DKr;9w=0g#`9veOpWEk^ zp>@0jqJWa|zT~TYY8OhG1HUV3{AXuToO-F_h;E?dW46gr!nEx?n6Yrj-pp(&j?esx zajk7ko(+Y=&(2GF0=a$bESva8G4(0Q|uLvzDO97T~GN&d-`*2uU{Rw zK-JMwsHTTiMYuZ@TR9)e5dBz{)O~S~JD)*CrK{)N?G1yh=WlhphYOCvFWv!F=ZiJ6 z!{fQxcH`B7oSGOC0y>4lLguX(5(F@VV1MODlfM;h9h#Q8BgqW}JX>C1H8oyl|3^`> z#aOd_C!EuYDHZwXBAH4xcJ1o$K=7v?-j}IY<4HCrE{>ZD?q*H=S-%O|5{T zrP#!>0m0{QHJ0S%`4Y)`49Ne&1paWJZkzROM&(jFvoI7U=S;eXl2|D*R>DgTT!~{$}*DtdhKd$)s z7V`QubaZse9{p%+YBF}2^aqvWZE5MlpAsk3Fz-}TQ`5m=b8WH-hIb99y^{^26LD(v z!;NCSlOXzR9j>>j>1k4UK2p+g&x7T?jh{Sv#UL{rlUGpCt9UYt{2_UURi;e=JL6tn z@c*Bmp9f?K*@r`K#oV@+zs1JKKU<4>MEQGP4Bw_G+3p~G|E zE1pWg6e?(BHz4wiYC@W|jhb?p$l{}BkABvAbH^R^FmXFdJ)Ko`5lf33; zXTc<~S_ipL@ILY&;o|jcH>jEEJ$EPJFH3mrZ^B2cJ>FlO{`BHx{N!jH{-w8xiAMk! zF9_S4oE#sy0bs9j+X<%=5eIP&w|=SZXz_#T)-XWZpFe-j(fR;zuBGr^dkmLuq5WiI z#nYdiZ^aH^DlI$_*6Gw?3!7{$wVIm?_{q?KZ&n+n{2&Ae?Uu z-k$x5&37y_} zqfSIVUIZWHD-nvvoqvfndaJluo%?1W!B_clNP|-w_o|cmA!W*KEAuA*25!wQsJAxN znU|>d>2zDqy~LE46DE6Zf`I6%b0K#@)O=WCR`^zh`kL^=!%otis6t9cgksS-6R^U+ zP!l~Rgr;9#6Yv(eFVr``WFiS5BHHwO`Ei%T$;1WMZWyobb^I$Lf;AeU|0S;Zsn@|n zda4$n!+<_~=2{8Cbw;M2W3Mculq92Rv*jCBVei+0A>fi8 zW3E30gbjarWtXq$i0@y*OTnD0EVYVcn~g&L5ZVnC6lvdwy=LSpSWy@=suWKSE?+XW z7cRw}+k3I)A<0+ub4#ACXm2+pP_B`MWKYyYa>?QayGDRFv5z0GL3KHu=4FOt)_cGW zSU38esJIh|00aLY%IXdmPK^JGD;4|E zYLed-6V?g0>DJ@w>fEWk76yAwQYD(lq9-XPpDnK6Aq?#bN{YX}flAQPjQs6~x_;lv z>R?2q;&u?V%2ajm%_SQbm^TUF z9-2=d#z~+KyDkxfa(elM1YnAtEA@1XL+Qci5nWtaK{F9|di*$JcdQ0K{bzi{ z@*N2YJ6QFZNd$)rIb@0|hCzCM{0-OaEGMW(#vYqYHuBk~YfRd&8aaK?yE|eOO5(d# zm10cl4kr#2>fd@ZF~xYY2EU7|Juo*bt$EalaoB=<)1vrjgh0?0u*cWQxQLLcYG)7=wH@%$a!xw6!&x+ZIODk)BD7@Gu>dA1oN zi3!v3v1iQN%H$HFe*T7*29QnZA5MkR-J}_zNh9%2Ukxyfp8(#p_|cC__yaD;YB)b% zy@5mCZ9YBL@@vA~ZVs;a+?09T%4W9*U6TWK^FpkPSU@~E`rZ|S>^n>T;FV(cbFHkSo9)IubNB3ZQ-?C5<79jSE$>K&@tW8_2caq ztUJGc-}KsU=NVrdDWc0Et3{i0R60pX;pTcpXpDXSoxUo6>ofQ_foJ&;=cHJ7ypNJ` z`Jh*kuG?*m7VIKwm%dEWV{r3vlG0_ZsJz8Qb=$dOJ(%nB%2V9M{ux}~5)!M#Oh(>c z?-_M=Nvv8AEXWIfdya{kd^bm1MN3+$vV&+Nq|);41pSxNd-TFasX^hny7uy>Xqag~c@$m9lWUB-6U? zf<5g>{{1HwpH)>UHdRJ+H^|FgL?<4tR0%$xG5<7Z1pI?+Ect*omH>s{TtiQ@u-~}6 z5aOd|*3OqDf3y7$2$x21pk=G4tGl{RWou*uO%0~E``PX;SdSi&Ll}_{&e9xI$KXV~ ztfxd6fHKuk-VB53nwHBc2Q!Ig*9cRukh;tNNNPrmx!PbDYzITK?o6a3>9zn~1Jg(F zDTOOTO+d*-b*toi8v~-B{ zpe!Pyc_G!^2KPOFUF)Hj0w4DksR4T;z5<`4UdwZi+F2UKUWWcJI$VPvp5$L6J?yzn zFShgjDVc=xib1-5X!JtX41P!l9~pND$8@t>ED#h<^MShJ=ZLWUOGY zH{%Xbtx5WEKFK!L0UsIW`BE2lYY_wCx|aR^+_N@`0n&3RA8V_p8` z=q|oZStDWseRtP|gO$SXMQhk1;YaiCaxb+Tup&!`3wRhx)z;@u}Z56 z#A-@hZIw%0QBl1XDgy~wSBHBb#m9|Tcw0vPk7i%8Ob;thK?)+Y zO|H=Y>P;V*`)cR0KVJo9s;}ZO<}lfAZPw2AGM6R6F8O1Bwm>f;$N0u$W{Uny6)WhH zpB$}v-G!dM9k1U}^@Bd8L6SIuUhnmtou;spBRds^%Tahy+SxBTcL`Bq*4s|Mm(Nec z*OpCh>};SLI{0{ql)MX&UAALP`^|Y?h3)=EamgK5*Ge_UT3R57_4flwIxG+$@)`2Q zzn25^;=FPJjmsl!PYV^snwoQl(g@|&c%6`#{`HM)PdKNbZSy)QEM~Jk$>eOZH+D=EjPUEp5qM_ z3_!G99(0pB7o&f?cCKFlR%nE5p%Naidl8^JPGfNsNjvG~)8A6-HVKVQEp77O(9c!* z8r{&fG&039hs>mt)9z+k0`C=B3ucOceSG-E{!u=m_*Y=+* z)J!x#tm~4r@cJSKt!&j*a_TtjihJ$)7L>egy6I5YJjcv#&vbBEo8Ty>r^zy`8iisl zKQjcALNn;eF1A`M`;v+P1xEehrOf=K*ei5h6q$(_bCQBlqQpCw z*3scSJlmZj#`~2mL&p1;Pn9zv3>PG1VP?5Q<|H!CAsQYUx&cxR*rpiUD~1@1fl~d3 zDat*^j^yHnM@2B{+2a}`BVr2JY4@dqPq{y1k^EP)$zPYi!$AC>WjaX->;wU8t+c+p zI|WCn&|`hIzLEIn*nl3)e5`POG7M_em?D%&WBT^>HTB`4Vg&!b48f_EtI0~}uDlsf)k#cXN6*5)0+(!!mlQ>F2nmgs=`vJg%-F=jY9O;n z#^@ma(&Qo87EGIYC)65t|AN^DkK~tM?UDD^{+tc1*WH^zyaIyA*AcuIuBL_^M>Ref02&jAM90#(eMIQ7r6mo@po|VD-0%IPvtA<3~P%EA7U_d*kQ-$l6g|jmy zqkyP6E47dt&P(92Y` z8sL#IA>zEE`9aSS&`8iZ8bLre^3k3X^*+$VS|`Rs;__&!rBAA4g2PkkY#bs6R&_03 z`a8U7<4v;7;xP+S`;n&tl&9V=^v*a@PLu|Osto8gIv!6b+a^r>G-iKieBq3P^u8gb z_PLYM-zjB{O^RA8WsFnQ?O3z$>CfH=lvQSpu?yom$rNfcERz1M~6X97)J_az6SxE=j@ zXCsZZIYB7}AfUKd@Y=O9nyc0zotXr(E*caAB{0SB_utR=MU{+gcqLsY3A^Ng+y8Zf zzljWPSY5tT81L)3-97CuzbLWKSlW!}hh2q5n2o?v1MQ`hBo4v|?W3b3xpke?w#SFN zmD#NM2A#TD#a}qvmTbk? zzAo%77@o&hCk}PcPG3|0Y`^BydTeec-*f!YCiTez<+xWg7`d!Qi?e|AWaiu;=H~1-h*?H4you|&-Pj8pIy*;)L1{)kmky!;u919QExY?BQ6x^H`s<+Bj z2JY-s{1$!AzGl=eB;&y!fq1(N{yhH(r@qfyr;6GE^VgXbdRr5P_mLVw5dxD#Q z#u$Zd6@fD)`E9_+H5=Xf+2L=!pIvrEjfnnh9IPqd>g#U+x#PnP+AO!`_GZFhqLf=J10~*ReDVgSjwJg?TKT^?CriYK*SWa#+-Y~vg0dt$PL8M_e#0`X zD&6VN)&vC?6r8?33@=}jynbCJ09%oca`&6vLD1p%S`U;+(qxw^TzuQe=@ULN#K=cVxZHotk7&HEWqIS<%XYp`BD`;__cl*V zv;t3o!XV?&Sve9?o^s3W`Nbcx-Fb!raLm&ZU-lUVuN{vLZ$R_INK$7t^awewDWKPr zDWc`L#6K%TS`8TG*#5$8LhDMI}r4Bx5co$C23@?`~eSAIZ3*3hY+M zy!0NBWR+qfZY%{s|C2;RTb&wT@D`?%s8!ZU&KHZuW|_#|^TZ*vd!0Z-s0=eRg3|x* zKbsUEaqlmQ60^Ogm@ZPHbWv8IAx0^tZ!>@Q`EGo?0R2S0k^yiE=vo_#AKg~R#HwwE zs$nAA%a^Q=#*dvcmAQ2T6l0ydKU4f=ep&hQ>IdjH(N8ypzdvT*?TQMK_L#2{(>lm!AX^>!NXl~)+Z%0b zo^-U%>!;(Q8TSB^rM-ds1Jt99sMTZ%p|j7IBF@fc8j4L`tI9}i1C}FQ(^4Qjh{7I& zss)snQn&Qo50+UK?}0BTA>h1?es)zqJ{7|3zyumMSYL zT{({!xduO53?zKJ%<)jEqjcy_oOfNhG-J~JuL+-dxfrgS;H)h*AnKoriW-E|>4&Ol zsGGeO%zmLl?Cg{WvyiKD^I=16{Cu&}!(=>(GV9waXcZxWc=AO3ri*fta+AwBknqS7 z4HG2VwG~09haD%j8Da9vz>r?#*%Kx%c>{w@I6aCqlhd(L^@?#0mx}I&JZPaCDFZZg zGmJ(YG?6Lq2!YPUH_1LaJs4zg;TT38`*w-`R%aUl?tk<-+9N!u2jlGx** zV&jX!(&B`Ng!$1o9NldOH-Y^pf9wr&+kDaMn{e>(c9ANa`#L)Id+W+;qPbSh*>)I@ zt;eb%q6HO1MR(+=R_3&R1KdmFIU|>v-vPN~i&0{CqNz2=FVlj!DRaE_u~mub5nN4% z25;cI;5~UV*I}tZM#1JzBwCo6NlT}>Iz27_-r**Y`;|J*S4&R1D8L_MHpYVHTj2$t62!Lr&`aN?p5QRyDo#es zcOf2R$rwJPzyJwbmTnOinf86z_&@v;2hhIz^EX{>n$rwb-snhJsm7|k+jn{PEZG#K zvQdF4V$9_PE*`^>GYAu<@TjkZ)~R7>u79i2er zd@bxDDkYcMJ$&z?NZk(<45S!-SzL6-!)LQkfyZo6Fee57lMmQIAMkKu8)Pl-)t!PUz!gmA3R z3zzY=(ATsQuU%&f$Eos3P1tBBv)7gD~f8UMO!?Vn(ij^C1lwH z@bCLvk9q!I8>?SPMhF!8o(jg!3=pA@LnqJc!-#UQe@N%YLf-{iW+B0Z z`5q$H6wG9fSM`apHPllOeIN?-k2ifgoUjEv92Q2u=J995a3%n$izPGgyR#CkEePX4 zFG~?+MK(N}M1ynw;pFVBPbunzEirLo1Qk6!9r-}ws;py(YI)3kNl2`^4nvUaGuCI@&2WK0Ncu6;*|G)#3?2? zR{os3DA~;%jHf@_T=Hh(joLQ$j*c8A99^P=XzGu*7Y5KkX7L5cCPMwTa1n)><@}Q%z1>k-sQNU3EW%w5*ZNaCah@?Sqpdta3WA(mWa%xrRmt|F=&5!40eA(6t{J9 zWJCs&SgnB~KlJE=SukegF;~FpW+uXYFG8-WIu0D^Vp6sPo#ul05WSjZ?u&(LfC+6RplI7D6C*p_vY66u}CspAlgFYnb zXz)vG+}NvMT)J=Z$@fetpP7+h4*c#t3tpr8lbZhJaEx2jzVQ?MERBeaJE3MghG$rY zpAp7U;o@Y?|NOZOi5HuFK5);Zb}CK8ek3E)Vm`nRbK5CI)*In0?0l+Sp#GE8^w?RM zl!|6p`g|+!<&0D^LJAJ;m`ipTJTjea>7o3U$S$)C@)a^G&_Q{|Vp8bxss)xf0rks| zKKOREPwwpil@}7M=^ej&aKO$XFN?$*Dwl#8&%il1%jwo#uu+hu z5}B$fP-r5T&VP#8Gi?HRg@!4j9CubsRTDrg526IwKz`1Q4WidV=Wm*QG+GXJtKL+{ z?qA=XF0qG6RXEEg0oPWS3?`#gUh1g98)z_&*{k=t2Z7GZz3F$G0!r$3&CX|!ycI6+ z1akSE?AGt~b*LEHK0jMK6`_|ymdGCq&RSS;BSNtBBd}GsEqal>96tG5!Dl zVXc$(_S->eY0YzUE6<-V$p(@`macd|8V^hwV%m+a`5Dh=t^<`3kbDNkY;&LJC6c9M zu7lGq3Ji_IvCd0z?TdF~&bkO}^qyX2kM=SdJx`8eIPP+!XI@UFKI?#dx&}^=-r-}W z+gb%NP-Ty1t?Y~o)Q5u{Gdxg=k>+_ba;{VH$`5@2KeCBW{)ZsqvS_*4jRy&I`QdyS#BpNJ;NbZqi)h6hysWD#3D?m- zy76ZsB-r7ctc!cmkA3@ES49hMu)AGiEEjCgcUE$sk{}n@5 zT@KvTGMAkB!CnjslAmX+{>QD#Jn7lu(7XXkkbZWT`cwTxW6yhdpZaE!3!en_Ifeg- zA+&t{)}xNWR2t6Q@Ga)I#fDXuo9t8x|MmGx^BHDa;cb7pib}-y!*G9G0vFe}3HHa! z&mkjXA5|9OzJAgcl_o*@Eh?OOAR-d`VAnP*^0n|X{iGk6N@%=l8th9ranY+7#rlxbPk>i(NJs$J3B&dEw{Xu_U z&2c~@%B1{u--8~yhQ_qya;4Mx0!_L_P|X~?8~^nV1gkGG$;tjjhd^7_ME6%-V5Hfh zS^WG8C8=EFUAzi~UzGm~K8%Wu-TE6KirT+`kIf*kRC3OKzBl|}=LPT1QKSFz1nnmA zn=J}%w7p*Y;BU_;(!@FRT-F#3yh?{ySXc(3!}>pN_2uQC`iR^1j~|P>3hse$pdKXO zH^)@ldef&zE)4+#qo|^ynb{Es(toZv^(RlAW4QI_WNTkk{Ks4Z51(aRrwsFHrszqJ zAX(4q2x=l zybU~w&$q89yGVP$&#KnpUJuSb!HXmc6PL}o8O|H9&v2v|pP5EW=C*?sXi1Bf9Z6Xy zc#z8i$$)^9!{ukbfPHoYX6eEzsa z!bb9uH4@!FuO%^TfL_}*EJXU zZscnVf!D@1Y^$7m@!i;uAO0p8HtIO_WXVb#=h3OnqvQkJkM|ZpN{YA2LA~smVm#w= zRzpxXbb1iiiY<pW?u+V zTbR)dr#FEFKC_MVeIrNo2*~r=8ZvUj9h{ucM28t_QLkEg&l|MNILTeo#uaOXvn}K^ zp5d0>(5s$y0g`Fw7SOMm3Q^&8%(~-QN6To3`P=XR3J2Gl+8d7OL)3YnUv32e{d(orfUS`g&bx6<+ zK9DCvo;=X3wtWAa<_C$4;A?!)SGo%j`bf`ACc!~he^(gRXsg@T1o5;FjYSMnQjPX{ zad;G(0CfQ3z8-m{6b+ z1*1%F&CV)4MCpvcn3Iq-W2XZritowueSwXWYdbqkVm2lN@2@EyEov%R^|9hu7WKb2 zwK%KH*9Zcf%A|!~lj4IE7UK;n+QTUGS$r{!U1rdnHOQU({zM3WV`6$5HxEqsH(X|b zWmPX?;Jq*d?RFgcFxsILU@z^bMq(;R23M|agkHG&X*}+H0G@?dOa-7fj9lcHYx^f2@LoMFBN4RmDF{&1OR3&sQ&> zx%c$x6Lpi3kW!_NTDV_f#b1cO`U%TDqqx{_Do>{I#u=n@!M;_c&-mtRFlIx~YJWBh zsu8wvZTBs2m8q#IrQl>i+uu~*vE0)vB^l5egzUdIAYcPA8Y-;eS=_3gDLMFh$as6; z_q93rNN1?z{j0kp+NxROAwFV`)?@*US3tm(y2{A20A52{6CM}qaA9s@;<21ZC_KZi zz)^!$Glr(gW`YFyfiA)a;vyuBj9|m~_pkHkoZ4OYzli2evVIFiQ_!^0i;W=Z;?8?r zA{}V}lp(=m5u_?N+f|a3IiD?i3e>f!IUa^x|2x3I`rh4baIYmX_3KWctV%A_^?cS+;j)_bAuO9|V-?P+$(AY*1s?i@L zleUk5kV5{h)hM7$dwM3DG3pWTwLT~XOB_ao+X6EgUF}pi%JW2y&dVI>$N#`37rKp`~M-C&ocgonN9T8YiM6w!AGe0 z2i$p0F#wv9A385bk3!o1=MPF%*P1oH{eDaTw||p1h%^2e1wIAUc!;#aO-_25AlJAK z3ybi$_IE3T8CRp*zec{6Q;qh_8@6R7HaLNC5i3A|Q5vJ)Oj_AmSCpS-`_jjZ1U84EopcUqdY=yBYO7N|7nwOX_4SRx^jR``w zU&5O9^c(~Gh>8TA94!;rBT`e(dSHvt*xv|_QO+2`@%&xncjYVtBi1P7oR(Ci@Pm5} z$k2@tz5&mu*lwXaM24pQ8QNUQXkf_|wvcnKEQ73Ny*{s1qix_A4v&tw26Tc# z$ojs-01{kde~C$b{$J(aSy%w_%I&d$8C;^wX~9WJJ3+)eL=A0U^agXZ-PR)3)=Fb} zekx)m{uikG>?N=PYCF}f=@&zlu8u08syOSAiEZ^y1Me@(r$+NKfqV>9>!w6+&j4mj z+%8^8n#~Z==)>oh!XnzcGf~)=F&H*ZBNhf+Ch7|te5;)1d*7Qjjb?Q!$b`sCP{v-h z-UUsgH56A0e?T60_NQt38_^j5z8#+ap7M3%Sr{W?UFX6{5_(AEoq6kGsf6SYnHU-_ zaGCs55-kb)1UC=?gpgy@)ya4M#qua%$6K4o(aeVQyBV9IZSZ^`naZD?>0kq{-WiL= zr!2iK?XUn{GY5Q^S6UD~Yyw#m(TLE)WG;U8)|kEX#{Q0X6Q zqCS2A3bWDD^HS-V%ITF=RS|E98JEPmz%czK)>#VK`9BL-u*#v4|AE_GrGd|T*50Ps1ZYNNyx5?h9o^IW$19;Vjn^=8m>AWeUxg;QB;)~2I zEEHc+GE<+Pt2i5tvmxar<+lGgxb zH5u=0I=pMn&AsRFMpQq^X~PmLIA^T9fL=7D4Mjz{f9KJU8~A<}2is+<->+k^WuRl! z)QIht`ouh^8NeR7N#4y-+X|T0M^ja3k(^tXKb%ej3HRP&o~I&`z5lUb0WOi$qMwrS zs>D-`@FBtX87;^sT+X+TQJ?9MUy~o|cRq%V?_XrbS!ZsJ`~RUccUfHg2FH7mBz{*1 zV^_x7QKH~fhn;bGM-Z5F&kdC*tl&9)VjEaXK3_E!bOTCVhMq#bLbc1 zf{`}$Kg?%H(y8j`aqDx_Vybg(a4eMCQd7}Svb#Nx0?94hZYx8^b~mR=A3ptsadR<{ zWN!8zxD3Yr2#PwG*&j^#<9}-iV*3WBJ!nbId<#~zzw{RKf#?zM)vIrv&a-DUjXtC3 z|7e^ElYj~o&lEw2f%Ls0oup? zKN(LsVY2i1u2kZ*Lb;hqNzQ=O@Y5)pRRTqMJz869pTFS!iVoaSkIUw(Ei-N(3u}M= zLYhmOAH*Ekg2NMHBG^#>Hwd;j_qsoXJn=7CP`(f^4K(Z%MJs+oN4C7&N{{FMXX8Kp zySXmO9gP8-f$vH1FsZ|xHt{* z4C=L~&U4p*4LRwm6yrt7VVToF1fb71)r-B8zI?!$s#|L;T3NYr6T%Y= z4BoI`5fvq4BL13jj*0<-B9O@+9u_ihBi&zuuf(3mi)aB3d2m;Tai4gc8`CR!-#EZN zX-DUnVeY1T%3;e?Gj{g%EpN^jBi?7|rE>lOUmbyF2?mgJLoHVMak&Mr!NQt6@_DW- z&Rv^jYj*`mw!PLN!ry#~Z}}TMRrN_az#)7M zf~&kw#XID|TM(ruGO7o+IOv=Kt!yA@krs>XZ+Ai-%!pinHGTUSvOneIwTS2QI5>Lr zO$$OWFKM%CaEL3zOxZs3n7pr$q8w*U!pw|u>HeS3@F6a@`|d|a zL+Tn)CO%JXF2-^)OJ5m&{imU1X3{S(h;dQ&K&*MC+bblRe3+&Dt2e5tI~En=7)ruG z7A9O=P2;J;TvSSeEt812ftKWB7X4w`!77}U@clk1he+w)XMIB!U{#DXEg|Sa@e?Ka zW8Mv*7QGOu|I5gS%c{b#Te5yMnix z*C744jU*ihS^^-}D<6G2H*-S6|5uB2B7zbR)X2sUpD} zJ-tdxGoqhy3-4!?j;W-zox-olwHFz2p7K6Ln+L1ZCbyx#95|~ceKES#7sKz-+pRv# zEZN&zg=dnjdPIlC{mARiM*KB4vY;)gE$jw6g4sJMVbOk$0xDh*!n4!15poNDT5G+g zKTMLc@?LLKOD9*g?Jl>54J%V zZomBc^|QRsSFTb1$)}Lq`Vb8Fwvn{ovx@~cUipy7`T`lwZG`t`F3)g7>`6JQeF;Rr z;*Y9=XJ>a-3e~kVNb%Qo-Zj7xv{|}DRC2&@XKAykcO5W819bE?NokaqAPUx`KjqtW z7w7}bI~I)k_PRuPvrt&fI-n{zYw{@m$8DdZa}U{1%$!Wo3Z7-rctNL63vnBfAM3^@ z09w{j6A_(woveCN znX(j-a1k@oRbbw|I}KD(g`&8)O%G&p{yZInV6lH}EVd|P{nrm>!0gD(NInpiyZLKQ zSHjS{mu{fF7nwfwrvb-7;aBiUwlRj=u4hd(r+NLG1-0QGbn(Gw(TA@grKcwaE5g1? z)%h;BD<_v0+sv2tevqhJkVnngLIe8fz}cwmiWVQ;N?r_nO{i-NZ08riH1hXD{tc;w zT-m`Jps3`I$u$M{jtP(b<^z!sRoBStD^guPhJT(;)xklyhcHF1CSIjCS@OeQqT&qY zFm>s%=zQ46DHi_<_h}ocK*LjWQ>7s!A*y^fs6v_S@Yi}hOa2Q9!36m@xl(}g*Tqvt z@sRwH^(&oAhNxrD?z_XQgoaq%M*;&0-h6@@3G#(JJQ=%z7Ce6ga^;K|6IQ02xR~C- ztVwhlS%k7wg^rLol9OmeDrdY23GHkorZpNTk(mE)X#Fl0(w(ZI8M|KBa2_;2zm{k& z;j3T#(x<l?(5-lLap_GdOJICSAGt_#clOR#*hwIu(B!l2M6> zhwPWruL?@zkO%nYNBdWK-~ZkTyM`6{gLvWeq*rWt?{DzR>r4Opdlu|sjH#shcXEPe z%%1gCfXUy^j_}+(xco=Ekbn_Nng6tQf2Erw$l}g?M|N&&R`Qz>a&IrzmUlm8hnu4h_0_`>9_yCH(f+*q^v_N@ zd5l{gw%#$m7-W&J?;km!ioQetQylz3)2-l-7zhlH&u-SkrlYpNIy+o&N+LLUG;CyK zwG0!-X0)ROt0&vG7q7H5Pm|8gbanc}Wdgv7%ad^4J82(M(Jq zyb$eo2lTyIml96*ZS_}=g*0RCw*& zM1?&YEP-!kh4p-LHd}xle6bv&QO z%+NcVm;#F`jla2Mu3(Ep0`z46(xOJ9Zq@MA^rJ3AT(zF|#}%+T4i-Ov(e!zcQgQz> zv(qw-)ImVQ(>IBn?(3g@qtI7C?+5mm!+R`X|F-?xVK0PNwrLBDJane`!@&PPM88TOs9t%T;Y7 zh=^zz(Hq^6&goIYE05t;KFu@K5o7=rtOzGj@ZSKtG3;-EtEy-2`h zVYy>Flt=w4z*ZW|Z>Mm}wwwhp@Hz@Ify#UuY;maS4cB%zy0pP`h+U2O-4fYS#l0P# zi`L$|ZlDDm8wfk`+$7blTj14IB_#0R8u6uaYKxz@AdWxmw zpR62`!Xj-FYND}r;f`qbTlJ=E#7Gsa8h_8FFOY=BYO@D|Ul9>)VUHV-iXYefx^5Dw(~)HgGTXx_o@GOjeoHtVK37gvg2m$(ZR(% zLN+^Ie*SOh>{7}gI!%a?tdi7yd?fNwpE4&-Xj||vX{!gn15ru>CO6Um9)&c3w|TD_ zwVKvj4T;zb9ai4x1T;&4Y&JDF)0~fZz>gZ^lx0s-td(aXh z@6K&0#%tc1pPz5C&vq7%XX5wa&u3`#td5@YeaA5*vheix87+y_x{6N4++HYKfB7+u z&_=$lL`TM)g?SVIRC1j2-)?N+Q%?@YeIRiRM!HC0Zvb&qdHY3a$b5@3u*kH6ZFSmT zk@D1fBe-OJ_wWeq6fJJL@JxW51I#uM+w|;DyONKT49C^i1?0O9%8YGT{LPp1qYcojz?NX>#ydUI2exxNr=K;MVzv~ z{~LCV?Anl{z>t=9aGmtO&rVQ?dO71kAIk0(sPYv=5@uIFB6?rO?; zfVqHa8>YAcWn!SSU|?dpgRxOl`A>gQSXdoo3vK5{H8R6_sBdaDLXAeF8(~J`c@r1x z7oa^U5^B2o8z{4=A0FZuQ#G3r3N~e<#TueSZQTz>ZkJ_$}u~-`)NOWF6Bt z2+FeRx0{tQj~CBn?6u=YMQ(@0|7-8BopF8=SWoz5M{Tyy{D>P%5?wc9ycqIXJ9$Xt z+=LLEB){471FN+yv=9_;L}Cei<$r^V0b!+fVJukJFb2ikX0Q|aG&N_iau%*$SC*VO zPs(3_l+D)9_veMGOS|rf;xmGD9@6-;&CDcWdjvgSnwy^=ESMH}9>aU`2@k)K3PVFm zro=`Ys#<^XyF;BKCKfDUuJOGaFZiIlBmU%G%SF-h3!Sh2aMjvsnOQ9B+>RNJtDTeN zXUhYx6>-ciVpBUsL4jI^bcUZh04qfAn(z~gSF%T1tb48}$HYeTT59uU94w49oR?B= zBTu_)y6?)qUW)RU%RaHeL#1khL@hA$eZXn2_7KUjyhE?kcov848=1B#^bm2yfUP1a zkOgu=Pr=3#AOqL1?p$5;mKoYC!`Rf`Ds3b_?B)h|xYkqt_y~D&&(%A9=R-cH>)%ce z$~^q_r0Yd{vBu)+$j1$t|4AZ@^dz7OA>Akf*3N|04&mAI^JpdT&CF z6a?u52}B12?Ns%Nxj*JZ;C)xVz(M{l+uN)+TYISUKng`xO#jCy#MZiAM*4b3C$PO8 zFMxp|kukchtUq3>T13IwR>t#`YB}wHan&9{l)+N(j~}x@qA%}%uzj<(pN}DMH29Jj zxxJZ?veUQ7ZW8vNF5sslkX?5?)~>oDlkWV{QgTfPSf;y5bu;SdIOUXE3G>swtbkKq z&C1JBDYt6@TN0o#^ABH!U&%%-5fRO3V|zOjM4U{_Y4Jh1PBK0H?pUi>#t9NQh+JO^?au?1@aBuph>i9YvuVGfK$f`qvY6*qxqfFY z%fI1EXe`>e_ueo4((0BA&LxZLnyx$66l8RC%A4q1S=IwzqIa7J=i7i!4~ReM`v*k3 z*+kZNd@~xNdM6G4PiJ2lRrS||D-yz?4vmByQaFHwG}2uX(%qdBQi34ejg+*s2q+~X zDTp-Ef;31gB@%ZZ)PKD1d)K<_`o#|}@V8@TKl9AYGjCVhoaBHQYkAgjuuAp6`aYMp z^pURASdW;H{uIohUl|3_Zp;X!-mg3ItAtn~(vE|a{Rn7>ZX_3ai09o)^3~vbtR0x< zXV)9nEib!{_a8Yst3gLZc?nP$-BSZqV=;zE7+073HZe-VQ*?Q~*NkY`Pj2MhnGp9w%~;2Eo)aFy%YQz>s_ zF=zF_r{q6>{tQs5Qu1!PM0P};3+7~2cNXX23LjY@q0Z7z1;U|tUMdJn4J$Vi$=Z!* zaFxMt(|%=)<%oq|9DXC0D(MrG?QaWp_55|kL#`Lo-c$2PdHj=O3-cT`uc~dcLwDGT zRrrrj{yTN+;c^DR;P=o>T^EB0$=!?iFIp{(G>?6gY*Iq^-c#KGc#*wNXJ{G&cKfVa zNC9YT_6v+civM~M5Yq7D7FIvzui2wi;_8*3R-{M*@Zbgk;Nh(WqP45h@7(NE?`w2? z96O+Xq~ar&NOCvT=ooPx`~D2*_`S_n@fL$3sfzR^QdIGn4AAD!RqZxrsE@*Ch%_=a zL7N`fT-6*#6asC?S}-JaGBYqSP!<4*;LDRGV<5W#8i_v6n{IscjAk$Uqq=9&W9G-E zaVZ{Ris7+RoBW^ceV{Mz{KwjD&?pp4g@=hSFDjj|I8?ylyY$4}P^%&5?MAeFwMtdP z!qpH13;qWJci_5Y-5qC8xpX+k}`b#UK+|yUF`I zs%aOdE9lLYkTd@GvqZustWA{wq`I{#kAOB%C_<9mE45Ivg$Bf#HrI4x?%5}r|9A3} zGKA-^{tf=+YAAe0e@H2j?ujB@#pvQVIt zrKc-zP6R}{Wr`W;>3Mh`-R2|8x_k2Zkji!Kipp&Ot36 z6l4N&`Ha~HfvCgHC?Es}NE#u8)%=nAi3}xp*q-&kuX22chli#)1XxA)quX5Q)eO*!JTu zg>FM2{v;Ag!^u%sJ`ui2rMYrE&YqJwlWU1|pW?LkRBq4_ilu`X- z5SO1w7xGP$FhZU1_1*Z+2~H`((Qi*+O#w`|M7zuwuZM%#PzibY)TiT{NVGpcN~|Ca zo?6Pa+#K*1WS(fvY__66LkT&bop|h0(R?($$yJl><#;qbNVeE&+U4elPBd1k;hJ)> zQKZiWVufJWwHPp~;azq0HWQ9Tyo9VG9oYB`9rBnsu|*1)cfVq|ltork+b#GS_biT=MG`A{FGU+_G~9s0BeJse zax2JMjtgoe)nUn&f$nK6Yd@$>rV?qs3y(O%FBYL`rZ*j>$6sbGtgT_MAQSDMZeHdq z0Ln9Cv>+VSXO7c)sLa07ZR$7>lwiVl9Q9tNqvA5~L>IQ-Ul;Xf*kfHj>ajbsDYur7ynDM4#vfZ|@s81)yf4 zCFH#+pVIMw8iTEs6vcP;$(fFO1uQ$n^*F)7Ot$?>k%II6{i2 zc0Mc2c@hQm_+~Wqg@n&8_Dg4OGpF+@AY(b-x&o=^FQ`Ze5qKKo0P=ZLl<>Di{I0k{vi-` zLaOW=9i<%5^gZJ{0Q*V=wuKmRBc_O4&a}W>L1JS3y36N6y*N0mwT_SLBg^g(byDVf zZzReZupu*TZp1@q)M-l#0{KpARx>k|_swQsL<{*f{9t%GqWyBWWrhTMA(cGzYKt%< zyN&#_KD;!oMfUevc>FUZn&Kup6{^U>iK-Q~qr23TnFaOr{(H8^yGAj@l$6_Z{+AAxBnA8lUKXJ&_iZZlkW5+CY#6j- zd%x+On|vwVTM5Rf63mN#mwQpt;eh^huk&UIlGmbymi7~qj_cZFx2`GMsrnjrqSv@C zNe57;W$y75Sj9h3Rn^~|mp08R+#ri6^<--FQ}{L?%-*GMvAer_|MjmTh+2=C7{OcbcDz4%uV% z-}@3rs^+mXTeZ4s2_)3?n)tr0W!Jq@G_0@pOit6uUtd24>g0o$;mqVnnzgs1bgAtQ zwJB`&^rxzT;(YosB$Qpi`g9;mTsv>=xm`384MCO+m^pD*MNdU#Fc|Z;oa;eorv@fR ziTS^_v9&j%C*!>$F+TSXrY}5OqicoV*S^Q?eCosGb+7Q}2$PHl=2N;@xPB@pl|}WK zYiqSXu*z)S)UX8)=h`Jvi;G!m3M8;Spi|9GJ&sGhMK`R%$mlUX>jWnDK9ToRwC2W# zD{fP(^+k`4>|?UB`cqiLRrFOJ7X+ez3YIU1RlKTU)USm_3)x9u5AE%Ja8lN2H~!Ih zT7oBq*J@uU3Hn{wgnM*;NtHpbo zBZz*TM(Mti3NQP%!T*Fy{d_i&mDb%ZDq6W z{zAyytl`^?1Qt`Iq9qxrOPQWFm#{lrPhHHH|1B8shG%Ty(_TzeO`P082OMOF>*CV; zsukvuFAddZcs{77KfLO!O_p|cP;~WpF|ZG1EbZ+*wYB5;v_>e-sa-yan;TA1CqigA z;r%ERIz*Cm;}+>JbBiNV^EPiMH!r=Pd|g6MflEtqO$d&D5fvHvR97a+msO_N@RUyX zB?&3TtROQp@yH$aAsH>#+0n=dGDvGo7W|H(6g*7DfL$H+CcX!;k#$SpT_K@#8{8@F zmuE*%i4TjGdq+o5=1%H6BpT4j(^5ZuRJr-n! zc3pEl`7l+jw+7j-MdITNqvPzb4uEmxl*Fv*2j|B+O6l5}_tJthF$mD4WLj_c$72J7 zPSet=zb#xSN&mox;h8!#-WmlsXLZn#dzcs@urNwXAkt#Ll8lG*H7r4kaELzaK`Po^lc~6c47RS~5S+jAm88;4J6;Cxe zOG`%uz-6_R3#jcrk!2mNW;73XbVv8k&QbvNg1vU#E9=vxpyRQBMti^K><7VQf0Oe9 zo&NgHPEZxQ4OnAzB6IY|GP@pMdArXLs9n7L-L`_jFiBeL#*n-S!-y^AuQh|UPlDb# z3HkZzs1Se)dYEryl4-k#ZVd(@k<>a}`j|X_$@nAh_e+h5g?+fT%hJnpdxs>*>s3un zfHT>>6K;gbiPPuN-s9NXYH)4X>Jogj`dM)H(^--|iggB^z=p`gM!5+!aAPVD6F+2~ zWbnT6_l3++}XIa+u7V9Fjo ztj@k`g@w|bkwF_dav~W)ZBZ84=q*ld7k>C0>_miy*zpc!z56EfQQf$p1Q$QTWRJd_ zEapc|FOE6~eZ?VK@lLyfYZepg4&v@yurc@^-dH0BZ2S&6<3|+UVkROkACF1@%b$mA zt@cupTPxBXy>kTC(_{FrtE#}{Y~*)wOL~DFxhe~u-`B9dO!6380+h6RwDn|*|`rYd|4h8>H<=8 zt~~A2yMPu&g{Gg5MqFbp&EKocHVfhFC;JESw8%hje>hiSCNGc3e%I^Gs?3mwRuoTeaQibrycYY3*|^bP0b=YIxb)BUd_xNaop zPp|f8pxrob@%>@)t{C{Wf(LGkogsL%r^=b6BYDBt!tn_SZWUg|hk|9#huyGIy_h;1 z6-U9&VgScx+MG9{_{uMl+kK7ZDB&9ZNDatNIZjpUI6AiXCL%QQSqd)R*a>Fvyirt+ zy~8{sY&&+XHhzA4=It;v^Ca7Ujz&W)6sLmct{oxe`CP5TcZ*}q)KZu=sgI8yo!=P; zIb>~p*uBp2G10ACvz11?RSge{%m+%j$ps^nWlxW`KbUUZ(PqbcI+7pQa$@SZJ7>u2 zNNC(synL{sRJ}wbQ!w7N7!}^=S_J*N-ms=C;^~Z@wtkCq;$>FAbYP%2n7|~L?z*G@ zGCF!?Eqk!ZnOcNvEc?)C;^=!c8FwbQ{f!)sv+t0QeLKC3S@Fvdn4(948oW-3YaIun z!QUhTp~K;`a^8`msE;wzex^#c`!saU#TqbvFUY*BbAS3xMbyF<_W@~35QKsr|L(|b zqLl_G9Z5I15E~4pB>Ok#iJ-Xcm$ z{LU1TmVG(Z>~llZ04xmUr5oiY1+-ci}nSGhhme%v9fp^_!P4Fssc)K((cMgT;t<={iVs1 z<1!o`_Wl{Z!P)uG)J-+9A?iDKaBP+Afx1TfbloFqiDqvv8?Vc1t6`K;cxK{l+#kz{ z@n_IfUPpV6BYT{|@K~z%G@mrp3G)k@n;mK_H3=B70-*_%m3%ZqgM)9SFv%Z1x;-@A zC}&+P!f9sK(a|2*=_u<;LxWZmst^Trij%H>fI`&Ci#Gh`{9YBAO=C!)I`q%_-nvIb?5s-J9BF_PUVw^Kz^;|UJWY^%j<@;{Evc=4*OwxeIc9vHBf7V51^ET0 z!PROytA4+~v@y~iwdm2FY;hh*%}frT5dAQ)9DrQn?qz0~=f}gYv)0YG&Z#r-U824E zw$$q5f(7-nF2v3_uQ=GVU}8S_vflblUh73*4ndsP!Mea3X)^bnvwNfWoXsEmDp2!PeEeZZwy z$2@HRYSOcw3=Ari8^^?J6?PLi>>2a^*}-z{ky$UZ~oH1d76-1;xQcE{mGH0QZfWHl4f`!6v;+`Se2*@=od~h^M?V-reeF{?=x%j> zSdEK|yLyQyD;FNP8zaHDegpTVc^VSZ=l=eF=Nh~7HK)sql|0L9CZpvQ89CD%qcUOe zFr=bJcOR3VN39d9ZC#T=B00b3VbkcKRY^rx9+cMs;Y$jiZNzRb(Yx5@IkYx|+His>`cTakOq@qNmy4 zJS+EBSy{+H&Jg}K!l5LfwP~;Aai8b1=9yu&J4&v34; z^gj)~JwxG(*+PS!h{lWRCueTXSOOa@9LXdXV(4=^3=Jr2PbFdK+zA6QmM-c*R-Xmi zX&LwKsf6y{1MpwP@$b`2ojant+|{(LRDP|Ys#;#gzoA1)ar8V^_q#Im`8bUwBE|0N zYR`^!B5dbW__3jYzcB8GVRMu7g9-1{uoqH=HzC&pMC0=C;j+wIERa-ISu^IvxOce$ z9NItB?$|U<_@CSLcZO3Jqulog9$#BKY8DRSOJ|L#^}5VM?vQfLVts2m>s!_}h%m3& zt46ezUpSGJDHHBN42k~rT}l?WjQaMztx(nnn{X*Q_G`$=34BCV)bXf2;uN9T4_8mm z1&58ogry-C5|qWwj>i0GzRR<+2N5zf!DaCPX;O6GA`%`}Nl2m*$5mfyf1o#TN+zMn ztbXU;VVN&OeqM;_++@k(q6V;)RA4Km#Q;lNsQos$Ut!ufIDpy5BumZhI>#V5v+KAD z&iwVX)Wt?fY%TKVBg#`b%nNfLa^Qlwo?uv^UaPQfg^n|$L(JfE0)66-0t@rbI0&Z! zyuX3^3IzY&#`a(F60+H=(%>&e_kgJ5!=$KaY?%iFzg zN@$Y7kB{e%-`JP|Q5gkdG%Ut;DtgVKkrq35P>XAy`cI%fn6H9!<5`y1(#iE+%?xvOd&%zP>nDLJHiUL*-gR#;X~cYSa}V+i04 z$Iqt`=M{$o(D3R%*P*o9u9S!R9vSp2=AO;?=`PnWI*-aT*U=nZjX2VRVQVnU<==Rn z))tyt`tTNCoV%n@f*`k$YHvne6Ve%J0=PQAu zwX;Zo&}h;oTQZ`fTo;4<#+{iN@bq$kHh!MCdAPmyxje6%VzAUl1==$*WCVBz@(2<#dx08v%0z-{uLUA1YFCQBj=iuThs~Ntu{oF|JLj4ft3O`p!_5~Km*4L>5Z;Jl!(1%8o zjGjhA@ z9`9uNoxg$J17vMzC?;q89oBwzyF5N|&Z-0zu{i1S1b|${UWX}RkrThN{q+89?`Zq; z(7i`Hgej?I;8k*(W094Q*xTRuIFLt;1zKd-8X)4lV9rc_FH}MLQW($SlaDT<3 z$!%ynVik-p2F|)+*rJ-IRUewbZ8KU$6#Fbf!aTyl^cNbWco}FpK!NSB^kpb8aogga zohIo429D3+x36QpN)@VNzL;$K0|)qP%e@l9Kgcr{B zNr8C*xMb;i-4xSo>8Sg>|FH|7F55;4DswbtL`MO+!LW=@li9MlOem`Wkf;qfaUw&6wpBs##3+|myU{>^exQH z5ZJF^bTmKy$Ar<1!~~i--MKQ90_jyu@far1mWIS8XD0`<$6Je66y<~~xyBPwU zxiAJ3Eycx`q;$TivEnZ@Ic5u>)H^%(0Sy@*(D> zfgl(r`eFrc@h-{Kw64Sv%)!a2&+L70$SD}{#C(t*Sit@4xdOj4BWl1EZ*AGbGSP7TqNA==HU8z;f8nWnjho>FofKcw*5(3Z9@JBC zttaetDFYv)R&35CsS2=NE`C_y`8Z3` z{e9Iwl;phc7_e<6>AdvEm>L2SBK)r1Ny!eOnVI#Qn$Qkz|9}5hm0Bz-B;+5^KjuEdfW+ZJf7Zac49XYk0XNJaqg5WWeduWyhnwxcfFzn-wvQN_E2xFB8GE#qMMW+TKoBT&`uf z0buE$@BSZ{Z0dF?>~QJo1U~GL&_xq5`>=jPzTTLTks+of`|E~aMvs*wl0zhp>g)Ls z+-^uz6e+SsoG!r$5;q_J6c}IoUHAbwj0zQ-0qhbO%`o~Or=1)YV{AM*^+C;lQs@4Z zc2)HR=R$5u?b@lM27NCY>k4+zz%F)05gB+tUF~Z_hgKf2ektu{z!{fctz+ zHLA^HJ-VPPsu$4G(qqYsdgD$ot{k^ZVIcLNs4UNRqhhPX$e&fxVKMKCR3t<5zI0`& z+aFpL_OiS95)<|ZpBLW;a2nq(3$eUz^ZoUB*;tC3lYop*S`~mpr73d}X;Anx zMPCYK3DoVm=H;wMr;UvQhE3Y8%-2uYfjf1@Qo2-g{k?^M!K@b%49vIJ9{fAV>6m-Gs`Y0?Ekjs40wPS z3aLlVl{%|{8hz|5ASf{1e0edmrxJfT>skT8^k=}2wgA55@?uxoAUXmb#v$ydKluE4 z{G@6%tya5wDEThm42l*2!&UWlu!yH$Nm( zR>RRd+CVjOW4)d)E;nB$sjy!9AZN8DO(^|;sYDP?&IGM@@idG{nL>KWh+I=jxF zYLy)-#r4Mz%*4~$u)s=n36j?;>Q0NfeMaR(B!xfvUkYL;*S{4sc}7b4E6_v*c2i}D z006%UT{!LkB6L5V{}-WKxqn6IHjMy-=OAn8q4NJ2@|Dlq?K8OgAhmV8dF4@bm6fs1^BVfp#Ch_^WX3^2JA?L~ZT4azp9Ii&h?{*e*Nn^r$!H@el^7%qn%G=e$Ri#nYhyh+a7%T-Sy529 z`zgH`W6wHmtr1YaGdHk;>@a1hF3Nzdrywh}4}9Q(Yl!WY0s`a9(udkEK_(wf)?%2R zo?S}58tWzi#OHKZlrqC@k;}WXgfG-yYj%pkjTvrod@LwH2ML98e5@O&FAdM})sUv6 zEb?#xieVA5_@L5qhSk3?R;VxoFihw3KRADAea>@ln}?l<%XQV-^EIgX;A1oVxOTAu;Pbo3R+n~GlBc0m zEym%1bp8^ylmNJtXJ%yN3ATQ$*rCK0ILEb*&te813K$MLUO~vVgLSz=Ng#s zut!gJeO?%80np?Btyk8^X9hSBQ1^%;lyljf6BgFCMU6pAhpq1`i+UkWc=`?vC$H>5 z(S=b;2waro z|C9@tKt4Zf(tG`??V1?l+>na@lv5y=jK`cL(QE(9hc5#QsPgy}v9OUl**Uba(tbtj zxehmgR)X&`=XJpGKGCb!RFreb4ZtBX=eZ55W#@5pnw_5|2}J}%)zzj`8Fa>g5`G}2 zLUx9P=Lzbo!XP_F0Jy0pG7#Il6PtN>AZFn9^=a7H)ChRE1uKeM8qVFT-F_%9Pw1bx zcJ`xbb{2(0;JTJrHP|Z^5CyxISj;SDB?&Q?!ZvmWPu)?aLkDJCjZpl_YLe0glv*L_ zzo}`E<%!v)lSV3e=R~~ZoZA$sTfaPo~$}lWR9WysTq5VZP9M;Hv_(@ zC?Z>ya9+@vOHbzurI^*TF9fVNsB}y4BQS3zAMq0O;knUu$MB;J6&kkpr@lUeRLEjS zXAV1;!D;B#wz0=i(m~M~ungeVijGZAUweWAp9L9kgugY7+cOY`r0I5jSrs4ojj}H5 ziwY#$Zgx@MyMI)E4GVqU(b2Jct}czo0kopk1@K0-Qu*Ht?4|R}-g_h@^jXluEjpIU z3e+C3*6Y?gfWAm%WKj#%P+}?Bvl&G<$3jLHMqB8|7 zxW1OCnW$z}_}BT?_gR9$O%(|V*x;RDV2G)E{o2{X5moB~WciXc#9CSm)JrW`2r3Z8 zW|MYDN40{F?r=5MZ7n6@Pot$8Uy$?im_@F5j*gTTWGC@)T_yZAh5av3URb?u!KmgR z@j{k~#c2->a|FXu#9JXFB8qBa2$vN2*M-WN|B8#O70kw_81@-28U^PK1hl{O&FO2| z85)MJ^(%`_vRA6pxpwkTrHJWvYK%PA{h}C&Ipd~Ut16V_5cx>$$X=so@y>c0bfcJ= zn%@*I;grAH&(69hr^Zu_-`k>nVZd)arPf_~nQ$#)DL}Aa^ z4~k*zAmWKkiViveaWwq)?VljjqGO18)*vto9)5rGd}9nbVQPX z$2Gr!ff9%z(F*aV0U)T#@$=U5GE)c(4b3>6g8WEigrrs*iAdK8@HkFvxFB6>nzaUH?o8mh1=j<=Ps9cNH(HfX zl}vzes{ZR!iHO`T{qX1{LGsdJMmQsG52;VRBn8wZ)4F~Uo!^{zM7{R;(a*f(qwTE0 ztUivrcAcCz5vSm~CZ2L%A!B7>!4xkJ+I-%nUo_p-6Nyq$h!m^#i~2$ z>D7>$R1le*^Bw90#(d>i%ZS^^{1Co0J~bDf#; zdes#|%z!RbO)&os|fN;!pp#c`7*7(<1ecC(v z@`t6P$p+HyqDeeyy2<`drhK{WsRSROL6|#n@iB=N?}6(1X{r43)nBQaQvjZMcv7VK1@fCm=;w7ljIgu;-Z{J$U@ zqS_fI86O%NsjGb-?Gs9oQ7vl{+Z9#HAll)!bJnCwEBmp(e`l6SlI%@d8n-xeH9fCm zl+S+Gnzjb?7J_a~cv|Oo{1TFWV;YUWLYEsTe37Gbx4*>Kh^wgJM%*j+ugfn|SjxzG zSe}Szs@ZYjbK#!q7`|+OGh`1EslvipQ#uC}6Nb&F^iJ1n#)<|Nwpc<$;XQL8unQ>kbaoRc-G`59`GA{qakg&r+BX$Wg@UeZ6C0bhTSe?N z=N-64uR6EuK|rU+1swmezZQM$*L*_>H^x{b*%{uer9pqN`vq5D}DVt9bUSmISGU#o}i&FZIg5<_PV zJCtxxvv)`46hzkPY1|_koS@#X(nIiy&lS@|biGv?wK^`nZ><67LHGL@`f0QQeJSjP z?^vV8P#pCI5F{okx{l9C*XguA4dWQwT-kS|Al?EcN1cmxz-M8xt{O-{A(IVaws(Cg>elO5j zfE_gYrL8jlKRw88fx!QO5f+i>;JE@6452H`K1bqp1jp37-dd~?nwO=;jH{vgak7|p z$>ulnNd`wH;JCFtv@I7>)40HtdokC+4n=k}z-50n4(x?2F;Fs}1Y zANt=A;QtFr41+Kpgh4uAx=XfwQUT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/caching/etc/caching.urm.puml b/caching/etc/caching.urm.puml deleted file mode 100644 index 6ac3fd4cc136..000000000000 --- a/caching/etc/caching.urm.puml +++ /dev/null @@ -1,110 +0,0 @@ -@startuml -package com.iluwatar.caching { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - + useCacheAsideStategy() - + useReadAndWriteThroughStrategy() - + useReadThroughAndWriteAroundStrategy() - + useReadThroughAndWriteBehindStrategy() - } - class AppManager { - - cachingPolicy : CachingPolicy {static} - - AppManager() - + find(userId : String) : UserAccount {static} - - findAside(userId : String) : UserAccount {static} - + initCacheCapacity(capacity : int) {static} - + initCachingPolicy(policy : CachingPolicy) {static} - + initDb(useMongoDb : boolean) {static} - + printCacheContent() : String {static} - + save(userAccount : UserAccount) {static} - - saveAside(userAccount : UserAccount) {static} - } - class CacheStore { - - LOGGER : Logger {static} - ~ cache : LruCache {static} - - CacheStore() - + clearCache() {static} - + flushCache() {static} - + get(userId : String) : UserAccount {static} - + initCapacity(capacity : int) {static} - + invalidate(userId : String) {static} - + print() : String {static} - + readThrough(userId : String) : UserAccount {static} - + readThroughWithWriteBackPolicy(userId : String) : UserAccount {static} - + set(userId : String, userAccount : UserAccount) {static} - + writeAround(userAccount : UserAccount) {static} - + writeBehind(userAccount : UserAccount) {static} - + writeThrough(userAccount : UserAccount) {static} - } - enum CachingPolicy { - + AROUND {static} - + ASIDE {static} - + BEHIND {static} - + THROUGH {static} - - policy : String - + getPolicy() : String - + valueOf(name : String) : CachingPolicy {static} - + values() : CachingPolicy[] {static} - } - class DbManager { - - db : MongoDatabase {static} - - mongoClient : MongoClient {static} - - useMongoDB : boolean {static} - - virtualDB : Map {static} - - DbManager() - + connect() {static} - + createVirtualDb() {static} - + readFromDb(userId : String) : UserAccount {static} - + updateDb(userAccount : UserAccount) {static} - + upsertDb(userAccount : UserAccount) {static} - + writeToDb(userAccount : UserAccount) {static} - } - class LruCache { - - LOGGER : Logger {static} - ~ cache : Map - ~ capacity : int - ~ end : Node - ~ head : Node - + LruCache(capacity : int) - + clear() - + contains(userId : String) : boolean - + get(userId : String) : UserAccount - + getCacheDataInListForm() : List - + getLruData() : UserAccount - + invalidate(userId : String) - + isFull() : boolean - + remove(node : Node) - + set(userId : String, userAccount : UserAccount) - + setCapacity(newCapacity : int) - + setHead(node : Node) - } - ~class Node { - ~ next : Node - ~ previous : Node - ~ userAccount : UserAccount - ~ userId : String - + Node(this$0 : String, userId : UserAccount) - } - class UserAccount { - - additionalInfo : String - - userId : String - - userName : String - + UserAccount(userId : String, userName : String, additionalInfo : String) - + getAdditionalInfo() : String - + getUserId() : String - + getUserName() : String - + setAdditionalInfo(additionalInfo : String) - + setUserId(userId : String) - + setUserName(userName : String) - + toString() : String - } -} -LruCache --> "-head" Node -Node --+ LruCache -Node --> "-previous" Node -AppManager --> "-cachingPolicy" CachingPolicy -Node --> "-userAccount" UserAccount -CacheStore --> "-cache" LruCache -@enduml \ No newline at end of file diff --git a/caching/pom.xml b/caching/pom.xml deleted file mode 100644 index cd17845392d9..000000000000 --- a/caching/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - caching - - - junit - junit - test - - - org.mongodb - mongodb-driver - 3.0.4 - - - org.mongodb - mongodb-driver-core - 3.0.4 - - - org.mongodb - bson - 3.0.4 - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.19 - - false - - - - - diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java deleted file mode 100644 index 589b262453e8..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ /dev/null @@ -1,169 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * the resources immediately after their use. The resources retain their identity, are kept in some - * fast-access storage, and are re-used to avoid having to acquire them again. There are four main - * caching strategies/techniques in this pattern; each with their own pros and cons. They are; - * write-through which writes data to the cache and DB in a single transaction, - * write-around which writes data immediately into the DB instead of the cache, - * write-behind which writes data into the cache initially whilst the data is only - * written into the DB when the cache is full, and cache-aside which pushes the - * responsibility of keeping the data synchronized in both data sources to the application itself. - * The read-through strategy is also included in the mentioned four strategies -- - * returns data from the cache to the caller if it exists else queries from DB and - * stores it into the cache for future use. These strategies determine when the data in the cache - * should be written back to the backing store (i.e. Database) and help keep both data sources - * synchronized/up-to-date. This pattern can improve performance and also helps to maintain - * consistency between data held in the cache and the data in the underlying data store. - *

- * In this example, the user account ({@link UserAccount}) entity is used as the underlying - * application data. The cache itself is implemented as an internal (Java) data structure. It adopts - * a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The four - * strategies are individually tested. The testing of the cache is restricted towards saving and - * querying of user accounts from the underlying data store ( {@link DbManager}). The main class ( - * {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and - * whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager - * ({@link AppManager}) handles the transaction of data to-and-from the underlying data store - * (depending on the preferred caching policy/strategy). - * - * App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager - *

- * - * @see CacheStore - * @See LRUCache - * @see CachingPolicy - * - */ -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) { - AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests - // and the App class to avoid Maven compilation errors. Set flag to - // true to run the tests with MongoDB (provided that MongoDB is - // installed and socket connection is open). - AppManager.initCacheCapacity(3); - App app = new App(); - app.useReadAndWriteThroughStrategy(); - app.useReadThroughAndWriteAroundStrategy(); - app.useReadThroughAndWriteBehindStrategy(); - app.useCacheAsideStategy(); - } - - /** - * Read-through and write-through - */ - public void useReadAndWriteThroughStrategy() { - LOGGER.info("# CachingPolicy.THROUGH"); - AppManager.initCachingPolicy(CachingPolicy.THROUGH); - - UserAccount userAccount1 = new UserAccount("001", "John", "He is a boy."); - - AppManager.save(userAccount1); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("001"); - AppManager.find("001"); - } - - /** - * Read-through and write-around - */ - public void useReadThroughAndWriteAroundStrategy() { - LOGGER.info("# CachingPolicy.AROUND"); - AppManager.initCachingPolicy(CachingPolicy.AROUND); - - UserAccount userAccount2 = new UserAccount("002", "Jane", "She is a girl."); - - AppManager.save(userAccount2); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("002"); - LOGGER.info(AppManager.printCacheContent()); - userAccount2 = AppManager.find("002"); - userAccount2.setUserName("Jane G."); - AppManager.save(userAccount2); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("002"); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("002"); - } - - /** - * Read-through and write-behind - */ - public void useReadThroughAndWriteBehindStrategy() { - LOGGER.info("# CachingPolicy.BEHIND"); - AppManager.initCachingPolicy(CachingPolicy.BEHIND); - - UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food."); - UserAccount userAccount4 = new UserAccount("004", "Rita", "She hates cats."); - UserAccount userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard."); - - AppManager.save(userAccount3); - AppManager.save(userAccount4); - AppManager.save(userAccount5); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("003"); - LOGGER.info(AppManager.printCacheContent()); - UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child."); - AppManager.save(userAccount6); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("004"); - LOGGER.info(AppManager.printCacheContent()); - } - - /** - * Cache-Aside - */ - public void useCacheAsideStategy() { - LOGGER.info("# CachingPolicy.ASIDE"); - AppManager.initCachingPolicy(CachingPolicy.ASIDE); - LOGGER.info(AppManager.printCacheContent()); - - UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food."); - UserAccount userAccount4 = new UserAccount("004", "Rita", "She hates cats."); - UserAccount userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard."); - AppManager.save(userAccount3); - AppManager.save(userAccount4); - AppManager.save(userAccount5); - - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("003"); - LOGGER.info(AppManager.printCacheContent()); - AppManager.find("004"); - LOGGER.info(AppManager.printCacheContent()); - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/AppManager.java b/caching/src/main/java/com/iluwatar/caching/AppManager.java deleted file mode 100644 index 2acc1accd17d..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/AppManager.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import java.text.ParseException; - -/** - * - * AppManager helps to bridge the gap in communication between the main class and the application's - * back-end. DB connection is initialized through this class. The chosen caching strategy/policy is - * also initialized here. Before the cache can be used, the size of the cache has to be set. - * Depending on the chosen caching policy, AppManager will call the appropriate function in the - * CacheStore class. - * - */ -public final class AppManager { - - private static CachingPolicy cachingPolicy; - - private AppManager() { - } - - /** - * - * Developer/Tester is able to choose whether the application should use MongoDB as its underlying - * data storage or a simple Java data structure to (temporarily) store the data/objects during - * runtime. - */ - public static void initDb(boolean useMongoDb) { - if (useMongoDb) { - try { - DbManager.connect(); - } catch (ParseException e) { - e.printStackTrace(); - } - } else { - DbManager.createVirtualDb(); - } - } - - /** - * Initialize caching policy - */ - public static void initCachingPolicy(CachingPolicy policy) { - cachingPolicy = policy; - if (cachingPolicy == CachingPolicy.BEHIND) { - Runtime.getRuntime().addShutdownHook(new Thread(CacheStore::flushCache)); - } - CacheStore.clearCache(); - } - - public static void initCacheCapacity(int capacity) { - CacheStore.initCapacity(capacity); - } - - /** - * Find user account - */ - public static UserAccount find(String userId) { - if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) { - return CacheStore.readThrough(userId); - } else if (cachingPolicy == CachingPolicy.BEHIND) { - return CacheStore.readThroughWithWriteBackPolicy(userId); - } else if (cachingPolicy == CachingPolicy.ASIDE) { - return findAside(userId); - } - return null; - } - - /** - * Save user account - */ - public static void save(UserAccount userAccount) { - if (cachingPolicy == CachingPolicy.THROUGH) { - CacheStore.writeThrough(userAccount); - } else if (cachingPolicy == CachingPolicy.AROUND) { - CacheStore.writeAround(userAccount); - } else if (cachingPolicy == CachingPolicy.BEHIND) { - CacheStore.writeBehind(userAccount); - } else if (cachingPolicy == CachingPolicy.ASIDE) { - saveAside(userAccount); - } - } - - public static String printCacheContent() { - return CacheStore.print(); - } - - /** - * Cache-Aside save user account helper - */ - private static void saveAside(UserAccount userAccount) { - DbManager.updateDb(userAccount); - CacheStore.invalidate(userAccount.getUserId()); - } - - /** - * Cache-Aside find user account helper - */ - private static UserAccount findAside(String userId) { - UserAccount userAccount = CacheStore.get(userId); - if (userAccount != null) { - return userAccount; - } - - userAccount = DbManager.readFromDb(userId); - if (userAccount != null) { - CacheStore.set(userId, userAccount); - } - - return userAccount; - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/CacheStore.java b/caching/src/main/java/com/iluwatar/caching/CacheStore.java deleted file mode 100644 index f22a731b4880..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/CacheStore.java +++ /dev/null @@ -1,182 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * - * The caching strategies are implemented in this class. - * - */ -public class CacheStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(CacheStore.class); - - static LruCache cache; - - private CacheStore() { - } - - /** - * Init cache capacity - */ - public static void initCapacity(int capacity) { - if (cache == null) { - cache = new LruCache(capacity); - } else { - cache.setCapacity(capacity); - } - } - - /** - * Get user account using read-through cache - */ - public static UserAccount readThrough(String userId) { - if (cache.contains(userId)) { - LOGGER.info("# Cache Hit!"); - return cache.get(userId); - } - LOGGER.info("# Cache Miss!"); - UserAccount userAccount = DbManager.readFromDb(userId); - cache.set(userId, userAccount); - return userAccount; - } - - /** - * Get user account using write-through cache - */ - public static void writeThrough(UserAccount userAccount) { - if (cache.contains(userAccount.getUserId())) { - DbManager.updateDb(userAccount); - } else { - DbManager.writeToDb(userAccount); - } - cache.set(userAccount.getUserId(), userAccount); - } - - /** - * Get user account using write-around cache - */ - public static void writeAround(UserAccount userAccount) { - if (cache.contains(userAccount.getUserId())) { - DbManager.updateDb(userAccount); - cache.invalidate(userAccount.getUserId()); // Cache data has been updated -- remove older - // version from cache. - } else { - DbManager.writeToDb(userAccount); - } - } - - /** - * Get user account using read-through cache with write-back policy - */ - public static UserAccount readThroughWithWriteBackPolicy(String userId) { - if (cache.contains(userId)) { - LOGGER.info("# Cache Hit!"); - return cache.get(userId); - } - LOGGER.info("# Cache Miss!"); - UserAccount userAccount = DbManager.readFromDb(userId); - if (cache.isFull()) { - LOGGER.info("# Cache is FULL! Writing LRU data to DB..."); - UserAccount toBeWrittenToDb = cache.getLruData(); - DbManager.upsertDb(toBeWrittenToDb); - } - cache.set(userId, userAccount); - return userAccount; - } - - /** - * Set user account - */ - public static void writeBehind(UserAccount userAccount) { - if (cache.isFull() && !cache.contains(userAccount.getUserId())) { - LOGGER.info("# Cache is FULL! Writing LRU data to DB..."); - UserAccount toBeWrittenToDb = cache.getLruData(); - DbManager.upsertDb(toBeWrittenToDb); - } - cache.set(userAccount.getUserId(), userAccount); - } - - /** - * Clears cache - */ - public static void clearCache() { - if (cache != null) { - cache.clear(); - } - } - - /** - * Writes remaining content in the cache into the DB. - */ - public static void flushCache() { - LOGGER.info("# flushCache..."); - if (null == cache) { - return; - } - List listOfUserAccounts = cache.getCacheDataInListForm(); - for (UserAccount userAccount : listOfUserAccounts) { - DbManager.upsertDb(userAccount); - } - } - - /** - * Print user accounts - */ - public static String print() { - List listOfUserAccounts = cache.getCacheDataInListForm(); - StringBuilder sb = new StringBuilder(); - sb.append("\n--CACHE CONTENT--\n"); - for (UserAccount userAccount : listOfUserAccounts) { - sb.append(userAccount.toString() + "\n"); - } - sb.append("----\n"); - return sb.toString(); - } - - /** - * Delegate to backing cache store - */ - public static UserAccount get(String userId) { - return cache.get(userId); - } - - /** - * Delegate to backing cache store - */ - public static void set(String userId, UserAccount userAccount) { - cache.set(userId, userAccount); - } - - /** - * Delegate to backing cache store - */ - public static void invalidate(String userId) { - cache.invalidate(userId); - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java b/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java deleted file mode 100644 index 9f7c92b2eef5..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -/** - * - * Enum class containing the four caching strategies implemented in the pattern. - * - */ -public enum CachingPolicy { - THROUGH("through"), AROUND("around"), BEHIND("behind"), ASIDE("aside"); - - private String policy; - - private CachingPolicy(String policy) { - this.policy = policy; - } - - public String getPolicy() { - return policy; - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/DbManager.java b/caching/src/main/java/com/iluwatar/caching/DbManager.java deleted file mode 100644 index 6fccaf43e5ff..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/DbManager.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import java.text.ParseException; -import java.util.HashMap; -import java.util.Map; - -import org.bson.Document; - -import com.mongodb.MongoClient; -import com.mongodb.client.FindIterable; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.UpdateOptions; - -/** - * - *

DBManager handles the communication with the underlying data store i.e. Database. It contains the - * implemented methods for querying, inserting, and updating data. MongoDB was used as the database - * for the application.

- * - *

Developer/Tester is able to choose whether the application should use MongoDB as its underlying - * data storage (connect()) or a simple Java data structure to (temporarily) store the data/objects - * during runtime (createVirtualDB()).

- * - */ -public final class DbManager { - - private static MongoClient mongoClient; - private static MongoDatabase db; - private static boolean useMongoDB; - - private static Map virtualDB; - - private DbManager() { - } - - /** - * Create DB - */ - public static void createVirtualDb() { - useMongoDB = false; - virtualDB = new HashMap<>(); - } - - /** - * Connect to DB - */ - public static void connect() throws ParseException { - useMongoDB = true; - mongoClient = new MongoClient(); - db = mongoClient.getDatabase("test"); - } - - /** - * Read user account from DB - */ - public static UserAccount readFromDb(String userId) { - if (!useMongoDB) { - if (virtualDB.containsKey(userId)) { - return virtualDB.get(userId); - } - return null; - } - if (db == null) { - try { - connect(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - FindIterable iterable = - db.getCollection("user_accounts").find(new Document("userID", userId)); - if (iterable == null) { - return null; - } - Document doc = iterable.first(); - return new UserAccount(userId, doc.getString("userName"), doc.getString("additionalInfo")); - } - - /** - * Write user account to DB - */ - public static void writeToDb(UserAccount userAccount) { - if (!useMongoDB) { - virtualDB.put(userAccount.getUserId(), userAccount); - return; - } - if (db == null) { - try { - connect(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - db.getCollection("user_accounts").insertOne( - new Document("userID", userAccount.getUserId()).append("userName", - userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())); - } - - /** - * Update DB - */ - public static void updateDb(UserAccount userAccount) { - if (!useMongoDB) { - virtualDB.put(userAccount.getUserId(), userAccount); - return; - } - if (db == null) { - try { - connect(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - db.getCollection("user_accounts").updateOne( - new Document("userID", userAccount.getUserId()), - new Document("$set", new Document("userName", userAccount.getUserName()).append( - "additionalInfo", userAccount.getAdditionalInfo()))); - } - - /** - * - * Insert data into DB if it does not exist. Else, update it. - */ - public static void upsertDb(UserAccount userAccount) { - if (!useMongoDB) { - virtualDB.put(userAccount.getUserId(), userAccount); - return; - } - if (db == null) { - try { - connect(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - db.getCollection("user_accounts").updateOne( - new Document("userID", userAccount.getUserId()), - new Document("$set", new Document("userID", userAccount.getUserId()).append("userName", - userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())), - new UpdateOptions().upsert(true)); - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/LruCache.java b/caching/src/main/java/com/iluwatar/caching/LruCache.java deleted file mode 100644 index fb9127bdc8b8..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/LruCache.java +++ /dev/null @@ -1,190 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - * Data structure/implementation of the application's cache. The data structure consists of a hash - * table attached with a doubly linked-list. The linked-list helps in capturing and maintaining the - * LRU data in the cache. When a data is queried (from the cache), added (to the cache), or updated, - * the data is moved to the front of the list to depict itself as the most-recently-used data. The - * LRU data is always at the end of the list. - * - */ -public class LruCache { - - private static final Logger LOGGER = LoggerFactory.getLogger(LruCache.class); - - class Node { - String userId; - UserAccount userAccount; - Node previous; - Node next; - - public Node(String userId, UserAccount userAccount) { - this.userId = userId; - this.userAccount = userAccount; - } - } - - int capacity; - Map cache = new HashMap<>(); - Node head; - Node end; - - public LruCache(int capacity) { - this.capacity = capacity; - } - - /** - * Get user account - */ - public UserAccount get(String userId) { - if (cache.containsKey(userId)) { - Node node = cache.get(userId); - remove(node); - setHead(node); - return node.userAccount; - } - return null; - } - - /** - * Remove node from linked list. - */ - public void remove(Node node) { - if (node.previous != null) { - node.previous.next = node.next; - } else { - head = node.next; - } - if (node.next != null) { - node.next.previous = node.previous; - } else { - end = node.previous; - } - } - - /** - * Move node to the front of the list. - */ - public void setHead(Node node) { - node.next = head; - node.previous = null; - if (head != null) { - head.previous = node; - } - head = node; - if (end == null) { - end = head; - } - } - - /** - * Set user account - */ - public void set(String userId, UserAccount userAccount) { - if (cache.containsKey(userId)) { - Node old = cache.get(userId); - old.userAccount = userAccount; - remove(old); - setHead(old); - } else { - Node newNode = new Node(userId, userAccount); - if (cache.size() >= capacity) { - LOGGER.info("# Cache is FULL! Removing {} from cache...", end.userId); - cache.remove(end.userId); // remove LRU data from cache. - remove(end); - setHead(newNode); - } else { - setHead(newNode); - } - cache.put(userId, newNode); - } - } - - public boolean contains(String userId) { - return cache.containsKey(userId); - } - - /** - * Invalidate cache for user - */ - public void invalidate(String userId) { - Node toBeRemoved = cache.remove(userId); - if (toBeRemoved != null) { - LOGGER.info("# {} has been updated! Removing older version from cache...", userId); - remove(toBeRemoved); - } - } - - public boolean isFull() { - return cache.size() >= capacity; - } - - public UserAccount getLruData() { - return end.userAccount; - } - - /** - * Clear cache - */ - public void clear() { - head = null; - end = null; - cache.clear(); - } - - /** - * Returns cache data in list form. - */ - public List getCacheDataInListForm() { - List listOfCacheData = new ArrayList<>(); - Node temp = head; - while (temp != null) { - listOfCacheData.add(temp.userAccount); - temp = temp.next; - } - return listOfCacheData; - } - - /** - * Set cache capacity - */ - public void setCapacity(int newCapacity) { - if (capacity > newCapacity) { - clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll - // just clear the cache. - } else { - this.capacity = newCapacity; - } - } -} diff --git a/caching/src/main/java/com/iluwatar/caching/UserAccount.java b/caching/src/main/java/com/iluwatar/caching/UserAccount.java deleted file mode 100644 index 769eef6f6d2f..000000000000 --- a/caching/src/main/java/com/iluwatar/caching/UserAccount.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -/** - * Entity class (stored in cache and DB) used in the application. - */ -public class UserAccount { - private String userId; - private String userName; - private String additionalInfo; - - /** - * Constructor - */ - public UserAccount(String userId, String userName, String additionalInfo) { - this.userId = userId; - this.userName = userName; - this.additionalInfo = additionalInfo; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getAdditionalInfo() { - return additionalInfo; - } - - public void setAdditionalInfo(String additionalInfo) { - this.additionalInfo = additionalInfo; - } - - @Override - public String toString() { - return userId + ", " + userName + ", " + additionalInfo; - } -} diff --git a/caching/src/test/java/com/iluwatar/caching/AppTest.java b/caching/src/test/java/com/iluwatar/caching/AppTest.java deleted file mode 100644 index 3ac51303359d..000000000000 --- a/caching/src/test/java/com/iluwatar/caching/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Caching example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/caching/src/test/java/com/iluwatar/caching/CachingTest.java b/caching/src/test/java/com/iluwatar/caching/CachingTest.java deleted file mode 100644 index 4d8dea7a48a9..000000000000 --- a/caching/src/test/java/com/iluwatar/caching/CachingTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.caching; - -import org.junit.Before; -import org.junit.Test; - -/** - * - * Application test - * - */ -public class CachingTest { - App app; - - /** - * Setup of application test includes: initializing DB connection and cache size/capacity. - */ - @Before - public void setUp() { - AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests - // to avoid Maven compilation errors. Set flag to true to run the - // tests with MongoDB (provided that MongoDB is installed and socket - // connection is open). - AppManager.initCacheCapacity(3); - app = new App(); - } - - @Test - public void testReadAndWriteThroughStrategy() { - app.useReadAndWriteThroughStrategy(); - } - - @Test - public void testReadThroughAndWriteAroundStrategy() { - app.useReadThroughAndWriteAroundStrategy(); - } - - @Test - public void testReadThroughAndWriteBehindStrategy() { - app.useReadThroughAndWriteBehindStrategy(); - } - - @Test - public void testCacheAsideStrategy() { - app.useCacheAsideStategy(); - } -} diff --git a/callback/README.md b/callback/README.md deleted file mode 100644 index 278aa9b0aa5a..000000000000 --- a/callback/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Callback -folder: callback -permalink: /patterns/callback/ -pumlid: FSVB4S8m30N0Lg20M7UwUL4qYOciUFGXxSE9s-wp6sjjKgwF8tF6YyXnjxtdKMk5E5-MOjdu6jIrRYIStlXWsIJwRij4fhW53SGFn51TmIT9yZ-jVBHPGxy0 -categories: Other -tags: - - Java - - Difficulty-Beginner - - Functional - - Idiom ---- - -## Intent -Callback is a piece of executable code that is passed as an -argument to other code, which is expected to call back (execute) the argument -at some convenient time. - -![alt text](./etc/callback.png "Callback") - -## Applicability -Use the Callback pattern when - -* when some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity. - -## Real world examples - -* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept callback that will be triggered every time when barrier is tripped. diff --git a/callback/etc/callback.png b/callback/etc/callback.png deleted file mode 100644 index a81745871a642705dad3be5fe90fc7abacb7185c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8577 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 Peyvbb(N->dY!&ujDtTa# diff --git a/callback/etc/callback.ucls b/callback/etc/callback.ucls deleted file mode 100644 index ae3e7b23223a..000000000000 --- a/callback/etc/callback.ucls +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/callback/etc/callback.urm.puml b/callback/etc/callback.urm.puml deleted file mode 100644 index 02545e80f841..000000000000 --- a/callback/etc/callback.urm.puml +++ /dev/null @@ -1,28 +0,0 @@ -@startuml -package com.iluwatar.callback { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - interface Callback { - + call() {abstract} - } - class LambdasApp { - - LOGGER : Logger {static} - + LambdasApp() - + main(args : String[]) {static} - } - class SimpleTask { - - LOGGER : Logger {static} - + SimpleTask() - + execute() - } - abstract class Task { - + Task() - + execute() {abstract} - + executeWith(callback : Callback) - } -} -SimpleTask --|> Task -@enduml \ No newline at end of file diff --git a/callback/pom.xml b/callback/pom.xml deleted file mode 100644 index c87e58f63dce..000000000000 --- a/callback/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - callback - - - junit - junit - test - - - diff --git a/callback/src/main/java/com/iluwatar/callback/App.java b/callback/src/main/java/com/iluwatar/callback/App.java deleted file mode 100644 index 278975db9bae..000000000000 --- a/callback/src/main/java/com/iluwatar/callback/App.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * first-class citizens. Prior to Java 8 callbacks can be simulated using simple (alike command) - * interfaces. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - Task task = new SimpleTask(); - Callback callback = new Callback() { - @Override - public void call() { - LOGGER.info("I'm done now."); - } - }; - task.executeWith(callback); - } -} diff --git a/callback/src/main/java/com/iluwatar/callback/Callback.java b/callback/src/main/java/com/iluwatar/callback/Callback.java deleted file mode 100644 index 670d446c324e..000000000000 --- a/callback/src/main/java/com/iluwatar/callback/Callback.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.callback; - -/** - * - * Callback interface - * - */ -public interface Callback { - - void call(); -} diff --git a/callback/src/main/java/com/iluwatar/callback/LambdasApp.java b/callback/src/main/java/com/iluwatar/callback/LambdasApp.java deleted file mode 100644 index 57ab816f1445..000000000000 --- a/callback/src/main/java/com/iluwatar/callback/LambdasApp.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * defined as a Lambdas expression. - * - */ -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 = () -> 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 deleted file mode 100644 index 091699442b35..000000000000 --- a/callback/src/main/java/com/iluwatar/callback/SimpleTask.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.callback; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Implementation of task that need to be executed - * - */ -public class SimpleTask extends Task { - - private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTask.class); - - @Override - public void execute() { - LOGGER.info("Perform some important activity and after call the callback method."); - } -} diff --git a/callback/src/main/java/com/iluwatar/callback/Task.java b/callback/src/main/java/com/iluwatar/callback/Task.java deleted file mode 100644 index 9e4ebf35fbab..000000000000 --- a/callback/src/main/java/com/iluwatar/callback/Task.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.callback; - -/** - * - * Template-method class for callback hook execution - * - */ -public abstract class Task { - - /** - * Execute with callback - */ - public final void executeWith(Callback callback) { - execute(); - if (callback != null) { - callback.call(); - } - } - - public abstract void execute(); -} diff --git a/callback/src/test/java/com/iluwatar/callback/AppTest.java b/callback/src/test/java/com/iluwatar/callback/AppTest.java deleted file mode 100644 index 9e3355f47255..000000000000 --- a/callback/src/test/java/com/iluwatar/callback/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.callback; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Callback example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java b/callback/src/test/java/com/iluwatar/callback/CallbackTest.java deleted file mode 100644 index d6f804f4508a..000000000000 --- a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.callback; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Add a field as a counter. Every time the callback method is called increment this field. Unit - * test checks that the field is being incremented. - * - * Could be done with mock objects as well where the call method call is verified. - */ -public class CallbackTest { - - private Integer callingCount = 0; - - @Test - public void test() { - Callback callback = new Callback() { - @Override - public void call() { - callingCount++; - } - }; - - Task task = new SimpleTask(); - - assertEquals("Initial calling count of 0", new Integer(0), callingCount); - - task.executeWith(callback); - - assertEquals("Callback called once", new Integer(1), callingCount); - - task.executeWith(callback); - - assertEquals("Callback called twice", new Integer(2), callingCount); - - } - - @Test - public void testWithLambdasExample() { - Callback callback = () -> callingCount++; - - Task task = new SimpleTask(); - - assertEquals("Initial calling count of 0", new Integer(0), callingCount); - - task.executeWith(callback); - - assertEquals("Callback called once", new Integer(1), callingCount); - - task.executeWith(callback); - - assertEquals("Callback called twice", new Integer(2), callingCount); - - } -} diff --git a/chain/README.md b/chain/README.md deleted file mode 100644 index 1d7eb5b73025..000000000000 --- a/chain/README.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -layout: pattern -title: Chain of responsibility -folder: chain -permalink: /patterns/chain/ -pumlid: 9SR13SCm20NGLTe1OkxTXX0KKzd4Wa-pVYlrdTxJN4OTMZ4U7LZv8Wg-ssdejLTgoELGHvDhaesw6HpqvWzlXwQTlYq6D3nfSlv2qjcS5F9VgvXjrHnV -categories: Behavioral -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Intent -Avoid coupling the sender of a request to its receiver by giving -more than one object a chance to handle the request. Chain the receiving -objects and pass the request along the chain until an object handles it. - -## Explanation - -Real world example - -> The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility. - -In plain words - -> It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler. - -Wikipedia says - -> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. - -**Programmatic Example** - -Translating our example with orcs from above. First we have the request class - -``` -public class Request { - - private final RequestType requestType; - private final String requestDescription; - private boolean handled; - - public Request(final RequestType requestType, final String requestDescription) { - this.requestType = Objects.requireNonNull(requestType); - this.requestDescription = Objects.requireNonNull(requestDescription); - } - - public String getRequestDescription() { return requestDescription; } - - public RequestType getRequestType() { return requestType; } - - public void markHandled() { this.handled = true; } - - public boolean isHandled() { return this.handled; } - - @Override - public String toString() { return getRequestDescription(); } -} - -public enum RequestType { - DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX -} -``` - -Then the request handler hierarchy - -``` -public abstract class RequestHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); - private RequestHandler next; - - public RequestHandler(RequestHandler next) { - this.next = next; - } - - public void handleRequest(Request req) { - if (next != null) { - next.handleRequest(req); - } - } - - protected void printHandling(Request req) { - LOGGER.info("{} handling request \"{}\"", this, req); - } - - @Override - public abstract String toString(); -} - -public class OrcCommander extends RequestHandler { - public OrcCommander(RequestHandler handler) { - super(handler); - } - - @Override - public void handleRequest(Request req) { - if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) { - printHandling(req); - req.markHandled(); - } else { - super.handleRequest(req); - } - } - - @Override - public String toString() { - return "Orc commander"; - } -} - -// OrcOfficer and OrcSoldier are defined similarly as OrcCommander - -``` - -Then we have the Orc King who gives the orders and forms the chain - -``` -public class OrcKing { - RequestHandler chain; - - public OrcKing() { - buildChain(); - } - - private void buildChain() { - chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null))); - } - - public void makeRequest(Request req) { - chain.handleRequest(req); - } -} -``` - -Then it is used as follows - -``` -OrcKing king = new OrcKing(); -king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle" -king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner" -king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax" -``` - -## Applicability -Use Chain of Responsibility when - -* more than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically -* you want to issue a request to one of several objects without specifying the receiver explicitly -* the set of objects that can handle a request should be specified dynamically - -## Real world examples - -* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29) -* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html) -* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/chain/pom.xml b/chain/pom.xml deleted file mode 100644 index ffdb13821cbe..000000000000 --- a/chain/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - chain - - - junit - junit - test - - - diff --git a/chain/src/main/java/com/iluwatar/chain/App.java b/chain/src/main/java/com/iluwatar/chain/App.java deleted file mode 100644 index 456609e4f366..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/App.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * The Chain of Responsibility pattern is a design pattern consisting of command objects and a - * series of processing objects. Each processing object contains logic that defines the types of - * command objects that it can handle; the rest are passed to the next processing object in the - * chain. A mechanism also exists for adding new processing objects to the end of this chain. - *

- * In this example we organize the request handlers ({@link RequestHandler}) into a chain where each - * handler has a chance to act on the request on its turn. Here the king ({@link OrcKing}) makes - * requests and the military orcs ({@link OrcCommander}, {@link OrcOfficer}, {@link OrcSoldier}) - * form the handler chain. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - OrcKing king = new OrcKing(); - king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); - king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); - king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); - - } -} diff --git a/chain/src/main/java/com/iluwatar/chain/OrcCommander.java b/chain/src/main/java/com/iluwatar/chain/OrcCommander.java deleted file mode 100644 index 048ba495457f..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/OrcCommander.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * OrcCommander - * - */ -public class OrcCommander extends RequestHandler { - - public OrcCommander(RequestHandler handler) { - super(handler); - } - - @Override - public void handleRequest(Request req) { - if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) { - printHandling(req); - req.markHandled(); - } else { - super.handleRequest(req); - } - } - - @Override - public String toString() { - return "Orc commander"; - } -} diff --git a/chain/src/main/java/com/iluwatar/chain/OrcKing.java b/chain/src/main/java/com/iluwatar/chain/OrcKing.java deleted file mode 100644 index 35bdbb3c1e46..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/OrcKing.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * OrcKing makes requests that are handled by the chain. - * - */ -public class OrcKing { - - RequestHandler chain; - - public OrcKing() { - buildChain(); - } - - private void buildChain() { - chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null))); - } - - public void makeRequest(Request req) { - chain.handleRequest(req); - } - -} diff --git a/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java b/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java deleted file mode 100644 index 8e90b7ca0bdb..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * OrcOfficer - * - */ -public class OrcOfficer extends RequestHandler { - - public OrcOfficer(RequestHandler handler) { - super(handler); - } - - @Override - public void handleRequest(Request req) { - if (req.getRequestType().equals(RequestType.TORTURE_PRISONER)) { - printHandling(req); - req.markHandled(); - } else { - super.handleRequest(req); - } - } - - @Override - public String toString() { - return "Orc officer"; - } - -} diff --git a/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java b/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java deleted file mode 100644 index 99e0d5022348..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * OrcSoldier - * - */ -public class OrcSoldier extends RequestHandler { - - public OrcSoldier(RequestHandler handler) { - super(handler); - } - - @Override - public void handleRequest(Request req) { - if (req.getRequestType().equals(RequestType.COLLECT_TAX)) { - printHandling(req); - req.markHandled(); - } else { - super.handleRequest(req); - } - } - - @Override - public String toString() { - return "Orc soldier"; - } -} diff --git a/chain/src/main/java/com/iluwatar/chain/Request.java b/chain/src/main/java/com/iluwatar/chain/Request.java deleted file mode 100644 index c9ac2505b623..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/Request.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -import java.util.Objects; - -/** - * Request - */ -public class Request { - - /** - * The type of this request, used by each item in the chain to see if they should or can handle - * this particular request - */ - private final RequestType requestType; - - /** - * A description of the request - */ - private final String requestDescription; - - /** - * Indicates if the request is handled or not. A request can only switch state from unhandled to - * handled, there's no way to 'unhandle' a request - */ - private boolean handled; - - /** - * Create a new request of the given type and accompanied description. - * - * @param requestType The type of request - * @param requestDescription The description of the request - */ - public Request(final RequestType requestType, final String requestDescription) { - this.requestType = Objects.requireNonNull(requestType); - this.requestDescription = Objects.requireNonNull(requestDescription); - } - - /** - * Get a description of the request - * - * @return A human readable description of the request - */ - public String getRequestDescription() { - return requestDescription; - } - - /** - * Get the type of this request, used by each person in the chain of command to see if they should - * or can handle this particular request - * - * @return The request type - */ - public RequestType getRequestType() { - return requestType; - } - - /** - * Mark the request as handled - */ - public void markHandled() { - this.handled = true; - } - - /** - * Indicates if this request is handled or not - * - * @return true when the request is handled, false if not - */ - public boolean isHandled() { - return this.handled; - } - - @Override - public String toString() { - return getRequestDescription(); - } - -} diff --git a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java b/chain/src/main/java/com/iluwatar/chain/RequestHandler.java deleted file mode 100644 index 81e41fb7c120..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * RequestHandler - * - */ -public abstract class RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); - - private RequestHandler next; - - public RequestHandler(RequestHandler next) { - this.next = next; - } - - /** - * Request handler - */ - public void handleRequest(Request req) { - if (next != null) { - next.handleRequest(req); - } - } - - protected void printHandling(Request req) { - LOGGER.info("{} handling request \"{}\"", this, req); - } - - @Override - public abstract String toString(); -} diff --git a/chain/src/main/java/com/iluwatar/chain/RequestType.java b/chain/src/main/java/com/iluwatar/chain/RequestType.java deleted file mode 100644 index f4d83edc3c94..000000000000 --- a/chain/src/main/java/com/iluwatar/chain/RequestType.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -/** - * - * RequestType enumeration - * - */ -public enum RequestType { - - DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX - -} diff --git a/chain/src/test/java/com/iluwatar/chain/AppTest.java b/chain/src/test/java/com/iluwatar/chain/AppTest.java deleted file mode 100644 index 2a3b6b1970d0..000000000000 --- a/chain/src/test/java/com/iluwatar/chain/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java b/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java deleted file mode 100644 index 208e6ecb62c0..000000000000 --- a/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.chain; - -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/6/15 - 9:29 PM - * - * @author Jeroen Meulemeester - */ -public class OrcKingTest { - - /** - * All possible requests - */ - private static final Request[] REQUESTS = new Request[]{ - new Request(RequestType.DEFEND_CASTLE, "Don't let the barbarians enter my castle!!"), - new Request(RequestType.TORTURE_PRISONER, "Don't just stand there, tickle him!"), - new Request(RequestType.COLLECT_TAX, "Don't steal, the King hates competition ..."), - }; - - @Test - public void testMakeRequest() throws Exception { - final OrcKing king = new OrcKing(); - - for (final Request request : REQUESTS) { - king.makeRequest(request); - assertTrue( - "Expected all requests from King to be handled, but [" + request + "] was not!", - request.isHandled() - ); - } - - } - -} \ No newline at end of file diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml deleted file mode 100644 index 37799eee8a93..000000000000 --- a/checkstyle-suppressions.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/checkstyle.xml b/checkstyle.xml deleted file mode 100644 index b3fbf19a8820..000000000000 --- a/checkstyle.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/converter/README.md b/converter/README.md deleted file mode 100644 index 190ae8bfc917..000000000000 --- a/converter/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Converter -folder: converter -permalink: /patterns/converter/ -categories: -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -The purpose of the Converter Pattern is to provide a generic, common way of bidirectional -conversion between corresponding types, allowing a clean implementation in which the types do not -need to be aware of each other. Moreover, the Converter Pattern introduces bidirectional collection -mapping, reducing a boilerplate code to minimum. - -![alt text](./etc/converter.png "Converter Pattern") - -## Applicability -Use the Converter Pattern in the following situations: - -* When you have types that logically correspond which other and you need to convert entities between them -* When you want to provide different ways of types conversions depending on a context -* Whenever you introduce a DTO (Data transfer object), you will probably need to convert it into the domain equivalence - -## Credits - -* [Converter](http://www.xsolve.pl/blog/converter-pattern-in-java-8/) diff --git a/converter/etc/Converter.png b/converter/etc/Converter.png deleted file mode 100644 index 01435ef5ae29dbda20c7078291a8c1c912003000..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19389 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 Ir04hl0JmNfk^lez diff --git a/converter/etc/Converter.ucls b/converter/etc/Converter.ucls deleted file mode 100644 index 368657430e2b..000000000000 --- a/converter/etc/Converter.ucls +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/converter/etc/converter.urm.puml b/converter/etc/converter.urm.puml deleted file mode 100644 index 5e0acf1915a3..000000000000 --- a/converter/etc/converter.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.converter { - class App { - + App() - + main(args : String[]) {static} - } - class Converter { - - fromDto : Function - - fromEntity : Function - + Converter(fromDto : Function, fromEntity : Function) - + convertFromDto(userDto : T) : U - + convertFromEntity(user : U) : T - + createFromDtos(dtoUsers : Collection) : List - + createFromEntities(users : Collection) : List - } - class User { - - firstName : String - - isActive : boolean - - lastName : String - - userId : String - + User(firstName : String, lastName : String, isActive : boolean, userId : String) - + equals(o : Object) : boolean - + getFirstName() : String - + getLastName() : String - + getUserId() : String - + hashCode() : int - + isActive() : boolean - + toString() : String - } - class UserConverter { - + UserConverter() - } - class UserDto { - - email : String - - firstName : String - - isActive : boolean - - lastName : String - + UserDto(firstName : String, lastName : String, isActive : boolean, email : String) - + equals(o : Object) : boolean - + getEmail() : String - + getFirstName() : String - + getLastName() : String - + hashCode() : int - + isActive() : boolean - + toString() : String - } -} -UserConverter --|> Converter -@enduml \ No newline at end of file diff --git a/converter/pom.xml b/converter/pom.xml deleted file mode 100644 index 923b0e43c5f7..000000000000 --- a/converter/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - - junit - junit - test - - - com.google.guava - guava - - - converter - - - diff --git a/converter/src/main/java/com/iluwatar/converter/App.java b/converter/src/main/java/com/iluwatar/converter/App.java deleted file mode 100644 index 6e436706d94f..000000000000 --- a/converter/src/main/java/com/iluwatar/converter/App.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.converter; - - -import com.google.common.collect.Lists; - -import java.util.ArrayList; -import java.util.List; - -/** - * The Converter pattern is a behavioral design pattern which allows a common way of bidirectional - * conversion between corresponding types (e.g. DTO and domain representations of the logically - * isomorphic types). Moreover, the pattern introduces a common way of converting a collection of - * objects between types. - */ -public class App { - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - Converter userConverter = new UserConverter(); - - UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com"); - User user = userConverter.convertFromDto(dtoUser); - System.out.println("Entity converted from DTO:" + user); - - ArrayList users = Lists.newArrayList(new User("Camile", "Tough", false, "124sad"), - new User("Marti", "Luther", true, "42309fd"), new User("Kate", "Smith", true, "if0243")); - System.out.println("Domain entities:"); - users.forEach(System.out::println); - - System.out.println("DTO entities converted from domain:"); - List dtoEntities = userConverter.createFromEntities(users); - dtoEntities.forEach(System.out::println); - - } -} diff --git a/converter/src/main/java/com/iluwatar/converter/Converter.java b/converter/src/main/java/com/iluwatar/converter/Converter.java deleted file mode 100644 index 918d2d503321..000000000000 --- a/converter/src/main/java/com/iluwatar/converter/Converter.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.converter; - -import java.util.Collection; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * Generic converter, thanks to Java8 features not only provides a way of generic bidirectional - * conversion between coresponding types, but also a common way of converting a collection of objects - * of the same type, reducing boilerplate code to the absolute minimum. - * @param DTO representation's type - * @param Domain representation's type - */ -public class Converter { - - private final Function fromDto; - private final Function fromEntity; - - /** - * @param fromDto Function that converts given dto entity into the domain entity. - * @param fromEntity Function that converts given domain entity into the dto entity. - */ - public Converter(final Function fromDto, final Function fromEntity) { - this.fromDto = fromDto; - this.fromEntity = fromEntity; - } - - /** - * @param userDto DTO entity - * @return The domain representation - the result of the converting function application on dto entity. - */ - public final U convertFromDto(final T userDto) { - return fromDto.apply(userDto); - } - - /** - * @param user domain entity - * @return The DTO representation - the result of the converting function application on domain entity. - */ - public final T convertFromEntity(final U user) { - return fromEntity.apply(user); - } - - /** - * @param dtoUsers collection of DTO entities - * @return List of domain representation of provided entities retrieved by - * mapping each of them with the conversion function - */ - public final List createFromDtos(final Collection dtoUsers) { - return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList()); - } - - /** - * @param users collection of domain entities - * @return List of domain representation of provided entities retrieved by - * mapping each of them with the conversion function - */ - public final List createFromEntities(final Collection users) { - return users.stream().map(this::convertFromEntity).collect(Collectors.toList()); - } - -} diff --git a/converter/src/main/java/com/iluwatar/converter/User.java b/converter/src/main/java/com/iluwatar/converter/User.java deleted file mode 100644 index 62903a9313cd..000000000000 --- a/converter/src/main/java/com/iluwatar/converter/User.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.converter; - -import java.util.Objects; - -/** - * User class - */ -public class User { - private String firstName; - private String lastName; - private boolean isActive; - private String userId; - - /** - * @param firstName user's first name - * @param lastName user's last name - * @param isActive flag indicating whether the user is active - * @param userId user's identificator - */ - public User(String firstName, String lastName, boolean isActive, String userId) { - this.firstName = firstName; - this.lastName = lastName; - this.isActive = isActive; - this.userId = userId; - } - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public boolean isActive() { - return isActive; - } - - public String getUserId() { - return userId; - } - - @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - User user = (User) o; - return isActive == user.isActive && Objects.equals(firstName, user.firstName) && Objects - .equals(lastName, user.lastName) && Objects.equals(userId, user.userId); - } - - @Override public int hashCode() { - return Objects.hash(firstName, lastName, isActive, userId); - } - - @Override public String toString() { - return "User{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' - + ", isActive=" + isActive + ", userId='" + userId + '\'' + '}'; - } -} diff --git a/converter/src/main/java/com/iluwatar/converter/UserConverter.java b/converter/src/main/java/com/iluwatar/converter/UserConverter.java deleted file mode 100644 index 9ef1d03c24de..000000000000 --- a/converter/src/main/java/com/iluwatar/converter/UserConverter.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.converter; - -/** - * Example implementation of the simple User converter. - */ -public class UserConverter extends Converter { - - /** - * Constructor. - */ - public UserConverter() { - super(userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(), - userDto.getEmail()), - user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), - user.getUserId())); - } -} diff --git a/converter/src/main/java/com/iluwatar/converter/UserDto.java b/converter/src/main/java/com/iluwatar/converter/UserDto.java deleted file mode 100644 index 8eacc0b3be96..000000000000 --- a/converter/src/main/java/com/iluwatar/converter/UserDto.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

With the DAO pattern, we can use various method calls to retrieve/add/delete/update data - * without directly interacting with the data source. The below example demonstrates basic CRUD - * operations: select, add, update, and delete. - * - * - */ -public class App { - private static final String DB_URL = "jdbc:h2:~/dao"; - private static Logger log = Logger.getLogger(App.class); - - /** - * Program entry point. - * - * @param args command line args. - * @throws Exception if any error occurs. - */ - public static void main(final String[] args) throws Exception { - final CustomerDao inMemoryDao = new InMemoryCustomerDao(); - performOperationsUsing(inMemoryDao); - - final DataSource dataSource = createDataSource(); - createSchema(dataSource); - final CustomerDao dbDao = new DbCustomerDao(dataSource); - performOperationsUsing(dbDao); - deleteSchema(dataSource); - } - - private static void deleteSchema(DataSource dataSource) throws SQLException { - try (Connection connection = dataSource.getConnection(); - Statement statement = connection.createStatement()) { - statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL); - } - } - - private static void createSchema(DataSource dataSource) throws SQLException { - try (Connection connection = dataSource.getConnection(); - Statement statement = connection.createStatement()) { - statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL); - } - } - - private static DataSource createDataSource() { - JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL(DB_URL); - return dataSource; - } - - private static void performOperationsUsing(final CustomerDao customerDao) throws Exception { - addCustomers(customerDao); - log.info("customerDao.getAllCustomers(): "); - try (Stream customerStream = customerDao.getAll()) { - customerStream.forEach((customer) -> log.info(customer)); - } - log.info("customerDao.getCustomerById(2): " + customerDao.getById(2)); - final Customer customer = new Customer(4, "Dan", "Danson"); - customerDao.add(customer); - log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); - customer.setFirstName("Daniel"); - customer.setLastName("Danielson"); - customerDao.update(customer); - log.info("customerDao.getAllCustomers(): "); - try (Stream customerStream = customerDao.getAll()) { - customerStream.forEach((cust) -> log.info(cust)); - } - customerDao.delete(customer); - log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); - } - - private static void addCustomers(CustomerDao customerDao) throws Exception { - for (Customer customer : generateSampleCustomers()) { - customerDao.add(customer); - } - } - - /** - * Generate customers. - * - * @return list of customers. - */ - public static List generateSampleCustomers() { - final Customer customer1 = new Customer(1, "Adam", "Adamson"); - final Customer customer2 = new Customer(2, "Bob", "Bobson"); - final Customer customer3 = new Customer(3, "Carl", "Carlson"); - final List customers = new ArrayList<>(); - customers.add(customer1); - customers.add(customer2); - customers.add(customer3); - return customers; - } -} diff --git a/dao/src/main/java/com/iluwatar/dao/CustomException.java b/dao/src/main/java/com/iluwatar/dao/CustomException.java deleted file mode 100644 index fd291b605392..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/CustomException.java +++ /dev/null @@ -1,43 +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.dao; - -/** - * - * Custom exception - * - */ -public class CustomException extends Exception { - - private static final long serialVersionUID = 1L; - - public CustomException() {} - - public CustomException(String message) { - super(message); - } - - public CustomException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/dao/src/main/java/com/iluwatar/dao/Customer.java b/dao/src/main/java/com/iluwatar/dao/Customer.java deleted file mode 100644 index a133bf2b0ded..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/Customer.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -/** - * A customer POJO that represents the data that will be read from the data source. - * - */ -public class Customer { - - private int id; - private String firstName; - private String lastName; - - /** - * Creates an instance of customer. - */ - public Customer(final int id, final String firstName, final String lastName) { - this.id = id; - this.firstName = firstName; - this.lastName = lastName; - } - - public int getId() { - return id; - } - - public void setId(final int id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(final String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(final String lastName) { - this.lastName = lastName; - } - - @Override - public String toString() { - return "Customer{" + "id=" + getId() + ", firstName='" + getFirstName() + '\'' + ", lastName='" - + getLastName() + '\'' + '}'; - } - - @Override - public boolean equals(final Object that) { - boolean isEqual = false; - if (this == that) { - isEqual = true; - } else if (that != null && getClass() == that.getClass()) { - final Customer customer = (Customer) that; - if (getId() == customer.getId()) { - isEqual = true; - } - } - return isEqual; - } - - @Override - public int hashCode() { - return getId(); - } -} diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java b/dao/src/main/java/com/iluwatar/dao/CustomerDao.java deleted file mode 100644 index 6156bb8d7d95..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import java.util.Optional; -import java.util.stream.Stream; - -/** - * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object - * that provides an interface to some type of persistence mechanism. By mapping application calls - * to the persistence layer, DAO provides some specific data operations without exposing details - * of the database. This isolation supports the Single responsibility principle. It separates what - * data accesses the application needs, in terms of domain-specific objects and data types - * (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS, - * database schema, etc. - * - *

Any change in the way data is stored and retrieved will not change the client code as the - * client will be using interface and need not worry about exact source. - * - * @see InMemoryCustomerDao - * @see DbCustomerDao - */ -public interface CustomerDao { - - /** - * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based - * on the implementation. The stream must be closed after use. - * @throws Exception if any error occurs. - */ - Stream getAll() throws Exception; - - /** - * @param id unique identifier of the customer. - * @return an optional with customer if a customer with unique identifier id - * exists, empty optional otherwise. - * @throws Exception if any error occurs. - */ - Optional getById(int id) throws Exception; - - /** - * @param customer the customer to be added. - * @return true if customer is successfully added, false if customer already exists. - * @throws Exception if any error occurs. - */ - boolean add(Customer customer) throws Exception; - - /** - * @param customer the customer to be updated. - * @return true if customer exists and is successfully updated, false otherwise. - * @throws Exception if any error occurs. - */ - boolean update(Customer customer) throws Exception; - - /** - * @param customer the customer to be deleted. - * @return true if customer exists and is successfully deleted, false otherwise. - * @throws Exception if any error occurs. - */ - boolean delete(Customer customer) throws Exception; -} diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java b/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java deleted file mode 100644 index cce967dc8939..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dao; - -/** - * Customer Schema SQL Class - */ -public final class CustomerSchemaSql { - - private CustomerSchemaSql() {} - - public static final String CREATE_SCHEMA_SQL = "CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), " - + "LNAME VARCHAR(100))"; - - public static final String DELETE_SCHEMA_SQL = "DROP TABLE CUSTOMERS"; - -} diff --git a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java deleted file mode 100644 index fa2e411dab56..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Consumer; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import javax.sql.DataSource; - -import org.apache.log4j.Logger; - -/** - * An implementation of {@link CustomerDao} that persists customers in RDBMS. - * - */ -public class DbCustomerDao implements CustomerDao { - - private static final Logger LOGGER = Logger.getLogger(DbCustomerDao.class); - - private final DataSource dataSource; - - /** - * Creates an instance of {@link DbCustomerDao} which uses provided dataSource - * to store and retrieve customer information. - * - * @param dataSource a non-null dataSource. - */ - public DbCustomerDao(DataSource dataSource) { - this.dataSource = dataSource; - } - - /** - * @return a lazily populated stream of customers. Note the stream returned must be closed to - * free all the acquired resources. The stream keeps an open connection to the database till - * it is complete or is closed manually. - */ - @Override - public Stream getAll() throws Exception { - - Connection connection; - try { - connection = getConnection(); - PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); // NOSONAR - ResultSet resultSet = statement.executeQuery(); // NOSONAR - return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, - Spliterator.ORDERED) { - - @Override - public boolean tryAdvance(Consumer action) { - try { - if (!resultSet.next()) { - return false; - } - action.accept(createCustomer(resultSet)); - return true; - } catch (SQLException e) { - throw new RuntimeException(e); // NOSONAR - } - } - }, false).onClose(() -> mutedClose(connection, statement, resultSet)); - } catch (SQLException e) { - throw new CustomException(e.getMessage(), e); - } - } - - private Connection getConnection() throws SQLException { - return dataSource.getConnection(); - } - - private void mutedClose(Connection connection, PreparedStatement statement, ResultSet resultSet) { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (SQLException e) { - LOGGER.info("Exception thrown " + e.getMessage()); - } - } - - private Customer createCustomer(ResultSet resultSet) throws SQLException { - return new Customer(resultSet.getInt("ID"), - resultSet.getString("FNAME"), - resultSet.getString("LNAME")); - } - - /** - * {@inheritDoc} - */ - @Override - public Optional getById(int id) throws Exception { - - ResultSet resultSet = null; - - try (Connection connection = getConnection(); - PreparedStatement statement = - connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) { - - statement.setInt(1, id); - resultSet = statement.executeQuery(); - if (resultSet.next()) { - return Optional.of(createCustomer(resultSet)); - } else { - return Optional.empty(); - } - } catch (SQLException ex) { - throw new CustomException(ex.getMessage(), ex); - } finally { - if (resultSet != null) { - resultSet.close(); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean add(Customer customer) throws Exception { - if (getById(customer.getId()).isPresent()) { - return false; - } - - try (Connection connection = getConnection(); - PreparedStatement statement = - connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) { - statement.setInt(1, customer.getId()); - statement.setString(2, customer.getFirstName()); - statement.setString(3, customer.getLastName()); - statement.execute(); - return true; - } catch (SQLException ex) { - throw new CustomException(ex.getMessage(), ex); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean update(Customer customer) throws Exception { - try (Connection connection = getConnection(); - PreparedStatement statement = - connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) { - statement.setString(1, customer.getFirstName()); - statement.setString(2, customer.getLastName()); - statement.setInt(3, customer.getId()); - return statement.executeUpdate() > 0; - } catch (SQLException ex) { - throw new CustomException(ex.getMessage(), ex); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean delete(Customer customer) throws Exception { - try (Connection connection = getConnection(); - PreparedStatement statement = - connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) { - statement.setInt(1, customer.getId()); - return statement.executeUpdate() > 0; - } catch (SQLException ex) { - throw new CustomException(ex.getMessage(), ex); - } - } -} diff --git a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java deleted file mode 100644 index 38acca60f66e..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -/** - * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory - * and data is lost when the application exits. - *
- * This implementation is useful as temporary database or for testing. - */ -public class InMemoryCustomerDao implements CustomerDao { - - private Map idToCustomer = new HashMap<>(); - - /** - * An eagerly evaluated stream of customers stored in memory. - */ - @Override - public Stream getAll() { - return idToCustomer.values().stream(); - } - - @Override - public Optional getById(final int id) { - return Optional.ofNullable(idToCustomer.get(id)); - } - - @Override - public boolean add(final Customer customer) { - if (getById(customer.getId()).isPresent()) { - return false; - } - - idToCustomer.put(customer.getId(), customer); - return true; - } - - @Override - public boolean update(final Customer customer) { - return idToCustomer.replace(customer.getId(), customer) != null; - } - - @Override - public boolean delete(final Customer customer) { - return idToCustomer.remove(customer.getId()) != null; - } -} diff --git a/dao/src/main/resources/log4j.xml b/dao/src/main/resources/log4j.xml deleted file mode 100644 index 14f043ff7576..000000000000 --- a/dao/src/main/resources/log4j.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dao/src/test/java/com/iluwatar/dao/AppTest.java b/dao/src/test/java/com/iluwatar/dao/AppTest.java deleted file mode 100644 index 73534eb02212..000000000000 --- a/dao/src/test/java/com/iluwatar/dao/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import org.junit.Test; - -/** - * Tests that DAO example runs without errors. - */ -public class AppTest { - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java b/dao/src/test/java/com/iluwatar/dao/CustomerTest.java deleted file mode 100644 index 8122c369fab3..000000000000 --- a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import org.junit.Before; -import org.junit.Test; - -/** - * Tests {@link Customer}. - */ -public class CustomerTest { - - private Customer customer; - private static final int ID = 1; - private static final String FIRSTNAME = "Winston"; - private static final String LASTNAME = "Churchill"; - - @Before - public void setUp() { - customer = new Customer(ID, FIRSTNAME, LASTNAME); - } - - @Test - public void getAndSetId() { - final int newId = 2; - customer.setId(newId); - assertEquals(newId, customer.getId()); - } - - @Test - public void getAndSetFirstname() { - final String newFirstname = "Bill"; - customer.setFirstName(newFirstname); - assertEquals(newFirstname, customer.getFirstName()); - } - - @Test - public void getAndSetLastname() { - final String newLastname = "Clinton"; - customer.setLastName(newLastname); - assertEquals(newLastname, customer.getLastName()); - } - - @Test - public void notEqualWithDifferentId() { - final int newId = 2; - final Customer otherCustomer = new Customer(newId, FIRSTNAME, LASTNAME); - assertNotEquals(customer, otherCustomer); - assertNotEquals(customer.hashCode(), otherCustomer.hashCode()); - } - - @Test - public void equalsWithSameObjectValues() { - final Customer otherCustomer = new Customer(ID, FIRSTNAME, LASTNAME); - assertEquals(customer, otherCustomer); - assertEquals(customer.hashCode(), otherCustomer.hashCode()); - } - - @Test - public void equalsWithSameObjects() { - assertEquals(customer, customer); - assertEquals(customer.hashCode(), customer.hashCode()); - } - - @Test - public void testToString() { - final StringBuffer buffer = new StringBuffer(); - buffer.append("Customer{id=") - .append("" + customer.getId()) - .append(", firstName='") - .append(customer.getFirstName()) - .append("\', lastName='") - .append(customer.getLastName() + "\'}"); - assertEquals(buffer.toString(), customer.toString()); - } -} diff --git a/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java deleted file mode 100644 index 213aef20676f..000000000000 --- a/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.stream.Stream; - -import javax.sql.DataSource; - -import org.h2.jdbcx.JdbcDataSource; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.mockito.Mockito; - -import de.bechte.junit.runners.context.HierarchicalContextRunner; - -/** - * Tests {@link DbCustomerDao}. - */ -@RunWith(HierarchicalContextRunner.class) -public class DbCustomerDaoTest { - - private static final String DB_URL = "jdbc:h2:~/dao"; - private DbCustomerDao dao; - private Customer existingCustomer = new Customer(1, "Freddy", "Krueger"); - - /** - * Creates customers schema. - * @throws SQLException if there is any error while creating schema. - */ - @Before - public void createSchema() throws SQLException { - try (Connection connection = DriverManager.getConnection(DB_URL); - Statement statement = connection.createStatement()) { - statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL); - } - } - - /** - * Represents the scenario where DB connectivity is present. - */ - public class ConnectionSuccess { - - /** - * Setup for connection success scenario. - * @throws Exception if any error occurs. - */ - @Before - public void setUp() throws Exception { - JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL(DB_URL); - dao = new DbCustomerDao(dataSource); - boolean result = dao.add(existingCustomer); - assertTrue(result); - } - - /** - * Represents the scenario when DAO operations are being performed on a non existing customer. - */ - public class NonExistingCustomer { - - @Test - public void addingShouldResultInSuccess() throws Exception { - try (Stream allCustomers = dao.getAll()) { - assumeTrue(allCustomers.count() == 1); - } - - final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); - boolean result = dao.add(nonExistingCustomer); - assertTrue(result); - - assertCustomerCountIs(2); - assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get()); - } - - @Test - public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception { - final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); - boolean result = dao.delete(nonExistingCustomer); - - assertFalse(result); - assertCustomerCountIs(1); - } - - @Test - public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception { - final int nonExistingId = getNonExistingCustomerId(); - final String newFirstname = "Douglas"; - final String newLastname = "MacArthur"; - final Customer customer = new Customer(nonExistingId, newFirstname, newLastname); - boolean result = dao.update(customer); - - assertFalse(result); - assertFalse(dao.getById(nonExistingId).isPresent()); - } - - @Test - public void retrieveShouldReturnNoCustomer() throws Exception { - assertFalse(dao.getById(getNonExistingCustomerId()).isPresent()); - } - } - - /** - * Represents a scenario where DAO operations are being performed on an already existing - * customer. - * - */ - public class ExistingCustomer { - - @Test - public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception { - Customer existingCustomer = new Customer(1, "Freddy", "Krueger"); - - boolean result = dao.add(existingCustomer); - - assertFalse(result); - assertCustomerCountIs(1); - assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get()); - } - - @Test - public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception { - boolean result = dao.delete(existingCustomer); - - assertTrue(result); - assertCustomerCountIs(0); - assertFalse(dao.getById(existingCustomer.getId()).isPresent()); - } - - @Test - public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception { - final String newFirstname = "Bernard"; - final String newLastname = "Montgomery"; - final Customer customer = new Customer(existingCustomer.getId(), newFirstname, newLastname); - boolean result = dao.update(customer); - - assertTrue(result); - - final Customer cust = dao.getById(existingCustomer.getId()).get(); - assertEquals(newFirstname, cust.getFirstName()); - assertEquals(newLastname, cust.getLastName()); - } - } - } - - /** - * Represents a scenario where DB connectivity is not present due to network issue, or - * DB service unavailable. - * - */ - public class ConnectivityIssue { - - private static final String EXCEPTION_CAUSE = "Connection not available"; - @Rule public ExpectedException exception = ExpectedException.none(); - - /** - * setup a connection failure scenario. - * @throws SQLException if any error occurs. - */ - @Before - public void setUp() throws SQLException { - dao = new DbCustomerDao(mockedDatasource()); - exception.expect(Exception.class); - exception.expectMessage(EXCEPTION_CAUSE); - } - - private DataSource mockedDatasource() throws SQLException { - DataSource mockedDataSource = mock(DataSource.class); - Connection mockedConnection = mock(Connection.class); - SQLException exception = new SQLException(EXCEPTION_CAUSE); - doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString()); - doReturn(mockedConnection).when(mockedDataSource).getConnection(); - return mockedDataSource; - } - - @Test - public void addingACustomerFailsWithExceptionAsFeedbackToClient() throws Exception { - dao.add(new Customer(2, "Bernard", "Montgomery")); - } - - @Test - public void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() throws Exception { - dao.delete(existingCustomer); - } - - @Test - public void updatingACustomerFailsWithFeedbackToTheClient() throws Exception { - final String newFirstname = "Bernard"; - final String newLastname = "Montgomery"; - - dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname)); - } - - @Test - public void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() throws Exception { - dao.getById(existingCustomer.getId()); - } - - @Test - public void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() throws Exception { - dao.getAll(); - } - - } - - /** - * Delete customer schema for fresh setup per test. - * @throws SQLException if any error occurs. - */ - @After - public void deleteSchema() throws SQLException { - try (Connection connection = DriverManager.getConnection(DB_URL); - Statement statement = connection.createStatement()) { - statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL); - } - } - - private void assertCustomerCountIs(int count) throws Exception { - try (Stream allCustomers = dao.getAll()) { - assertTrue(allCustomers.count() == count); - } - } - - - /** - * An arbitrary number which does not correspond to an active Customer id. - * - * @return an int of a customer id which doesn't exist - */ - private int getNonExistingCustomerId() { - return 999; - } -} diff --git a/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java deleted file mode 100644 index 2532b2fad4c9..000000000000 --- a/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; - -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import de.bechte.junit.runners.context.HierarchicalContextRunner; - -/** - * Tests {@link InMemoryCustomerDao}. - */ -@RunWith(HierarchicalContextRunner.class) -public class InMemoryCustomerDaoTest { - - private InMemoryCustomerDao dao; - private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger"); - - @Before - public void setUp() { - dao = new InMemoryCustomerDao(); - assertTrue(dao.add(CUSTOMER)); - } - - /** - * Represents the scenario when the DAO operations are being performed on a non existent - * customer. - */ - public class NonExistingCustomer { - - @Test - public void addingShouldResultInSuccess() throws Exception { - try (Stream allCustomers = dao.getAll()) { - assumeTrue(allCustomers.count() == 1); - } - - final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); - boolean result = dao.add(nonExistingCustomer); - assertTrue(result); - - assertCustomerCountIs(2); - assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get()); - } - - @Test - public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception { - final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); - boolean result = dao.delete(nonExistingCustomer); - - assertFalse(result); - assertCustomerCountIs(1); - } - - @Test - public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception { - final int nonExistingId = getNonExistingCustomerId(); - final String newFirstname = "Douglas"; - final String newLastname = "MacArthur"; - final Customer customer = new Customer(nonExistingId, newFirstname, newLastname); - boolean result = dao.update(customer); - - assertFalse(result); - assertFalse(dao.getById(nonExistingId).isPresent()); - } - - @Test - public void retrieveShouldReturnNoCustomer() throws Exception { - assertFalse(dao.getById(getNonExistingCustomerId()).isPresent()); - } - } - - /** - * Represents the scenario when the DAO operations are being performed on an already existing - * customer. - */ - public class ExistingCustomer { - - @Test - public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception { - boolean result = dao.add(CUSTOMER); - - assertFalse(result); - assertCustomerCountIs(1); - assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get()); - } - - @Test - public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception { - boolean result = dao.delete(CUSTOMER); - - assertTrue(result); - assertCustomerCountIs(0); - assertFalse(dao.getById(CUSTOMER.getId()).isPresent()); - } - - @Test - public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception { - final String newFirstname = "Bernard"; - final String newLastname = "Montgomery"; - final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname); - boolean result = dao.update(customer); - - assertTrue(result); - - final Customer cust = dao.getById(CUSTOMER.getId()).get(); - assertEquals(newFirstname, cust.getFirstName()); - assertEquals(newLastname, cust.getLastName()); - } - - @Test - public void retriveShouldReturnTheCustomer() { - Optional optionalCustomer = dao.getById(CUSTOMER.getId()); - - assertTrue(optionalCustomer.isPresent()); - assertEquals(CUSTOMER, optionalCustomer.get()); - } - } - - /** - * An arbitrary number which does not correspond to an active Customer id. - * - * @return an int of a customer id which doesn't exist - */ - private int getNonExistingCustomerId() { - return 999; - } - - private void assertCustomerCountIs(int count) throws Exception { - try (Stream allCustomers = dao.getAll()) { - assertTrue(allCustomers.count() == count); - } - } -} diff --git a/data-bus/.gitignore b/data-bus/.gitignore deleted file mode 100644 index ea8c4bf7f35f..000000000000 --- a/data-bus/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/data-bus/README.md b/data-bus/README.md deleted file mode 100644 index 257192e25234..000000000000 --- a/data-bus/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: pattern -title: Data Bus -folder: data-bus -permalink: /patterns/data-bus/ - -categories: Architectural -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent - -Allows send of messages/events between components of an application -without them needing to know about each other. They only need to know -about the type of the message/event being sent. - -![data bus pattern uml diagram](./etc/data-bus.urm.png "Data Bus pattern") - -## Applicability -Use Data Bus pattern when - -* you want your components to decide themselves which messages/events they want to receive -* you want to have many-to-many communication -* you want your components to know nothing about each other - -## Related Patterns -Data Bus is similar to - -* Mediator pattern with Data Bus Members deciding for themselves if they want to accept any given message -* Observer pattern but supporting many-to-many communication -* Publish/Subscribe pattern with the Data Bus decoupling the publisher and the subscriber diff --git a/data-bus/etc/data-bus.urm.png b/data-bus/etc/data-bus.urm.png deleted file mode 100644 index 8bd2148174e4ce0cca85051d0c67a004e6d1e5fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61121 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%0A8B(lGa>!X0%#dOQ+z&% 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 H^VR - + DataBus() - + getInstance() : DataBus {static} - + publish(event : DataType) - + subscribe(member : Member) - + unsubscribe(member : Member) - } - interface DataType { - + getDataBus() : DataBus {abstract} - + setDataBus(DataBus) {abstract} - } - interface Member { - + accept(DataType) {abstract} - } -} -package com.iluwatar.databus.data { - class MessageData { - - message : String - + MessageData(message : String) - + getMessage() : String - + of(message : String) : DataType {static} - } - class StartingData { - - when : LocalDateTime - + StartingData(when : LocalDateTime) - + getWhen() : LocalDateTime - + of(when : LocalDateTime) : DataType {static} - } - class StoppingData { - - when : LocalDateTime - + StoppingData(when : LocalDateTime) - + getWhen() : LocalDateTime - + of(when : LocalDateTime) : DataType {static} - } -} -package com.iluwatar.databus.members { - class CounterMember { - - log : Logger {static} - - name : String - + CounterMember(name : String) - + accept(data : DataType) - - handleEvent(data : MessageData) - } - class StatusMember { - - id : int - - log : Logger {static} - + StatusMember(id : int) - + accept(data : DataType) - - handleEvent(data : StartingData) - - handleEvent(data : StoppingData) - } -} -AbstractDataType --> "-dataBus" DataBus -DataBus --> "-INSTANCE" DataBus -DataBus --> "-listeners" Member -AbstractDataType ..|> DataType -MessageData --|> AbstractDataType -StartingData --|> AbstractDataType -StoppingData --|> AbstractDataType -CounterMember ..|> Member -StatusMember ..|> Member -@enduml \ No newline at end of file diff --git a/data-bus/pom.xml b/data-bus/pom.xml deleted file mode 100644 index 318caf89abca..000000000000 --- a/data-bus/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - 1.16.14 - - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - data-bus - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/data-bus/src/main/java/com/iluwatar/databus/AbstractDataType.java b/data-bus/src/main/java/com/iluwatar/databus/AbstractDataType.java deleted file mode 100644 index d57e4a014fdc..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/AbstractDataType.java +++ /dev/null @@ -1,67 +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. - */ -/* -The MIT License (MIT) - -Copyright (c) 2016 Paul Campbell - -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.databus; - -/** - * Base for data to send via the Data-Bus. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class AbstractDataType implements DataType { - - private DataBus dataBus; - - @Override - public DataBus getDataBus() { - return dataBus; - } - - @Override - public void setDataBus(DataBus dataBus) { - this.dataBus = dataBus; - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/App.java b/data-bus/src/main/java/com/iluwatar/databus/App.java deleted file mode 100644 index 748bb6af0381..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/App.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus; - -import com.iluwatar.databus.data.MessageData; -import com.iluwatar.databus.data.StartingData; -import com.iluwatar.databus.data.StoppingData; -import com.iluwatar.databus.members.MessageCollectorMember; -import com.iluwatar.databus.members.StatusMember; - -import java.time.LocalDateTime; - -/** - * The Data Bus pattern - *

- *

{@see http://wiki.c2.com/?DataBusPattern}

- *

- *

The Data-Bus pattern provides a method where different parts of an application may - * pass messages between each other without needing to be aware of the other's existence.

- *

Similar to the {@code ObserverPattern}, members register themselves with the {@link DataBus} - * and may then receive each piece of data that is published to the Data-Bus. The member - * may react to any given message or not.

- *

It allows for Many-to-Many distribution of data, as there may be any number of - * publishers to a Data-Bus, and any number of members receiving the data. All members - * will receive the same data, the order each receives a given piece of data, is an - * implementation detail.

- *

Members may unsubscribe from the Data-Bus to stop receiving data.

- *

This example of the pattern implements a Synchronous Data-Bus, meaning that - * when data is published to the Data-Bus, the publish method will not return until - * all members have received the data and returned.

- *

The {@link DataBus} class is a Singleton.

- *

Members of the Data-Bus must implement the {@link Member} interface.

- *

Data to be published via the Data-Bus must implement the {@link DataType} interface.

- *

The {@code data} package contains example {@link DataType} implementations.

- *

The {@code members} package contains example {@link Member} implementations.

- *

The {@link StatusMember} demonstrates using the DataBus to publish a message - * to the Data-Bus when it receives a message.

- * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -class App { - - public static void main(String[] args) { - final DataBus bus = DataBus.getInstance(); - bus.subscribe(new StatusMember(1)); - bus.subscribe(new StatusMember(2)); - final MessageCollectorMember foo = new MessageCollectorMember("Foo"); - final MessageCollectorMember bar = new MessageCollectorMember("Bar"); - bus.subscribe(foo); - bus.publish(StartingData.of(LocalDateTime.now())); - bus.publish(MessageData.of("Only Foo should see this")); - bus.subscribe(bar); - bus.publish(MessageData.of("Foo and Bar should see this")); - bus.unsubscribe(foo); - bus.publish(MessageData.of("Only Bar should see this")); - bus.publish(StoppingData.of(LocalDateTime.now())); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/DataBus.java b/data-bus/src/main/java/com/iluwatar/databus/DataBus.java deleted file mode 100644 index edaefe623499..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/DataBus.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus; - -import java.util.HashSet; -import java.util.Set; - -/** - * The Data-Bus implementation. - * - *

This implementation uses a Singleton.

- * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class DataBus { - - private static final DataBus INSTANCE = new DataBus(); - - private final Set listeners = new HashSet<>(); - - public static DataBus getInstance() { - return INSTANCE; - } - - /** - * Register a member with the data-bus to start receiving events. - * - * @param member The member to register - */ - public void subscribe(final Member member) { - this.listeners.add(member); - } - - /** - * Deregister a member to stop receiving events. - * - * @param member The member to deregister - */ - public void unsubscribe(final Member member) { - this.listeners.remove(member); - } - - /** - * Publish and event to all members. - * - * @param event The event - */ - public void publish(final DataType event) { - event.setDataBus(this); - listeners.forEach(listener -> listener.accept(event)); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/DataType.java b/data-bus/src/main/java/com/iluwatar/databus/DataType.java deleted file mode 100644 index a3dd328705ba..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/DataType.java +++ /dev/null @@ -1,70 +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. - */ -/* -The MIT License (MIT) - -Copyright (c) 2016 Paul Campbell - -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.databus; - -/** - * Events are sent via the Data-Bus. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ - -public interface DataType { - - /** - * Returns the data-bus the event is being sent on. - * - * @return The data-bus - */ - DataBus getDataBus(); - - /** - * Set the data-bus the event will be sent on. - * - * @param dataBus The data-bus - */ - void setDataBus(DataBus dataBus); -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/Member.java b/data-bus/src/main/java/com/iluwatar/databus/Member.java deleted file mode 100644 index c2ab7de32d7d..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/Member.java +++ /dev/null @@ -1,59 +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. - */ -/* -The MIT License (MIT) - -Copyright (c) 2016 Paul Campbell - -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.databus; - -import java.util.function.Consumer; - -/** - * Members receive events from the Data-Bus. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public interface Member extends Consumer { - - void accept(DataType event); -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/data/MessageData.java b/data-bus/src/main/java/com/iluwatar/databus/data/MessageData.java deleted file mode 100644 index ac541cf200cc..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/data/MessageData.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus.data; - -import com.iluwatar.databus.AbstractDataType; -import com.iluwatar.databus.DataType; - -/** - * An event raised when a string message is sent. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class MessageData extends AbstractDataType { - - private final String message; - - public MessageData(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - - public static DataType of(final String message) { - return new MessageData(message); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java b/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java deleted file mode 100644 index ac7391f1a236..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus.data; - -import com.iluwatar.databus.AbstractDataType; -import com.iluwatar.databus.DataType; - -import java.time.LocalDateTime; - -/** - * An event raised when applications starts, containing the start time of the application. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class StartingData extends AbstractDataType { - - private final LocalDateTime when; - - public StartingData(LocalDateTime when) { - this.when = when; - } - - public LocalDateTime getWhen() { - return when; - } - - public static DataType of(final LocalDateTime when) { - return new StartingData(when); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java b/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java deleted file mode 100644 index 976fdc4e941e..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus.data; - -import com.iluwatar.databus.AbstractDataType; -import com.iluwatar.databus.DataType; - -import java.time.LocalDateTime; - -/** - * An event raised when applications stops, containing the stop time of the application. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class StoppingData extends AbstractDataType { - - private final LocalDateTime when; - - public StoppingData(LocalDateTime when) { - this.when = when; - } - - public LocalDateTime getWhen() { - return when; - } - - public static DataType of(final LocalDateTime when) { - return new StoppingData(when); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java b/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java deleted file mode 100644 index a8ee94ad5403..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus.members; - -import com.iluwatar.databus.DataType; -import com.iluwatar.databus.Member; -import com.iluwatar.databus.data.MessageData; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Logger; - -/** - * Receiver of Data-Bus events that collects the messages from each {@link MessageData}. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class MessageCollectorMember implements Member { - - private static final Logger LOGGER = Logger.getLogger(MessageCollectorMember.class.getName()); - - private final String name; - - private List messages = new ArrayList<>(); - - public MessageCollectorMember(String name) { - this.name = name; - } - - @Override - public void accept(final DataType data) { - if (data instanceof MessageData) { - handleEvent((MessageData) data); - } - } - - private void handleEvent(MessageData data) { - LOGGER.info(String.format("%s sees message %s", name, data.getMessage())); - messages.add(data.getMessage()); - } - - public List getMessages() { - return Collections.unmodifiableList(messages); - } -} diff --git a/data-bus/src/main/java/com/iluwatar/databus/members/StatusMember.java b/data-bus/src/main/java/com/iluwatar/databus/members/StatusMember.java deleted file mode 100644 index 803e2df205c3..000000000000 --- a/data-bus/src/main/java/com/iluwatar/databus/members/StatusMember.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.databus.members; - -import com.iluwatar.databus.DataType; -import com.iluwatar.databus.Member; -import com.iluwatar.databus.data.MessageData; -import com.iluwatar.databus.data.StartingData; -import com.iluwatar.databus.data.StoppingData; - -import java.time.LocalDateTime; -import java.util.logging.Logger; - -/** - * Receiver of Data-Bus events. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class StatusMember implements Member { - - private static final Logger LOGGER = Logger.getLogger(StatusMember.class.getName()); - - private final int id; - - private LocalDateTime started; - - private LocalDateTime stopped; - - public StatusMember(int id) { - this.id = id; - } - - @Override - public void accept(final DataType data) { - if (data instanceof StartingData) { - handleEvent((StartingData) data); - } else if (data instanceof StoppingData) { - handleEvent((StoppingData) data); - } - } - - private void handleEvent(StartingData data) { - started = data.getWhen(); - LOGGER.info(String.format("Receiver #%d sees application started at %s", id, started)); - } - - private void handleEvent(StoppingData data) { - stopped = data.getWhen(); - LOGGER.info(String.format("Receiver #%d sees application stopping at %s", id, stopped)); - LOGGER.info(String.format("Receiver #%d sending goodbye message", id)); - data.getDataBus().publish(MessageData.of(String.format("Goodbye cruel world from #%d!", id))); - } - - public LocalDateTime getStarted() { - return started; - } - - public LocalDateTime getStopped() { - return stopped; - } -} diff --git a/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java b/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java deleted file mode 100644 index f986e1681f2c..000000000000 --- a/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java +++ /dev/null @@ -1,74 +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.databus; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.never; - -/** - * Tests for {@link DataBus}. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class DataBusTest { - - @Mock - private Member member; - - @Mock - private DataType event; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void publishedEventIsReceivedBySubscribedMember() { - //given - final DataBus dataBus = DataBus.getInstance(); - dataBus.subscribe(member); - //when - dataBus.publish(event); - //then - then(member).should().accept(event); - } - - @Test - public void publishedEventIsNotReceivedByMemberAfterUnsubscribing() { - //given - final DataBus dataBus = DataBus.getInstance(); - dataBus.subscribe(member); - dataBus.unsubscribe(member); - //when - dataBus.publish(event); - //then - then(member).should(never()).accept(event); - } - -} diff --git a/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java b/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java deleted file mode 100644 index 35deeb5fbcc7..000000000000 --- a/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java +++ /dev/null @@ -1,62 +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.databus.members; - -import com.iluwatar.databus.data.MessageData; -import com.iluwatar.databus.data.StartingData; -import org.junit.Assert; -import org.junit.Test; - -import java.time.LocalDateTime; - -/** - * Tests for {@link MessageCollectorMember}. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class MessageCollectorMemberTest { - - @Test - public void collectMessageFromMessageData() { - //given - final String message = "message"; - final MessageData messageData = new MessageData(message); - final MessageCollectorMember collector = new MessageCollectorMember("collector"); - //when - collector.accept(messageData); - //then - Assert.assertTrue(collector.getMessages().contains(message)); - } - - @Test - public void collectIgnoresMessageFromOtherDataTypes() { - //given - final StartingData startingData = new StartingData(LocalDateTime.now()); - final MessageCollectorMember collector = new MessageCollectorMember("collector"); - //when - collector.accept(startingData); - //then - Assert.assertEquals(0, collector.getMessages().size()); - } - -} diff --git a/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java b/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java deleted file mode 100644 index d5afbd13293a..000000000000 --- a/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java +++ /dev/null @@ -1,79 +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.databus.members; - -import com.iluwatar.databus.DataBus; -import com.iluwatar.databus.data.MessageData; -import com.iluwatar.databus.data.StartingData; -import com.iluwatar.databus.data.StoppingData; -import org.junit.Assert; -import org.junit.Test; - -import java.time.LocalDateTime; -import java.time.Month; - -/** - * Tests for {@link StatusMember}. - * - * @author Paul Campbell (pcampbell@kemitix.net) - */ -public class StatusMemberTest { - - @Test - public void statusRecordsTheStartTime() { - //given - final LocalDateTime startTime = LocalDateTime.of(2017, Month.APRIL, 1, 19, 9); - final StartingData startingData = new StartingData(startTime); - final StatusMember statusMember = new StatusMember(1); - //when - statusMember.accept(startingData); - //then - Assert.assertEquals(startTime, statusMember.getStarted()); - } - - @Test - public void statusRecordsTheStopTime() { - //given - final LocalDateTime stop = LocalDateTime.of(2017, Month.APRIL, 1, 19, 12); - final StoppingData stoppingData = new StoppingData(stop); - stoppingData.setDataBus(DataBus.getInstance()); - final StatusMember statusMember = new StatusMember(1); - //when - statusMember.accept(stoppingData); - //then - Assert.assertEquals(stop, statusMember.getStopped()); - } - - @Test - public void statusIgnoresMessageData() { - //given - final MessageData messageData = new MessageData("message"); - final StatusMember statusMember = new StatusMember(1); - //when - statusMember.accept(messageData); - //then - Assert.assertNull(statusMember.getStarted()); - Assert.assertNull(statusMember.getStopped()); - } - -} diff --git a/data-mapper/README.md b/data-mapper/README.md deleted file mode 100644 index 362f19c51d14..000000000000 --- a/data-mapper/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Data Mapper -folder: data-mapper -permalink: /patterns/data-mapper/ -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/data-mapper.png "Data Mapper") - -## Applicability -Use the Data Mapper in any of the following situations - -* when you want to decouple data objects from DB access layer -* when you want to write multiple data retrieval/persistence implementations - -## Credits - -* [Data Mapper](http://richard.jp.leguen.ca/tutoring/soen343-f2010/tutorials/implementing-data-mapper/) diff --git a/data-mapper/etc/data-mapper.png b/data-mapper/etc/data-mapper.png deleted file mode 100644 index bcda8054aac81eb6fb2bb564053a7e1fcd93c003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40158 zcmeFZcT`i`x;GpvA|fgxO0~j91hzszq={Xs(gj24NNCcfBq#`MMPMsE^xnIK5<(P2 zq_+@CfQSeILI^Dc5|X?Nz31F>+xve1e>Y=fEYQKqnscrBJij*c=8@ig-orwNK_C$C z!v}W^K%jki5NL1ap@YD`AZBOBfx{jzgZsBY<-H;cz%Tn9HFY&XpsE<29qR+Y@7&KH zJn;g7j(*vF?}?W_DhvXpdOf_OY4pO9!s2@&GGa{(J zN-fX39lCxMGFdHm^PV0|<<9%Rc%=Ra!$n{GaALtM;lg36vZI5qBd6O&aNn^{%k*{C z3%%*dX~__Z4M~ZVs_erP4qPz^^yx!WA4l-lk5~457TW#c<>^DfxPjM~o0Ypm2c10_ z0^U7>t{yAhvwQsOl@;&q@#c~J&bvpD%~`X3yT@bu{`VCBI~V`^TmVbq|Bq|rQJvM+ zI_RZOd3kwn#y*py1xG=kpXbf?-4v+$9AG`rV!@bTdr(W#ufC6K^hFmco8!tVc` zGqcSbHm{sxzMg%gO%%>F8EF5%R3a;%ZuNrve3AlLSb5BaRIx7~U$BaD_@>d2!S=)uyv((u*J4$Ehq4Wr(Mo4g=rE}&#p zzH5qIYC%pEu9c2`E|8Zb`9Mh5>~%xe-KGv}$f6LBH}_-7g^iwgaQo0eMNtvrQfMsa zO->lWYx%o6pBRN33tV0P zX=3r?7UT;fF$z~|XG<+Amfu@~6*n)dZReiYydL91uk*83x(lj zdGlDLvG(`v*88^3)D~bUd0Y;|Hn+WT2qYiO`p)9YK0gQI@qzVeMJN6WKnT_6Nk$=*L4{hrM7r=@I+`PhU#*NjE%gedw@nh{EV4V3kvvh!`~(;I{=&6vmoh_7J^1I2 zI;ab{?h?*xDODmmId(~rU$5*0S?-DB^J`Sy*ktqi6A7LokC`3&b0ffblY7druZ{ID z1TMi;Iw&xaWuFXkqpZ`n+Cx&0-R?r{-d^T|NB;LG%#8z=glASELDBznlt*s9aqUMf)(0iOLH79nB6HOtG>sq6==vW?Tspy zJ8bs+X)!f{GHsQayLjD6?*}t|1NnY@MFeLMm0ViPgM5gV6hh+?ZsbkJiCdL@ASZT& zK{<2wn|6qa*O9qu%0v<}J3+waLQLys+f>fuIyL#)2Qw%+KODlv%LF~44!%+>Qd{ut zZgJsSitp;>fm~l&$pypPLA{d~D>J{=fAf9nil(?z#5wg3Cr}o5jFbg4K&3tan9$$@ znUNM37biL{RT?aXg_tY*nAH&_g%vII8pe88&$^8FJEzzXS}=#EtKT-zXtY?RT0`q@`A@%-eKt}KDl`I&oUNpwnF>NhQ2RVR>IZ&hK)Xowg)L)v) z7bnImy*>&%p(MBOa(hqL%fCN%y2vv0v<|Xe2SUKLR0H4I2#ppu}Za>1m#w0Gje za~4FyVs`5|Yc+=a%9UQ<-WN1$I_U}ev~~`two!rG`X?CJV7am{(R>T(3>6w(MI1MU z<&0b#f(CDinYyLCCeW4`$}WGoDCd2BMXIe_X*wvBH=S^{G~Lj&8fxf<0G}jc{Ypu! z8MVBG>K32bioB}TJx+`dO-Ix!B8L!XDnneJi7{J;7z|oK~JA+p?d0C_Pse>HWa3U+O4ObF4cn}{7Q`GdVEHZ6Hy{I?!(d~1>YgoGrZ7`fk z87_TC)hQX>;=@VMgyZE0j*e_GW_2O=<-0Hx!7*%FpLKMdd&M?A?(0tIH?h_qgv-rt z513*;dOcDUv8LkWA`HykkMG*~y5miz2P&N3+neA5?d6V+R_7P6W^t*e!i1f`A1%Q+ z+l&{FGT5VTa0ik)oRJf3h(;_KE)%08I9ckowu$L3j5q`{1?oj6Rc565_+}je;r9YX z6<0r&XgMOB$hqadvkg{)Gx;oOi4Ta(DL(mGBC9urv95tF*I?&R8QSnSu3E{#`2m}= z2egH&nZr(wD$LqHw{zDP8@-bG8PVxHY;KmDmm)RMV$+V8`lzeINsQW*nQrGs8NqG% zMr~1HPZ=Wi;qzDN)`V8c)Xd~Sw%0;L4 z>YpL3SdRGTafv;rdem=L&R1WXlGeS1b4-xAB4X;-!I3g^KZspTRY&xhP`19^r#)*5Er*}D3wDC6XaJMQ{0hM^;E>?; zz(&vQM$15ouF?Vak3e_F&TBq#aD=_ zol+goQ%tl`Yv{_ILrs`FlvH6l_LBlAl~ULfpTk}yoA&I)B0pNoQx1fm@;gQ4nhCNm z3#?F1=RsB(;}?{5^H5R?GAnUayi}iLV+*>S9BAvUj5G;jKyu@cdlWUbH6?(dvFdbB zPtA*AcNo$)lzp^_sp!IB4%ZCBk#oNSLDSd?pR;7jv%aT^FAjGRJ;?T@bRK(9r4~@G zAI+$*yb>P>w{VYNY(k$UNL`?=GN+&g=;iSxjl&*$21=A`&z0MsL7tWrUSpmo#JXd{ zOJ?Jwxg)wS)qp$ZGQNffV)zktaHom1mB5md#&eCEKJ}lR2dfG9&CU=WP*(PO_8tI1 zH>w2!Dk|q7%?RU)AUZmL%tftlCpNId*BL3`dkeeB*FEEIi5$v+V6wYL zWYM&0{C3ziklCeQD~}%hqqWh#mFe9jBkWE7N>BMajpg)$!<-_Cxi`6nP6cbHxuIQi zeA!>1w8T?d-r^%I^=c0{otTnI&)rnt8e8pSznVWNSToKND@ng<| zVY3FZgw8A8rcIh%NM%K;tKD9Yt-UYh0>(OY2l9WEvP`}`sn<;90mOo@1kpUYr0QzQF5k^Ln2 z&BhlZ(|K``{ZX3piE9~W;m*Dp1z@DafDlBSCJ|~O?;Hxbt(W4MLChHQ(zDH)%d+&E z;}KGG)i2kU;n{3ZRhmLxcW@8?XzH45C;ar}q3CnjQuT&k8#lrF8N;LAUjnPYDdyjk z)O{n>Q!-ogR>q=(e%P6a@e95~ttc7tD{m@x)~GKJDTCSZ~b74I0=WBktts?d}F48yC*$}Akp0_V@WX_q?M@tB%bVY-wShBv`dMTNH@yxUjkoMldfpZ z?Yknp>fU1PGM20SnV#U!oEMQJeYNms(htiMstmhUEThmV@?#^O->^K@5WI8rIg!hr zb@8$dZV$2_Qf}l~Qyx1bTz$_Fp6T=y<$Q4%3i*ZEx;RMYZ#X7Dx&0ndgm zj6er+#F-!2G$K=g#x5(Mr8x(e2g`3;FuH^_aN<3f?2PR#{q4Su-%G=M@zjxEF;Hdi z7`q=e=P1R-au!(u(|*uFe9VNkSXi*o;s%M>kbhr{nZz#0Ku;%Hw~eXDGF!z2a6jYC zQ7ta>#qov_*NFwg8{3@cmK=7Q2YjoXZ$2HpY`}s98>hHoblo{CTuAJiV*oP^i_2)< zY&7>%&xW#9_?Ug2)qeC%w_Fl;aBp>26OX}RwdEz%yy^b1%fd;Nur!;lkiO@cUOP?U z6S37wiZ#rQ%|y5*n>~rbzcOb`fok6Z0MPiN+p(=(IKkp<5I5R~h{N<|dNj&qtPs~5 zxS^!(Q-KIdG)2Eod2NMR#5-4_TV26a=Ap^`Qx;lnF6!Ak4&<} zrK7EQjWmExVstzNY$Ehos1U%yg@}o!BfGfh{~_d*IR7X_9wgOpWFyA>dl)s^*6ls7{Pf5x4_iHh2L3$9;SoV&V*#c#sz>gm%L8Ui<56#@WF60t0$}4JU z>Sr|N?^Rg3piH$JOaJbdEM?ZG+6&ivfH-|fZBwt8vWWrM$ka7{H%hZZ#yZ`)paA^L zS6$`BtyV*pmT#Io-{C|wMM(|v)2v&O<)d%n#3r1W)Gw;3GF`}m%r%5{l@;L(^OrJ_ zn22cJZXr6Jq77NmPON8rsK9J^EinTwQq_)hwzSvxD<#4!BAdiYji06hQ}Pma2T;r6 zT=BUC+)=DU>2~HRoqCBXN`mg;mp*rYNH~qJ#4bUX6v5 zu%Xn!1?3L0h_TO38h>954Ea;!L{-!1>gdS8-y3tWynHX@wI>lpBhBBu;wCIt#17go zB=ZQlt)^RycxoAb4!BB$PTcu@5yihQqUT`SLgdt&!V)knpf~riZ~&%yY{;>DW|qfa z@xhHAbi9yS)|pA?TNTQh>gQ{d<-flvZyo&0?}O^pLYWY1bnQ>{9V=~Dv4VJxs$ZiuM7O;rR8@Q*MV!PUb#9hRj@6G zKOn0&`)m3i|BLvLcEu*G3a%=*+=tm?TvZMJbda%2NQ$UKcSc%aXHZ^z&(6Z1PI42t z0x|;fb>6$4-zC%298Q)$;XY$DdPWF_5)6}FxcOpIRFXxrG&Y4)EXfK9i$5yvE2mQY zN-0g@-bOz6QI4Co&TeJBy%?lhWnZG7Y7xM6(`25ekHxTD!lPSh&|X5tq-iQeFp$!Q za?0?sGchz&?57UbyW(9lQlO`9+$-_;zTGrZa}Bl-xDR*v_fn?a5ID?trmYhX3IXGD z!E8}LLm7_A{|*9`qHJ0($uN&;fk0Myk8FWr^jb)8SkgH|+t&^pAQ0GBGcsRUJ&=`42LT$NIHQPu%XussCpY7#RXcHCg(9xP_0q z9cIS{kjW%kyT*d!;gwQ+qQqGy7NZcop^u{hs3Iapt+=<+}?oQ7m?5!tr#f|gvh zuYpUT{Zf2@)0hasOM?waL=LxF&`iuk&Qg$D0CD)A<4Knx1ONU0cMW54RueZd6ZokPX z@9_2wFb|ESJS%G72kLsaD|bKIV_^tsws+Z^{=y(OR{!#}#uYd8(GAKlZr;vvG<9TQ zfM;>ZVre__5Atc7`K3h4$a4OMSd>HztOdFsyv^er;I#B0mN@_VVNGaBc0MfkjAG)>rmL$-nN!zFUVW4y zmL;e2l%E78>~>hQJE*y0=RYkhYOhoMr_Ik=rIAuL>a{o*37=Mggidi3(}{7+*M34s=BnxXG}7QgeW19fDoy ztIoWu1pPpKjl)0Z^=Y4nIyuKVqz~q*H9$)<^3@h-ju2gAV(N{S9tU}s%87!3P15Xe zsXzF6WH@Jpo^JfKN;f4o^U z$I;-s~a;`^sT`}+BnTWZ5*xNr@E1uQfJ?m25^01#q?p?>PODK4U6s#FP9rd zXRzJK>%R9WT)zH%T5j#HXO9MFXhy--5w$S~bszU!Jph+s^=q6se6Z(s)?B)qh9-94 zFA7(?jcG+?jKd4optX91gR)_$Lp{jr>ExUFnYHu`%xzCxpvah?Zxwx1U9Lv%N*gq2 zCZ(Kv%K}Reff{^c1=moq;^ytT=Y4D2%6+$9b2v)WniH1}b@Ds9YLl{&d>b&vx5uKw z@drbwmdVVws`!@#z507Qd%$+;xVyWWTRerX7RY#)Z$Qw3_Fv1GywDmroM31yb`HNf zN`pv&uIw&O*f&Q>iCU*tUbS?cMT#(WaalK|JE$do%s$N5=^Ne*JT63T%Fk?L$RPQr zbu`-FQ;_MN&O)1Cz*(Ygz1ch{!;0nO!5PU&JA$J(9{c8TVMU%R`^j_9^pPEfA@>b` zUL68Ew+-d~ItG)fj`U@HU_Ip(hCwpbt|Z%@uI6$L(Smkb7FNzqr(C@&V%l6tA6=F% zrY_k~J=QgA$}*i+7jZh}j^a#)hFsFyhu-3JbE7S)SLC*8W8^Kxrf5lA?8jN=Q=$X? z$(z9@!cOo;oxH;})UBTM))Tt05vg^o2JQ>G8-7>J`IC#Iot24em$socne5X?URFkaArM^Nn(VaA5#gcP>@GJ-JZ#%sES;lBjYVwddOPCqAq*w`)II3v9G^7hRP$%@@z(C4G+i`)%RJ zn0($pE-@PNU8A589YeDHbLl^o`243wrWBmI)vz0r(XHo+GaulNT`yuNEnTgY}|gh=hrja-vK&j%#xEN){OCD%7?<7?z{=BvW- zHPb3)>D(k`LKTw_zS+v;rAoihd(n{6LQLsDP+MuQoX&zJS>}cdgHCDg4$HGIK}ErD z`>iY#JE!lyuvY6_-Ysk4=d#|npzW`l1Rd@+xPh>xuP^WX{4BLJTRPnj*9g6lFZ zhml=VYJFxL;4fxQDRI_jl_sm}Pm~4bc2}xqAtK8)W>VkQn#hBS_}A2-N@E0nb{8pg-333~D+zosZv`LZ%w!MID&(l7dMDG5ae#dIyH zSj4I2>res;QG8vOhrT2`@#>)BAL5Pr)J>0qwD0~JdJr{dymHz%4Wm$@;yzaB=hj4; zQ<|u5lZouv-{GRs&X084=zY8r;=Jp1~3Je8e$fS}|Vjd`bzoZa;DX_9DgBld7Xcx&s#sr5^c9-inf5q&60 z${iD}oEJjBwy1_W*9^?yG<-~=YC6Bc?D#Z(zmBul-j{jB7Ju&egFf9b1zz|L>ps)o z#W8nGCR3x{I0mQm?E9NZ_6GsG6d`d!eus_H74z;dkHL@$sQ+rrcWgjqP@KxSx+YnkcfKcLr_i)TE*?WEV zWjsL9F9V`*u{iuc!>j+`f0tek3~lc3caJQ7p1LNI1s_Xc3M|#Va}|VJn&nk+f$+Ob z4fF|y#N;{!`?krnH!meE*Z<7fQ^yE`9GS*tpX#SsepNV1MNjw zNaUjFAbxEQcaT8Kz-K~f&JiVEeXc+~uJ|VJp-|J)xQiPm^+q21%*K%@T^2)9%@nV> z?fb@${6$4NmuTH!%+Nb%s)c4ar;i0HdVm4*?<^RfWLX;WOlcv&5k z*|}@H4TK=2IMZv=OOZ~_y-i5f3s3nS^Ifog#*49ysqp)e&2=8p{3S)~5x&_S3nNdo zP(&bW93mrTe%nDmDis#gi_x1{+w4TORg~Bwq0yX5=mp zJ_4F=$anE}Eo@zV(OmFqC6kW6&ozm?JH{cg9hDD_=E-FPDzFa4gF8)Are3Lm$_M(M zziVhl`Tx*{;+;oGJ}|1f+IoMe+f;&p0IqmEn1^9tZpm9BEpM2gKlXN!K4yoSNnihn zTw~biiKygk?n5{El5TAw}yW> z%rFqT%X}xKsBn)4KxO0BzhpGZJ5rmIHeah}iE0XzbBn_r2$uXKE4*F}z&=!d8QxR)Dh^Sx7Q0zWQPFjIU%t%^}+GueU2?}=+L zvz6<&6L-WXs}^QGBxtpk{S0ZKPs|`wRWo?|d$?){B5M{wqn|_@Pvg?Y^qxVpeBQdN z{Ft-J ztV<=`Q)Ww}in<3`cSf?`p1|RCjgoj|N7D;-9Tr7YFq5cO4`bvOp$-B z>e()plpDq6fRRd0#eNcYkTr}Ii9;i8Y7nueQwlHiLX)@s-P4})dOHM?y49mE8=eux z*Fzo#;}6V*%`ED5J6GmF4FSPy9J!FnLQ?jF@t2}C0!8kFpIK_7Bt$^4-S`!rTV+F^ zz2C}pbcdgB!4@j+#Yq5y0}Vnm2%n=Fw3Z6)QXpp#*DF_-?=bx5k73yo((9AmF?ztf zfAi(|lfdPc8vV^{Qs-G@I>B_BmNJ zTga;kK9vIDP5?7l%I|vwx8vl>Me#R9n>5Z9-@*2(qV82ZlSxbNT$D67Qf@zesi{JX zZgK08%Dl$L7iGPPBQz}H4-)Y~vd~Q6aR2p^$j#u7Wy)gjZ%mLHM(j+n6R?RKd?v5& ziz%%>|JrUgJ+tlg)IucN@8YfXzXe-dL1JEgk;P-Z1k=pXRf5CMWSU=5*$|rtR2v3V zJ+j%cN@-d{MfylthDK>xA7Y@V0%^dy(drU4)oqAeDyN5#3>a@@>r&yAe>4Ry){~LE zf1z1-m%_4trZPg1R@nM0X{;≀G`|+$$&(X4Bxlnj6(385V$r3EXY7f;H#DF5Xf7 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 diff --git a/data-mapper/etc/data-mapper.ucls b/data-mapper/etc/data-mapper.ucls deleted file mode 100644 index 2467983ce212..000000000000 --- a/data-mapper/etc/data-mapper.ucls +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/data-mapper/etc/data-mapper.urm.puml b/data-mapper/etc/data-mapper.urm.puml deleted file mode 100644 index 041cbb07b331..000000000000 --- a/data-mapper/etc/data-mapper.urm.puml +++ /dev/null @@ -1,42 +0,0 @@ -@startuml -package com.iluwatar.datamapper { - class App { - - log : Logger {static} - - App() - + main(args : String[]) {static} - } - class Student { - - grade : char - - name : String - - serialVersionUID : long {static} - - studentId : int - + Student(studentId : int, name : String, grade : char) - + equals(inputObject : Object) : boolean - + getGrade() : char - + getName() : String - + getStudentId() : int - + hashCode() : int - + setGrade(grade : char) - + setName(name : String) - + setStudentId(studentId : int) - + toString() : String - } - interface StudentDataMapper { - + delete(Student) {abstract} - + find(int) : Optional {abstract} - + insert(Student) {abstract} - + update(Student) {abstract} - } - class StudentDataMapperImpl { - - students : List - + StudentDataMapperImpl() - + delete(studentToBeDeleted : Student) - + find(studentId : int) : Optional - + getStudents() : List - + insert(studentToBeInserted : Student) - + update(studentToBeUpdated : Student) - } -} -StudentDataMapperImpl --> "-students" Student -StudentDataMapperImpl ..|> StudentDataMapper -@enduml \ No newline at end of file diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml deleted file mode 100644 index 66a0e469e0e4..000000000000 --- a/data-mapper/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - data-mapper - - - junit - junit - test - - - log4j - log4j - - - diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/App.java b/data-mapper/src/main/java/com/iluwatar/datamapper/App.java deleted file mode 100644 index 5fcd0d9ea04c..000000000000 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/App.java +++ /dev/null @@ -1,77 +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.datamapper; - -import java.util.Optional; - -import org.apache.log4j.Logger; - -/** - * 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 Logger log = Logger.getLogger(App.class); - - /** - * Program entry point. - * - * @param args command line args. - */ - public static void main(final String... args) { - - /* Create new data mapper for type 'first' */ - final StudentDataMapper mapper = new StudentDataMapperImpl(); - - /* Create new student */ - Student student = new Student(1, "Adam", 'A'); - - /* Add student in respectibe store */ - mapper.insert(student); - - log.debug("App.main(), student : " + student + ", is inserted"); - - /* Find this student */ - final Optional studentToBeFound = mapper.find(student.getStudentId()); - - log.debug("App.main(), student : " + studentToBeFound + ", is searched"); - - /* Update existing student object */ - student = new Student(student.getStudentId(), "AdamUpdated", 'A'); - - /* Update student in respectibe db */ - mapper.update(student); - - log.debug("App.main(), student : " + student + ", is updated"); - log.debug("App.main(), student : " + student + ", is going to be deleted"); - - /* Delete student in db */ - mapper.delete(student); - } - - private App() {} -} diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java b/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java deleted file mode 100644 index a6995b06d6fe..000000000000 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java +++ /dev/null @@ -1,42 +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.datamapper; - -/** - * Using Runtime Exception for avoiding dependancy on implementation exceptions. This helps in - * decoupling. - * - * @author amit.dixit - * - */ -public final class DataMapperException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** - * Constructs a new runtime exception with the specified detail message. The cause is not - * initialized, and may subsequently be initialized by a call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for later retrieval by the - * {@link #getMessage()} method. - */ - public DataMapperException(final String message) { - super(message); - } -} diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/Student.java b/data-mapper/src/main/java/com/iluwatar/datamapper/Student.java deleted file mode 100644 index d709833aac6d..000000000000 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/Student.java +++ /dev/null @@ -1,142 +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.datamapper; - - -import java.io.Serializable; - -/** - * Class defining Student - */ -public final class Student implements Serializable { - - private static final long serialVersionUID = 1L; - - private int studentId; - private String name; - private char grade; - - - /** - * Use this constructor to create a Student with all details - * - * @param studentId as unique student id - * @param name as student name - * @param grade as respective grade of student - */ - public Student(final int studentId, final String name, final char grade) { - super(); - - this.studentId = studentId; - this.name = name; - this.grade = grade; - } - - /** - * - * @return the student id - */ - public int getStudentId() { - return studentId; - } - - /** - * - * @param studentId as unique student id - */ - public void setStudentId(final int studentId) { - this.studentId = studentId; - } - - /** - * - * @return name of student - */ - public String getName() { - return name; - } - - /** - * - * @param name as 'name' of student - */ - public void setName(final String name) { - this.name = name; - } - - /** - * - * @return grade of student - */ - public char getGrade() { - return grade; - } - - /** - * - * @param grade as 'grade of student' - */ - public void setGrade(final char grade) { - this.grade = grade; - } - - /** - * - */ - @Override - public boolean equals(final Object inputObject) { - - boolean isEqual = false; - - /* Check if both objects are same */ - if (this == inputObject) { - - isEqual = true; - } else if (inputObject != null && getClass() == inputObject.getClass()) { - - final Student inputStudent = (Student) inputObject; - - /* If student id matched */ - if (this.getStudentId() == inputStudent.getStudentId()) { - - isEqual = true; - } - } - - return isEqual; - } - - /** - * - */ - @Override - public int hashCode() { - - /* Student id is assumed to be unique */ - return this.getStudentId(); - } - - /** - * - */ - @Override - public String toString() { - return "Student [studentId=" + studentId + ", name=" + name + ", grade=" + grade + "]"; - } -} diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapper.java b/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapper.java deleted file mode 100644 index cb93f46973fe..000000000000 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapper.java +++ /dev/null @@ -1,35 +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.datamapper; - -import java.util.Optional; - -/** - * Interface lists out the possible behaviour for all possible student mappers - */ -public interface StudentDataMapper { - - Optional find(int studentId); - - void insert(Student student) throws DataMapperException; - - void update(Student student) throws DataMapperException; - - void delete(Student student) throws DataMapperException; -} diff --git a/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapperImpl.java b/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapperImpl.java deleted file mode 100644 index 685a439ac60c..000000000000 --- a/data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapperImpl.java +++ /dev/null @@ -1,105 +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.datamapper; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * Implementation of Actions on Students Data - */ -public final class StudentDataMapperImpl implements StudentDataMapper { - - /* Note: Normally this would be in the form of an actual database */ - private List students = new ArrayList<>(); - - @Override - public Optional find(int studentId) { - - /* Compare with existing students */ - for (final Student student : this.getStudents()) { - - /* Check if student is found */ - if (student.getStudentId() == studentId) { - - return Optional.of(student); - } - } - - /* Return empty value */ - return Optional.empty(); - } - - @Override - public void update(Student studentToBeUpdated) throws DataMapperException { - - - /* Check with existing students */ - if (this.getStudents().contains(studentToBeUpdated)) { - - /* Get the index of student in list */ - final int index = this.getStudents().indexOf(studentToBeUpdated); - - /* Update the student in list */ - this.getStudents().set(index, studentToBeUpdated); - - } else { - - /* Throw user error after wrapping in a runtime exception */ - throw new DataMapperException("Student [" + studentToBeUpdated.getName() + "] is not found"); - } - } - - @Override - public void insert(Student studentToBeInserted) throws DataMapperException { - - /* Check with existing students */ - if (!this.getStudents().contains(studentToBeInserted)) { - - /* Add student in list */ - this.getStudents().add(studentToBeInserted); - - } else { - - /* Throw user error after wrapping in a runtime exception */ - throw new DataMapperException("Student already [" + studentToBeInserted.getName() + "] exists"); - } - } - - @Override - public void delete(Student studentToBeDeleted) throws DataMapperException { - - /* Check with existing students */ - if (this.getStudents().contains(studentToBeDeleted)) { - - /* Delete the student from list */ - this.getStudents().remove(studentToBeDeleted); - - } else { - - /* Throw user error after wrapping in a runtime exception */ - throw new DataMapperException("Student [" + studentToBeDeleted.getName() + "] is not found"); - } - } - - public List getStudents() { - return this.students; - } -} diff --git a/data-mapper/src/main/resources/log4j.xml b/data-mapper/src/main/resources/log4j.xml deleted file mode 100644 index 14f043ff7576..000000000000 --- a/data-mapper/src/main/resources/log4j.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/data-mapper/src/test/java/com/iluwatar/datamapper/AppTest.java b/data-mapper/src/test/java/com/iluwatar/datamapper/AppTest.java deleted file mode 100644 index f2858100efbb..000000000000 --- a/data-mapper/src/test/java/com/iluwatar/datamapper/AppTest.java +++ /dev/null @@ -1,34 +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.datamapper; - -import com.iluwatar.datamapper.App; -import org.junit.Test; - -/** - * Tests that Data-Mapper example runs without errors. - */ -public final class AppTest { - - @Test - public void test() { - final String[] args = {}; - App.main(args); - } -} diff --git a/data-mapper/src/test/java/com/iluwatar/datamapper/DataMapperTest.java b/data-mapper/src/test/java/com/iluwatar/datamapper/DataMapperTest.java deleted file mode 100644 index 17f4d3922447..000000000000 --- a/data-mapper/src/test/java/com/iluwatar/datamapper/DataMapperTest.java +++ /dev/null @@ -1,73 +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.datamapper; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.iluwatar.datamapper.Student; -import com.iluwatar.datamapper.StudentDataMapper; -import com.iluwatar.datamapper.StudentDataMapperImpl; - -/** - * 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 DataMapperTest { - - /** - * This test verify that first data mapper is able to perform all CRUD operations on Student - */ - @Test - public void testFirstDataMapper() { - - /* Create new data mapper of first type */ - final StudentDataMapper mapper = new StudentDataMapperImpl(); - - /* Create new student */ - Student student = new Student(1, "Adam", 'A'); - - /* Add student in respectibe db */ - mapper.insert(student); - - /* Check if student is added in db */ - assertEquals(student.getStudentId(), mapper.find(student.getStudentId()).get().getStudentId()); - - /* Update existing student object */ - student = new Student(student.getStudentId(), "AdamUpdated", 'A'); - - /* Update student in respectibe db */ - mapper.update(student); - - /* Check if student is updated in db */ - assertEquals(mapper.find(student.getStudentId()).get().getName(), "AdamUpdated"); - - /* Delete student in db */ - mapper.delete(student); - - /* Result should be false */ - assertEquals(false, mapper.find(student.getStudentId()).isPresent()); - } -} diff --git a/data-mapper/src/test/java/com/iluwatar/datamapper/StudentTest.java b/data-mapper/src/test/java/com/iluwatar/datamapper/StudentTest.java deleted file mode 100644 index ec35b21de8f9..000000000000 --- a/data-mapper/src/test/java/com/iluwatar/datamapper/StudentTest.java +++ /dev/null @@ -1,55 +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.datamapper; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Tests {@link Student}. - */ -public final class StudentTest { - - @Test - /** - * This API tests the equality behaviour of Student object - * Object Equality should work as per logic defined in equals method - * - * @throws Exception if any execution error during test - */ - public void testEquality() throws Exception { - - /* Create some students */ - final Student firstStudent = new Student(1, "Adam", 'A'); - final Student secondStudent = new Student(2, "Donald", 'B'); - final Student secondSameStudent = new Student(2, "Donald", 'B'); - final Student firstSameStudent = firstStudent; - - /* Check equals functionality: should return 'true' */ - assertTrue(firstStudent.equals(firstSameStudent)); - - /* Check equals functionality: should return 'false' */ - assertFalse(firstStudent.equals(secondStudent)); - - /* Check equals functionality: should return 'true' */ - assertTrue(secondStudent.equals(secondSameStudent)); - } -} diff --git a/data-transfer-object/README.md b/data-transfer-object/README.md deleted file mode 100644 index 7fe2d9cdce05..000000000000 --- a/data-transfer-object/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: Data Transfer Object -folder: data-transfer-object -permalink: /patterns/data-transfer-object/ -pumlid: RSh14SCW30NHLk82GFTq8uDYum71I5zn-t41kUtCswrfwL4bhBzEOFcRoFZEHyCPUxXOcGfHv387jHutWuqk_dAguktGj1WGKwV1_WJLvqWmLl-8fRbVKa22yXTosCWhHly1 -categories: Architectural -tags: - - Java - - KISS - - YAGNI - - Difficulty-Beginner ---- - -## Intent -Pass data with multiple attributes in one shot from client to server, -to avoid multiple calls to remote server. - -![alt text](./etc/data-transfer-object.urm.png "data-transfer-object") - -## Applicability -Use the Data Transfer Object pattern when - -* The client is asking for multiple information. And the information is related. -* When you want to boost the performance to get resources. -* You want reduced number of remote calls. - -## Credits - -* [Design Pattern - Transfer Object Pattern](https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm) -* [Data Transfer Object](https://msdn.microsoft.com/en-us/library/ff649585.aspx) diff --git a/data-transfer-object/etc/data-transfer-object.ucls b/data-transfer-object/etc/data-transfer-object.ucls deleted file mode 100644 index 15f777aad60c..000000000000 --- a/data-transfer-object/etc/data-transfer-object.ucls +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/data-transfer-object/etc/data-transfer-object.urm.png b/data-transfer-object/etc/data-transfer-object.urm.png deleted file mode 100644 index 46facff8dee4c45b2c6bbafb7ea6c3b6be80dfc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19132 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 R(&9dol~j_*6aUNm{{y~+`I`U$ diff --git a/data-transfer-object/etc/data-transfer-object.urm.puml b/data-transfer-object/etc/data-transfer-object.urm.puml deleted file mode 100644 index 2c21dd21cfda..000000000000 --- a/data-transfer-object/etc/data-transfer-object.urm.puml +++ /dev/null @@ -1,26 +0,0 @@ -@startuml -package com.iluwatar.datatransfer { - class CustomerClientApp { - + CustomerClientApp() - + main(args : String[]) {static} - - printCustomerDetails(allCustomers : List) {static} - } - class CustomerDto { - - firstName : String - - id : String - - lastName : String - + CustomerDto(id : String, firstName : String, lastName : String) - + getFirstName() : String - + getId() : String - + getLastName() : String - } - class CustomerResource { - - customers : List - + CustomerResource(customers : List) - + delete(customerId : String) - + getAllCustomers() : List - + save(customer : CustomerDto) - } -} -CustomerResource --> "-customers" CustomerDto -@enduml \ No newline at end of file diff --git a/data-transfer-object/pom.xml b/data-transfer-object/pom.xml deleted file mode 100644 index b0fd66da3513..000000000000 --- a/data-transfer-object/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - data-transfer-object - - - junit - junit - test - - - log4j - log4j - - - diff --git a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerClientApp.java b/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerClientApp.java deleted file mode 100644 index f5fcebe03a0b..000000000000 --- a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerClientApp.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.datatransfer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * The Data Transfer Object pattern is a design pattern in which an data transfer object is used to serve related - * information together to avoid multiple call for each piece of information. - *

- * In this example, ({@link CustomerClientApp}) as as customer details consumer i.e. client to request for - * customer details to server. - *

- * CustomerResource ({@link CustomerResource}) act as server to serve customer information. - * And The CustomerDto ({@link CustomerDto} is data transfer object to share customer information. - */ -public class CustomerClientApp { - - private static final Logger LOGGER = LoggerFactory.getLogger(CustomerClientApp.class); - - /** - * Method as act client and request to server for details. - * - * @param args program argument. - */ - public static void main(String[] args) { - List customers = new ArrayList<>(); - CustomerDto customerOne = new CustomerDto("1", "Kelly", "Brown"); - CustomerDto customerTwo = new CustomerDto("2", "Alfonso", "Bass"); - customers.add(customerOne); - customers.add(customerTwo); - - CustomerResource customerResource = new CustomerResource(customers); - - LOGGER.info("All customers:-"); - List allCustomers = customerResource.getAllCustomers(); - printCustomerDetails(allCustomers); - - LOGGER.info("----------------------------------------------------------"); - - LOGGER.info("Deleting customer with id {1}"); - customerResource.delete(customerOne.getId()); - allCustomers = customerResource.getAllCustomers(); - printCustomerDetails(allCustomers); - - LOGGER.info("----------------------------------------------------------"); - - LOGGER.info("Adding customer three}"); - CustomerDto customerThree = new CustomerDto("3", "Lynda", "Blair"); - customerResource.save(customerThree); - allCustomers = customerResource.getAllCustomers(); - printCustomerDetails(allCustomers); - } - - private static void printCustomerDetails(List allCustomers) { - allCustomers.forEach(customer -> LOGGER.info(customer.getFirstName())); - } -} diff --git a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerDto.java b/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerDto.java deleted file mode 100644 index 7dedf891c087..000000000000 --- a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerDto.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.datatransfer; - -/** - * {@link CustomerDto} is a data transfer object POJO. Instead of sending individual information to client - * We can send related information together in POJO. - *

- * Dto will not have any business logic in it. - */ -public class CustomerDto { - private final String id; - private final String firstName; - private final String lastName; - - /** - * @param id customer id - * @param firstName customer first name - * @param lastName customer last name - */ - public CustomerDto(String id, String firstName, String lastName) { - this.id = id; - this.firstName = firstName; - this.lastName = lastName; - } - - public String getId() { - return id; - } - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } -} diff --git a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerResource.java b/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerResource.java deleted file mode 100644 index a4926d08c134..000000000000 --- a/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerResource.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.datatransfer; - -import java.util.List; - -/** - * The resource class which serves customer information. - * This class act as server in the demo. Which has all customer details. - */ -public class CustomerResource { - private List customers; - - /** - * @param customers initialize resource with existing customers. Act as database. - */ - public CustomerResource(List customers) { - this.customers = customers; - } - - /** - * @return : all customers in list. - */ - public List getAllCustomers() { - return customers; - } - - /** - * @param customer save new customer to list. - */ - public void save(CustomerDto customer) { - customers.add(customer); - } - - /** - * @param customerId delete customer with id {@code customerId} - */ - public void delete(String customerId) { - customers.removeIf(customer -> customer.getId().equals(customerId)); - } -} \ No newline at end of file diff --git a/data-transfer-object/src/test/java/com/iluwatar/datatransfer/CustomerResourceTest.java b/data-transfer-object/src/test/java/com/iluwatar/datatransfer/CustomerResourceTest.java deleted file mode 100644 index adfe66b7dbda..000000000000 --- a/data-transfer-object/src/test/java/com/iluwatar/datatransfer/CustomerResourceTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.datatransfer; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * tests {@link CustomerResource}. - */ -public class CustomerResourceTest { - @Test - public void shouldGetAllCustomers() { - CustomerDto customer = new CustomerDto("1", "Melody", "Yates"); - List customers = new ArrayList<>(); - customers.add(customer); - - CustomerResource customerResource = new CustomerResource(customers); - - List allCustomers = customerResource.getAllCustomers(); - - assertEquals(allCustomers.size(), 1); - assertEquals(allCustomers.get(0).getId(), "1"); - assertEquals(allCustomers.get(0).getFirstName(), "Melody"); - assertEquals(allCustomers.get(0).getLastName(), "Yates"); - } - - @Test - public void shouldSaveCustomer() { - CustomerDto customer = new CustomerDto("1", "Rita", "Reynolds"); - CustomerResource customerResource = new CustomerResource(new ArrayList<>()); - - customerResource.save(customer); - - List allCustomers = customerResource.getAllCustomers(); - assertEquals(allCustomers.get(0).getId(), "1"); - assertEquals(allCustomers.get(0).getFirstName(), "Rita"); - assertEquals(allCustomers.get(0).getLastName(), "Reynolds"); - } - - @Test - public void shouldDeleteCustomer() { - CustomerDto customer = new CustomerDto("1", "Terry", "Nguyen"); - List customers = new ArrayList<>(); - customers.add(customer); - - CustomerResource customerResource = new CustomerResource(customers); - - customerResource.delete(customer.getId()); - - List allCustomers = customerResource.getAllCustomers(); - assertEquals(allCustomers.size(), 0); - } - -} \ No newline at end of file diff --git a/delegation/README.md b/delegation/README.md deleted file mode 100644 index b294607ec92a..000000000000 --- a/delegation/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: Delegation -folder: delegation -permalink: /patterns/delegation/ -pumlid: JSV14GCX20NGLf82LkxfXbN69OFeu2VRVdBCxRsdUhLiac6F2rZxHHHybwwuyimjKQT37ANEGMfvCpZepHy-ccpjVYm697pJuFq3DJ7f39rEWlhNaZ7Aoc5V -categories: Behavioral -tags: - - Java - - Difficulty-Beginner ---- - -## Also known as -Proxy Pattern - -## Intent -It is a technique where an object expresses certain behavior to the outside but in -reality delegates responsibility for implementing that behaviour to an associated object. - -![alt text](./etc/delegation.png "Delegate") - -## Applicability -Use the Delegate pattern in order to achieve the following - -* Reduce the coupling of methods to their class -* Components that behave identically, but realize that this situation can change in the future. - -## Credits - -* [Delegate Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Delegation_pattern) -* [Proxy Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Proxy_pattern) diff --git a/delegation/etc/delegation.png b/delegation/etc/delegation.png deleted file mode 100644 index 375ef4d6b00f30f1cb7f4dccc7d47c00f77a849a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25260 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 T6<_9Y0DhD&YFsE%FuDIP#mU)$ diff --git a/delegation/etc/delegation.ucls b/delegation/etc/delegation.ucls deleted file mode 100644 index e3ce088737b2..000000000000 --- a/delegation/etc/delegation.ucls +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/delegation/etc/delegation.urm.puml b/delegation/etc/delegation.urm.puml deleted file mode 100644 index 419cf350bd30..000000000000 --- a/delegation/etc/delegation.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.delegation.simple.printers { - class CanonPrinter { - - LOGGER : Logger {static} - + CanonPrinter() - + print(message : String) - } - class EpsonPrinter { - - LOGGER : Logger {static} - + EpsonPrinter() - + print(message : String) - } - class HpPrinter { - - LOGGER : Logger {static} - + HpPrinter() - + print(message : String) - } -} -package com.iluwatar.delegation.simple { - class App { - + MESSAGE_TO_PRINT : String {static} - + App() - + main(args : String[]) {static} - } - interface Printer { - + print(String) {abstract} - } - class PrinterController { - - printer : Printer - + PrinterController(printer : Printer) - + print(message : String) - } -} -PrinterController --> "-printer" Printer -PrinterController ..|> Printer -CanonPrinter ..|> Printer -EpsonPrinter ..|> Printer -HpPrinter ..|> Printer -@enduml \ No newline at end of file diff --git a/delegation/pom.xml b/delegation/pom.xml deleted file mode 100644 index f2cb95dc167b..000000000000 --- a/delegation/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - delegation - - - - junit - junit - test - - - com.github.stefanbirkner - system-rules - test - - - \ No newline at end of file diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/App.java b/delegation/src/main/java/com/iluwatar/delegation/simple/App.java deleted file mode 100644 index 5f410d09bb8a..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/App.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.delegation.simple; - -import com.iluwatar.delegation.simple.printers.CanonPrinter; -import com.iluwatar.delegation.simple.printers.EpsonPrinter; -import com.iluwatar.delegation.simple.printers.HpPrinter; - -/** - * The delegate pattern provides a mechanism to abstract away the implementation and control of the desired action. - * The class being called in this case {@link PrinterController} is not responsible for the actual desired action, - * but is actually delegated to a helper class either {@link CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. - * The consumer does not have or require knowledge of the actual class carrying out the action, only the - * container on which they are calling. - * - * In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link CanonPrinter} they all implement - * {@link Printer}. The {@link PrinterController} class also implements {@link Printer}. However neither provide the - * functionality of {@link Printer} by printing to the screen, they actually call upon the instance of {@link Printer} - * that they were instantiated with. Therefore delegating the behaviour to another class. - */ -public class App { - - public static final String MESSAGE_TO_PRINT = "hello world"; - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - PrinterController hpPrinterController = new PrinterController(new HpPrinter()); - PrinterController canonPrinterController = new PrinterController(new CanonPrinter()); - PrinterController epsonPrinterController = new PrinterController(new EpsonPrinter()); - - hpPrinterController.print(MESSAGE_TO_PRINT); - canonPrinterController.print(MESSAGE_TO_PRINT); - epsonPrinterController.print(MESSAGE_TO_PRINT); - } - -} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java b/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java deleted file mode 100644 index ee4d54938a86..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.delegation.simple; - -import com.iluwatar.delegation.simple.printers.CanonPrinter; -import com.iluwatar.delegation.simple.printers.EpsonPrinter; -import com.iluwatar.delegation.simple.printers.HpPrinter; - -/** - * Interface that both the Controller and the Delegate will implement. - * - * @see CanonPrinter - * @see EpsonPrinter - * @see HpPrinter - */ -public interface Printer { - - /** - * Method that takes a String to print to the screen. This will be implemented on both the - * controller and the delegate allowing the controller to call the same method on the delegate class. - * - * @param message to be printed to the screen - */ - void print(final String message); -} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java b/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java deleted file mode 100644 index c54f611ee213..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.delegation.simple; - -/** - * Delegator Class to delegate the implementation of the Printer. - * This ensures two things: - * - when the actual implementation of the Printer class changes the delegation will still be operational - * - the actual benefit is observed when there are more than one implementors and they share a delegation control - */ -public class PrinterController implements Printer { - - private final Printer printer; - - public PrinterController(Printer printer) { - this.printer = printer; - } - - /** - * This method is implemented from {@link Printer} however instead on providing an - * implementation, it instead calls upon the class passed through the constructor. This is the delegate, - * hence the pattern. Therefore meaning that the caller does not care of the implementing class only the owning - * controller. - * - * @param message to be printed to the screen - */ - @Override - public void print(String message) { - printer.print(message); - } -} 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 deleted file mode 100644 index 8f024122f15f..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * this case the message to be printed is appended to "Canon Printer : " - * - * @see Printer - */ -public class CanonPrinter implements Printer { - - private static final Logger LOGGER = LoggerFactory.getLogger(CanonPrinter.class); - - /** - * {@inheritDoc} - */ - @Override - public void print(String 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 deleted file mode 100644 index fb763d21a862..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * this case the message to be printed is appended to "Epson Printer : " - * - * @see Printer - */ -public class EpsonPrinter implements Printer { - - private static final Logger LOGGER = LoggerFactory.getLogger(EpsonPrinter.class); - - /** - * {@inheritDoc} - */ - @Override - public void print(String 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 deleted file mode 100644 index d80bb7aa7c9f..000000000000 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * this case the message to be printed is appended to "HP Printer : " - * - * @see Printer - */ -public class HpPrinter implements Printer { - - private static final Logger LOGGER = LoggerFactory.getLogger(HpPrinter.class); - - /** - * {@inheritDoc} - */ - @Override - public void print(String message) { - LOGGER.info("HP Printer : {}", message); - } - -} diff --git a/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java b/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java deleted file mode 100644 index 434d94baa44e..000000000000 --- a/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.delegation.simple; - -import org.junit.Test; -/** - * Application Test Entry - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } - -} diff --git a/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java b/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java deleted file mode 100644 index fd99a30dd3cd..000000000000 --- a/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.delegation.simple; - -import static org.junit.Assert.assertEquals; - -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 java.util.LinkedList; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -/** - * Test for Delegation Pattern - */ -public class DelegateTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - private static final String MESSAGE = "Test Message Printed"; - - @Test - public void testCanonPrinter() throws Exception { - PrinterController printerController = new PrinterController(new CanonPrinter()); - printerController.print(MESSAGE); - - assertEquals("Canon Printer : Test Message Printed", appender.getLastMessage()); - } - - @Test - public void testHpPrinter() throws Exception { - PrinterController printerController = new PrinterController(new HpPrinter()); - printerController.print(MESSAGE); - - assertEquals("HP Printer : Test Message Printed", appender.getLastMessage()); - } - - @Test - public void testEpsonPrinter() throws Exception { - PrinterController printerController = new PrinterController(new EpsonPrinter()); - printerController.print(MESSAGE); - - assertEquals("Epson Printer : Test Message Printed", appender.getLastMessage()); - } - - /** - * Logging Appender - */ - 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/README.md b/dependency-injection/README.md deleted file mode 100644 index b4ec12e6b082..000000000000 --- a/dependency-injection/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Dependency Injection -folder: dependency-injection -permalink: /patterns/dependency-injection/ -pumlid: RSdB3SCW303GLPe1mFTkunWhSGG6-PEesxS3zFQajubIpyPf_NL6B7y363xra3XpJsUZgS4QbUO0wVbWeC65DvR6BeUMXH5iwZ3GVu36YxMnqgU8NamXKu63_aPD6tNbw5y0 -categories: Behavioral -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Dependency Injection is a software design pattern in which one or -more dependencies (or services) are injected, or passed by reference, into a -dependent object (or client) and are made part of the client's state. The -pattern separates the creation of a client's dependencies from its own -behavior, which allows program designs to be loosely coupled and to follow the -inversion of control and single responsibility principles. - -![alt text](./etc/dependency-injection.png "Dependency Injection") - -## Applicability -Use the Dependency Injection pattern when - -* when you need to remove knowledge of concrete implementation from object -* to enable unit testing of classes in isolation using mock objects or stubs diff --git a/dependency-injection/etc/dependency-injection.png b/dependency-injection/etc/dependency-injection.png deleted file mode 100644 index 2a92c9eb228b3155c1599308668e94ecbb32d7f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22493 zcmbrmby$>b*Dp*XB}l3$ARQ8t0uCUEbO=b7bb~ZQw{$lQNOyNiNq2Y0kOD*3cj4{x zKKFCK``G(?_x^8=ne$rbI#>MGI@em)1jtH@V4*)phl7K|5)=I(2M3360|y81`3M2{ zCdT4e6%I}*Q|!Zg1;^xlS9de23D?7z(e3ZzBPXOX`E%6FbMI!AUFmCIby^g(HD@o( zn|&yAbm~|xeOk_r@v4=b$V#2_XCE#zS^yV+sY5#!HD!oXc(KZ(BXaGMMB1n0;@P>Q z)W+RBpP%P!e^$F162HwjcRjp$$7VCwpRlx*eCYy<;DGQt7#z6p+cc+gZ}oE*@d2E{ z!3iJ^=U*fJ{s@;3CyD+0Q;3Hp_@jt>0dg*CpoGS%2PHk+DhB?eZZuhR4sULG$ie&&NqD*_s~r}&d>nzsEqd((WS8$J!&Sc!Mx z&~!Q_+(%6_N51qsWb4tP!)iS~(3PDGSvpv@>fPh126H9*S(CwOIn3`|yv?%0FMX0n zpMV(>2Ht?YwH?5?yBM););R89(v3}UW*{v9oQNng0 zenv44BZJimmb`bVc#_}!J+Pl$QF=Hj5-hJ0PCh=8L-WGTbY}P0hS}cha~|CVNYT3$ z&hHsWoh!v+JhEO^Gcns^-or#hVAoZE0pu%~g4i~eD;QU{Z%(b573I{w8WNv&#uIE( z1W}isNH-$(^L}}?Tf~Lp+N8R)ao|IcUIXtywYVs_je*r<@ms3ooI(Ht^nWqHE*-W+ z2YQ?72^>Em;x!ukSK^VuI$a?&d-5fx<~Qkd!hh_^}%FN)7dum}#E>+CRKsg&n$sbq+^dDMOgOkA^Ir!z^-sAav4u1Y#TN@_*t75^z_?|bX+bIv4gL(4~WhS8GF z+qsp9>f(3Fwk@hva+0dJ5xY<BYMYnHFDbe|2gM*)gETyw!M6@Yu z@VPV~EO`umH|#>v#-H^zCc?U7Q6F&;%R_0lo#{D2g9$7dg|m;O4cUG* zvw&t29iATRB6ghRb9?&3tzg;)% z0J&eOaCfo}b*V{f{&W|arw#telk#Ts1xn8Nfn?PeFnah0?PLCH<3b-aoy=mxWtCxi zUY?XZLSAHV)T}iHqc}|Spy@9Xz?c(HP8`nf+XHd;lsN!=Z zQzVC~um|RUb&Du+wdlBC&0}*mTU~kPXt_qlx`Qp8kH%eLP=C@UiQ~vRWc7kh^R?xE zAKd(NgNc4Vvfe_XmkUJ_dsq48*t5_@gxNCWGREi z-pbH7HbmDwvQL|{SqLqGKTJd-1=q?&G(hfzB3(b29_yXY$D_VBu+)5PfRjM$PmrX0 z{F->bh=}e(-NmM!xYHwp_Q(B6wC;Ff3)eeAzYpTqxHfoXtTE)Fv8iRAbHzQI)jH)( zns{T@1CBJ+D&E-q*CF-2_83cg#9%*yN(w7VC%} zQn;|2SU@|OelkjQ+VBocdL7Vx6Ne^^BNSXvj{ zCfqX00iQtmq&|gQM*92i=4%n%mlOm&yHJ8>t#a0-%S7y6`3qL4Ld|b8IMlwPe`0Fp zPLL*9>A)KmyGjzZJv62AyBXJz&cjHsn)sH)w_0q^;`N12{6o}&8pVi+vJ3#@dX zdFs=V#~93h88q2NvJm&}`rEQ%csV#^M(82~HlTJR9_nE-LDyL>LH?`%RqZ4Apl3~f zZ{#AHAZ8qIb99(xub$A-4r!xrskA_80&)E3{~AHtv~{1*ozQ=5GE zZ9hEj=PtR5cNeWEj$uV%jKACrpJa>3awtVYzo^OF(kIVK$_UhQ1ZKY#Q^tHJ(~(Fr zI3`Il)($Q0dQKY+S~ zQfGFMEs>;dlX2vkr+FE zbDI)K4r;%d4b3btH-|QMt~&W<8Xey_p!|*HkgTvE=zf+ z+susazb@`14x1wR2yUeBgq+~syiB;|Q-9^do6uJj2kq{Mpyil~W{38dyC!qmRZ0!>MQ3HPk#%$m@0-=30b2cP7%Qmyj)|{!D}RHy2&lqtli89^OAA~Azt|JO%95%Uo_~S-$uFL%$PzC{p;fq zv*hTN11DYu$g%pME3h}=+l^^r4E_N&mZXafV*wd-5xw^NThjR?yKC>l zs}si>A%)JL+=!oFF4VHYJxK;!-_ zvMuGs0@@fh8u*US#tZy#G_LjV!^97iUB(C&Q2LCHTC0;}a*yS{m{4P#uve7kQ7|V1 zk)aby);BieDeVwv^;tu0Ts!B%h`6?>CSU%l$;up_{T-BEwk&+1?SW8ch3_BIO{$aA zxHgnC$b@r8VJs^SLW{e#;>RDfMN(2O#>3bD8WyDr{*?h8*s`=W|!p zH`fBKdlnfq?U2vwW4*g1QnZ~o;EFYj&*P5IUI8iX7tTf4TgAizK^atG)4_@-J zYnRx}{>UR97>o|wND|OU?CW`4R=XU+94nD&qy8vTh6=b)d>>Hji6|b01y>1mk$YBm zWmd(H!G@<&u(mn7Pog;JI|U;j5#q$c_io+mG4T{WfHNepN^8O#YhmMUZl*;v>3A@EH%U7jjsO)#9C9!Ti)q=sG+ zi!3$%Y7Qbv&h~B2B~IjdQ#zPw%5PKg3EE5iOFi2#2?YCLc6lzQO0O13B}Q%y9|XP% zSdv+mZwS_w2xLWT5Rs(wBa0qT^lGYzcckYPWQvksG@W~L1@DuM-s^+Inh%j zI??cLE}jn?f>8By3M!foH4=L{=8V#`e5n5XHwP|Qjb-Fu2}4aGzYG!9wL zWQUta?b>2dAfZ9%8^h6r)!cct#}Z3^HGXc?47chIUWr-pK9n7wdG97FV8eEZD+(AD ztfj?zQy9J09}Gr<_?6d;+MmGTJw6{E?m+QfI&{$)z1l2iU zoqts1Nu-al)Ukuo(*${g@prF=5lzS%{L{yD5mz?tEWQoieaCQ<_6+&Gh!$1$`YRK6xE5 z_QyShA#QHH*)_*R%*stlF=3vA`k!3QBn&IXD~sKMBJx=e+SS;=$C6)m;=q5oS;IRh z^i+pt>;(Oia{ovH{{0Sx=#xmPp`-(2Qt-;~%9#Jlv&UmCm2%aY7#(k|G}=s+d^D$0;9cE;e6rx(~ze6+!3DYn3IL#%RXM6b{sFp*V|ENBU49TIKR z;U2HVCtk&zT_Yv(8W#yCr%Zy}(i}A0OrMHCG~Qa9tlY_CR9ap3vKOtJB`-SG7ZI2p z!pKd*$sC{>8<{!|(7Zfu{`*MuSRJ{@Z+vkd7>y%1K;IGHyx%HDiy=xD$^Ay{D~wqa zm0>n-7s7lmOi%j`QxK zzlEyPO80leO=Hiy4aK5JPskt4G_xq@{s z9#1m%tLt5V(b)XEiAimAm^vLr(zaMiX$L2F;24fTmTPe`sew%DEar4h+U=*?N;siU zl5hIz)b}zH?%9O-l4&!CIPX=P0&eFKS8*W2WeBc;*nsbP?Hxj0Kb3BjtSjOlxn+~O zxz*T<<*NjWiF-kJTA!v>a)4g7QmWsG4&QRT8jw7F8?)o~>gi;rz+$jMd56aC1$tMi zWTR;Z7k~5!9Zxqs``P?bNuM< zUWm(r(i?bQui;og`Xi~{bRrxwEzqoZ`)nG!`J|Ux6M5SeRmvLSQ2?D2#Q#GO`@cx` z9`yw4DD^Tp-SKineC5~gA*JS@`r#cI^f5v1^#ZRtxbyiD2X8Y0p0!tUG`VEhH~rm= z(oZ(@{5H`#%vrBH*@HM%P3>J6sMnFW>4cl4hM)(J%AzGGl1)pW629fL_8H&+Ihehu z>WaznJ$7sE#0O4R_R(b^)UwkjnT#eYw+#AhI>p^Rk`@LsHt5{BIyo*xZJyp32p>%d zN|MlLc|EF-v!FwRg~b`ABENi`{pgE9N=ScV?7P%BR}1+8c94?GE#4IW;^kR^7U*pC zlWLkfcaoD59XpZaRL~wPo_>vm3cI)D&{B??bOMfP$JE}1qGUIkwOrssMVM~vWWLPd zOzYmO-Tku7rfcch3^n`90!L~adxOpG%!S2W-wi*n> zB@Rh;aLu+uRzZXz`hpup29DchSSRVd* z)Su`nP$YudB2RqZU$-^+cI+hEdDdU^t?dQui+@u)jJXKY;%D?@zNqZaTbfSyp3Lm< zMW?!j?Ll4kh{w=e~rcIWf=Cm+d2oIm?s<{c;sJtKt-(eWv^=usgce}0V##w z>wL4R&W5U#GDDJgHPnfa8j#g#NZ8Q4+p%|?*lRj3%cA|78nCugrHx^KvA!=|5 z`2TrQlGT7tjr+?e{V*EBC6YyI4Jny&sF=zao(kPNEYEUOhOT;$!z6pmUZYpm^c~*0 zhTGm1#SqgA?kcPMJY>~c7yU#3a2#c5WN;X+5aB)WuMb58unRQgrdE32v|ENXu5lt;D} zu^Mw)CDRl`JMWRlFX`f3Fon(3RrC4H!g9^+RP!c}%L>>ovvKfd5T%vr>JDtc-(z@? z@)1u8`=~l9wQT8q7V;fu`qUe6S>I8K?zG*MbWzp6v{Wc3eR6WrV874fe)n!&FFzTE zn@NfPESUx3w2RjFBDhs=g!VO>&A$ZTnQU)wKbXQRf*~OxVK@ZwP5$w;4JI0;HJ6aE zfz@DKZZsb0^ZkznyjGKDU|-TWMB&SRK-3Za|hVIQ&0352SsCXv-sQldo5gYk^*?cW4y}P@+ zwzkI0%NvdtpYZqRe7k!%d4T=boylleuwytuLPD0t@H?KXa&d3T0?<7!5Rl1plEF=j z#TpHSL`1J>(s0I=n*-94F%T0yPPT?f-&&;|RM4UT%}L%Ws@y#G6}N zG}P1&j}I$MP%f;je0e#f?$gsFwt&ShOQH?-$bav<2XL~^E1HiTU3&R`Y8Xx|I5c!e zPTu-#Zw3lAzBZF8-wO%~s;H>2OGQp&`u)sMG)z(**b1B7THo)Dn1hXtjf+d;L4~Nt z0*c6{wwv1`Tt<(MtEFym{Jn*g13pp<#+t;k;bXr3E&CO;KT0j zZziC`{Q!z?oWjDwr^XoDyabR%rkE)33G2bHYK3*Wutrmiws|DFY7WEBR}EL@M}f)LaCGEBVK{*RS*2dwT=( zZmTfhonCr3#82mzi<~5|8D33(PDx4OXnxa&cxz(qn1A{V^*3>ze&P_8CrL?3fFMzn zbk{p>Zf@4s^%e|2@#Gsjaa%3_7#@4JS*_L@qogMi?9(d5bGbyc{Y-9 zL;TcJk5%oQn;;ANkUP%O>Wl@8xrIu2G6LX))?apvd|1=EWZA8u9{Uyz6VRCQ-AFLI zd~?oRet)6XDn}2tyoentJgMg)RRwQ=)oSaldOd`<{U@F~F z45-IzbP3zk?CRND^a?p4yiz<*S)L#^qqP?OntPqtO<^nbXy2ZS>59%G2Uup@~C6rwJs@=dh{DhPk_sDbh5RlRc2{iE-PHqm-)o9c8oCh+htY-s*A# zfZ9X%@sPs#d|#TTiu==AqGLm_@N%O1WIfb9G^`7T(&r}S@$-Q^hE%+*APP)@hmUV@ znv)Nkm(T?8(Lt{~p(COqb?CZcwLz;?jknzy>xrFvjTl2w=aS^!$cuMFNox0|77Ngv ze!IZArbYV;wNcr%M9Nf78_3oW|8+sp{Z*dfYVnt1Qv`NIz#LV682OOU8n?nEB_&@o zF-=-&b0YgiHKkMw6aMgSpo)TJkfLLom>>0=W|9o_E7{xMUA0s$-Wal-K;2T_jn`85 z#DMyhsHyL)(oY-YPK8)N9!~+XbVl8oc*Y~^2T}my#@xEJ5cpb?CLti^OviS^F`I&U`T6q`LN$to{60ly9l#-&M-YC{fBX&q^ zL=BkA>iar#TU-1!KVJc42gELhd{U?>2YF9pylRLK$-vw~O%>DK_GqL&)&{*`8)~E< z>(qzMci6>6Dncr;E`M}KGVlVh=Ch~eSS|^sU%!?Oij}tK@l@XjR=rgwo(*4e7q+0P zc-q8KU0rQ|xCr9sXWr?4eY9JiK=Qd*>^1mW)%_R$qJC4B))@zUB0S*y+U!=NXk;jv z{wpghs;A5BJ((`@0Sm=jh9mQq^iHk|dk$BF$=nsy)dudAV0{p@OJDSti3Z*iQO^4l zCAFd?l&PE>Kp_Z#&R4UtJ~F$b~|oLvCjP!iMgo@wOEpB6_3)K7t>>PI16RWL87M$^+mp5OCIg zDw$TfI63$7F;t&EdzO%znv*Jq5l=AM-qF!fd1@Vd^K>8txlX8_d4~_Me7+Zq$c|&_i#^B-PX=6ip5&qcLVN>Q_3`xlJdEB^d2g{vZHaD1m~P&5e{^a{|Ht||rONb0 zzZ9$J(~LT&G=`6YCfO1w`S1X=VE&q>M=U|bu5mu>?d=61IG?{j(5e-g=$jceh&N6nJ8$Y`L#+K@Z~NEGnY+63ry&ChKuB|TkM0!+;NKJ+K|BEB zT>iV%bb$mnJ-rVwy1FmNPCuPjJ3EET@6NV)Bfp&)QNy!mLMXr#;VT6;I1*{kfWsdn zWIX9@KPbUrJEV3^q&KDaivKBf^{o(+7m(Z`<1~8^nOx*YJ)WVmOD*m6;kIdVBH82P z@8=G`XZkL*byfwO5YqE!G?s39ufOFUMM-!?!J9S9A9yD%ExlRTp_AlCe9S4(O%*l7 zX4fGtzyav2&ST_J#TOu`>giGPu*kUZMwBmSn}DsjCa|Is0JLSwzY5$RnGdHXnWP%i zr<^m)WJAG6lEe>-^pK`F^Iy)^~DE;FqKym$8 zbD_{vqshvAW=0?$f=seN7|eeADD;Q`jh6}vBNWf`osK=^G;&G9a`Qx0!r_=|mk|!N ztWjV={k!pkVqhbqT-qSZ^MiEdxtg%4jJj7EYTM$onoBnPaI#o{;P;F~@4d^P>@3{O z+YCWZ?Q5oZPDt;MNY8LSP=jj6n2)dMh!&CBn}6w_hnTiGDrqurhPTjciQKP(WYZJ? z5j^u0qX|TwYjARORL-bbY3vP{nD|_7N^LhtmLWt=!z-t0N3FIY)CJ!D?hh+(e5Os@ z0Hkt2V&gmjgk4ZFg$C;WtUY`a;6-{!A1PkHus__ibUR4`56tnfvDq9pokt#iALGm@ ziYjOAY3MZ|YUuTUF?4u$aA?A#81=4uX5QswV12*3rUvRic4%HRr#e)PVT2S8IKw>Utg>A2EKq@{jd*S&h&$K0~)h0%RJ?n>_TK6IeiAPq^~wV_C3<7BSocJ5(k z20q(Pveui~lH2D5WVy5O`9P)+j-0#soFqR3BwIFj*n$)*zDrINmXh+afgkJr`2F*v&&gEAh%C6n=;6p_G#}u^J}q@r zJD(pQqCW0$X#VIzKqHAwhHZr0jR1a4^87h##*~R086AD(baz9yZT8~qZ2G{u$o%_% zuX|K!uWT-z+%~;nj$@& zlNVvPmPUNFfL7JA5*Vm=*+HH8ZA&>pgVq74astF~I0%&pdZ?NSQ@bK_1w<_3sVgH&inmPx}W&rNbQytWu?=_(?%1H)Oa3Iec@tXO1 z@)2-A2cg|N&a?eFhXIbMY2xS?OJ;>)1c>*~7g{!qCcas7{$YI&U>)ndoO<6B}Q%Cz;YgKa|#x;*Xk; zE3Hm5#75}m>(GLeehI4h8%sZ@Bv3V=heNUVfy8Ibb;OhO?Ur(fB{5$!n@4e#lXewZ zUW(vDrX@Uk5#1#g`PgXOGBISv?Sx?4Nb$sxr(S{D`M%#QLLc(10rjh zSoJYHsb4eKunu0xz`%fJiO5GoH#dkLHxCaFE32HUOGTODXR959c@8nu;~qQdJ#iQm z9v`I=VI8=9>qP0?IP-rFEthIuem_QI)#=g z9iJs!?=#LF6_%8g6c)N%_GwWYvhngZ%z0_du<-Fo_p!0D!JhO)Vh+z#7)pd%a!zKV zJNvf|vo+Ord@?}B+kQr<5>QhER|N>l$&;{HU2Metp6V?)@L^=CCo~!ZujXrlY~Gp+ z==hAVgj8l-ZN;0qvFWp<5X!!ho}SO$V{GiXF{$th6?OGJ6U0@1 zuuIZ>d#javcPk^a2dWQ?g(BS@!-#rd!&&0{*XIzrxe7c+Wlg@3Qps?L&cM{a*_AuaI=6Bp$qA% z)rw06YB~Qp?B0FRcsf1`TB;K3tMr>>OPWFKy+rId-HU*~ePgx%9U%vNC-}@zZFMk& z3$*UIXgB0c1mU|_XOM9@?`k4)KL%Z0cW(;0HbakSn$TYvpvbBbh{^lxi2M-}W#UZR zXH7XuLz^+wyTh%+%cK^bX1mpryH;w(vFEBoR}gK!6ILB7p3K%?4J;t^&Z#wEAnooh zhlbB-wRnsl%w%iZVBVL#)J6aqoe=8p?*3wEhWSUe5k>|WN@8M1U50l{SW3kU{8P?_ z*XYi*Z0`5Wm75i)&M-Q2T}!ipy!F9WJ^c=8!~9O^m33ED@-JZ4<5_OuzZx zt>5YJ!l zH<&mrwKKbgJU(BW(n@l>7&0Gi$w*B|Yngh{(yC_A(rsFXUg>g4IIy)9dy@xp*+~JWks+a$2mcTx2+Ut&qd)>%?+$kCqQy5`~cpx*xl!G)!(^FE? zaXy}lCBO^#U8|AyZ{_?9sKRbKjMzPM+fO{_ldKH0TP1e4yqDN5aXs9@QgUO9zgMTw zp(=XM@k6`yT*!+vG=7mpdO!3uLKl4V6Q8E1PRrJsMpDM)KxOvaKS*iOPAB5=xy;tx zs%K*gTL-VJeX<`5HC3Ik24`>crvO}QFY49TUlTAT56u(m1xXqQq6Yp94VEImYak5D$k!}XLk+0 zS?5Oy7(Sztj=`Qg?qmab#et{6FDGFvi{19zZi+%DiXYuBMjDuSS<6bC`-r#hQ$jCp zu$!+(s_KSXSaL5eYfdcHr%omK~hG$F<(@9e!eX z-Nfet)_?LxsbSew4@zy2U|xc?kT!f>Ey*r%v0X}a9pIbnsd7)#R~4FfpP0?)>kryh z429YjY4+P&1i_3#uW+ShrhPUU;~}e;#|%lpOymrzqQ%8}fG=s&U82KwYRgd&D&&52 z{pc2O5xgtKT6*6++W<41;{FqUbj7Ke1H&}`?!^xx5pThDO4$F&&OMao{>=T(@wD2N zh7UyS7;<^deB(1Y&*vJ+ce=QETrS-JB7}nH0}BJ1dr73T_JXtp$ME{&zN6sl;;JEM z``7*-2aH18sN{sVe3Ggf4_aEY#WpiMIM9%yV*n%w31f@ZX;q9`FquPhz{8-hU1o$!XnRu;_I2_L>@*W+ONIxr${qrLuUocyRQ} zXi-pPQ&4PhbJg3qShe|Rr)00?>cZ_x0sz8Y$68QXTam&mt}zk}pT0@79B-Q+!#*`c z#YCh{dXs-loX$uALn%)zB6*KC>^!NUGzAMa92|J%S?`y3#bLYYEk7 z27A?jaOBl+cKSV)CWF=ikaJs}W^6c2y;&R5lyK)CZvxHcccM`VO;%hL#VQsy8669= zPHQtgU9CJUzzEf3{eyYG_nZ+sI@G+G@eW#QvD+!hDY>D(1)U{G^*8CuxwIz#G48D8 z`8pe*{A-sgEG!_$&il9M7wx;y;BXFZsvk;6C;QJJ*xUBkH4~_n(*HB8VE}brpxOoy zB={%6Z+?~k45#8BgjD|-PN~vgF{+CO8qjcdD1H4C2(3qa2$?8_EAWzvk6s41nPF*c zGvYU>=>wguhYY({7*Dl!Tq+PH3lvZCc@=pKaU0VJnU+Y(Xl0a)ZYT9D@eB9^UPt+u zRH4J1?!rMd|AbJO%BEkyu4~Fhs}F8J{`Z5g#;IpFxCf2j4-_a{FBjTURZVB*Q|whL zB673;LMtdsvv0w0=C{fmb)AA<7>lPBvs=m9&v6WY*V`H654Ri3$Z>&p+SRYGar!Au z7sW>*1*rE8m7{9kTuf5rkl6|t(*H)N_JNR&PC+-!YGaKQz~@ZzpXCF6V7(Z38Bc z;7kC;(R;Nrs-HGCO_WwnVU8ghy!u1!5z2qdynZkJhgs|ZIb?HPoytRb{lPkjR}0?$ z@c}z!b@k+w6ri#li29IUVFA}apvw0yjUbID8RTp~RjdKn=+QrHQ~{mhPkQ&e6@l)J zpb*Ciw-4Mc|NO!r5E4*?EMLH>mJ5Z?1hUeYw(h?y^KW}ku$1^>{38?O=r>&v{7(;4 zz&iP3{M!{-Z-*nEg+CO;5iuVY7Q$_JV+KwON@0^>86oGw`&IqZbxb_I{5LlNYs>wW zO)^TkToaWX-iFjUw5-XuoX@wowVVY_;{0)^-|Hm9fUJ|RxuL}-#M~kFugRs6=YoHd z8Ei?D6))%;-m)wXpi;WqVj)HLM>kkME3H~#@hQ{gNs#?I&Mo1}vIBcq!|sB8!C1kz zj)gvIs;Ix9oN)L?%}+9H zX>UV=mcc%S&e@!doum<+JA0xZ+o4VTOu)=m98IzF4?lJ~i-HS=5kz!RI(lsUWytc{ zQv=G;`_%~>7acPv=g>`QaWl@wMuvWuCh0!o6Ld4PeNONPd$vO*+wA8$V2k^~tzyk2 zC!O8eK3$+MyKeTP7UFHi@}(T;6_%TVny{XVuuhL^8Z;jqavEnjq*YR%dR6-ePb*R{`nw9hhoCM6 z4yE1YcxSM;!y2KGv+qQYU-G$5e>r5im0;i|t{{46=CNl=@aTO>d+pqC?7Rv0f%t)^ zOVvf!F+(iuUyl6@rP69cA}~1NS5LOUqP67e9{4A%(k8JZ5yRotZA!-Vks?Z@g?wVo z|7wuttpe4i76WrF{Meet&GNODcfk(tlx!((GLG&yZ#BRgLx9r7I3}WMtu>8s$tB(7 z_9J;Evah38kT}+Ml`->#$Q~DIbr+j=1ykmmFwcf9mEysm5o!T^AUJK{ZnWcnz^GmqNq)`F zYzbbyhQZnwyxTO?so1nKx!A8@ADrfThNdmIM!c*lf-Nmoq`OrrUIgnxYHFsH*Y+9H zRDgQV)putMrNvBIuyX-XLvr{~p$nAV+G)VBCxKacV=Zi>onNPR;-~bG%|IS>B;sif zsu3#yTyEQoZCSc<<4h;5Fnp2VZcKKfVe~YlN{f|IHae5oOKmWE=KV*=v4IlMo_&Bi z0W_n9wk%`0aR%TC5AwgfAC4-`?k|-1Hzo=YY|pg;gWi9?p#pC_RsR!o6g-<5)qg`H zl{b^M#*uj|EO&qqFi-%bWFG-x z8(mMucBchiqkFg>r{TcNR}e7$AlY5dBFWf^pxTaJgZR4MDA%vS2Sq=W<9tK?0O(yu zu0)_ka#gE^(=Dy5o7p{$jg9Sgmywp%wC)Mv`Db>#EmfnL3G(6lc+B=SC@0!qT zz4>Dof?Et9YNUXg7-dmZ)zyKnDxB_nh@bWPuU{l-d)%r&%{*GR@L*$r~R>|Q@kpz135~hE3mJbRoc_Pb)R4MIT_T)_$!MVZ`<6Y&dRDELSP{T z>N3FiKtR&%FMobYr4OMw%m@E{vLrYjVw9vX>QlbLNyj_pd@3Zlx@7^qrkoN}UhF*l zvNp@?F4Y0Ue1YAf9|*MeEPtZ23nJ%~+BF5)@!iEQkEH&Xe1~=h#C<)W6iJI(X$8OW z#n8|n$^P!$S_#=P^C5`lTuvrnaO?b#YZY(fXgLwcKC-Gi z(TX&2nQuls#YkVWH<84Y%ElI`z7Zg(!bbyG<{|e)eg@C(-R-o}MV zo%<|yj-8)%nL$&8hMANNH!RoUF->bm&R7jx8yflxLXTx?7gB_PlkY1e!T^`{6P@{KtySng~i38 z!NL9g{d;?Rr66aW7cyEhV|c~lc>%&<-Ti+m>azF%QS^?hE1sDYU`#?rL30S=*flma z0i%_jsTiEVe(tI&!k(x9uZEbCJbjW$)ia>kTjcZU-Q*fftAJCv3ZbM#2 z66=O&39cLO^*&JYhkkH(+DUIm zNP)6x3a>-)0UkUi(1J^22biMtVqNX;#}w1o*Uvhzp?eA&V`_qpYF%Y%avL z_4oI8-%xV%eZd%rK*p~PhRXtkNQSbG2F#xH900=`okOqkDfS$oV)sDDrEg7$PaS}X*_=Z{tou`K+jX)m26vvznio6M*UD0e(4$& z2?z}P;fZLM`YDCXhK+}(_i@FCzOk_}1=jw-!Nh#{G)katknb(-a&lz?H&Y7Wr@cQe zq&1I;T@cpjt2&hHCOZ#|&1sR!`B2Qm|%q%P>t#v%?fhM1VNXb;j3)yoOI1XK1 z-F6b?nZ3or5$-p%8N_FNs+_Vg;dar{(`PlM)zykeD)6(w*vBxO(TWMH+0>jx4W7UB z_%TI-gME+`-%AQ$^?X2=bt3sDpS;0e)ag_Q&ayYPkg1wDGOJb_?k`Bo19 zEp&KzST_u$I7J5!eqjA!*;4~x8Ma&%*RdwPsi|pHRMclk*i~AeFi%;WdEZ4p+t9F9 zW7XqsU~-~6?63I|x2Kg>38-tRiqbwH#zrH^cxPuPFu>F+BW^7FN+2#Mx?M4HrZ4_G zg6KmJ(??H2J^~tHwDLST02w-#w>=O4IG9vfg{1n_X;*D&XX4AWwkZc3wyjDxm46~~ z4@%XXd9X232Vyp=s26KCO_^`O)YtjYn(*2_X?lMoe4nZ+4q)#=4`3!re9o*0yJm?= zTj|V-S1=-%MfeR4A`q_#H75cLv2Hl_52{-}<&2>f*}V|X-K45-Uyr$C0*c1ljt8;0 zoc)Wg4P)=6WMb0r`GBSZH+Mjpq2Mo+C0*i19luv7AL3I|LZH;h><{BuxCkh}2Sga} zmoKoYt2?X6{yiX)&{<1Z{LAS|F`&h%q~_%vp)C1cAW!dZ_o}+jO^CUxpPygi%mf_` zkP>X~a1_bEBYWTxt&nk<7$bu5c-f+-ihMo>0TpkmEoKz9sl%JFVRJ;(e$jpFC z(I@PO&VL8sAc0dRtDXjhtOEJOq@*IBpZx#~L{#u95%R5-t}r`?bgT_|ECaVYe)gsO zFgDi{U>M4_2yi^M_ll7&*gWCz4^w57KKl}8sU)UfOF1iFwaA3c_iB45)cP`Lh!|{6 z0eK!;Iq%tzUPmWol&zuE98=$#>E3o=*J;-eWCFN zwp)f>7LafoiL#TPUZy7^gCU9rL!*fT=O6?W^ePFS7yu8qcnE}WoZQi}hmAuh#fXg< zF&;v$ja}FXWJy0C7baunZsuV=Eq_)DK;kwkeckN7{emI(-G2GrcM8Z@t%Tj7xCcqI!{y-aWgER&~M)hb>0M|_4ky5M-T!a7wk-(XGh?q0;>;O8{ zlaIIgYVvjdB@rZOow97~%imLPaHLPm>plVKWGiUI^7Jgg>Fd|8_V(3~F;)yf=)go{ z+mBv-Z5 zuOHyk!-K*rf}B$g!#a0(xH5HM%VSO7U{ ze7S~b-K-J;l{aj@3o;a_n6G9D@K!^pXAA@4r9}NKFpo%v0W78m7KZ?fO-q{WhajM* zONzK>!tD+81c(#wW`PqDqXALYQkJ}KJ3R>StzWakcf*N^Ped{BY)$;0!o_!?%J6i$D%}jk%}?DAHc~* zWlsV&#Fr(33ZBIlJ8J8H>wp8^XEb z)0%8>=i!*JVOBqUC8pf99WVP8x z5dv&krrBawbjdiG1`kJ&wRK{z)m1xVq_2Q9g`f^`NrqS~KX$-K9OfKJQdFSrctP73 z$t`vup0mkqO*V3cYhgSfj4+^(nP9Mu>NPGG?ppy=F}u@%=w7E*ONCH_gtqWgA+2@} z^FU730FrA|(Mlm|nOKK~x^X6i$ynL2J8wQ3M>L=EAwT*$JtiF_TFkr|J1IvwEV+^R zMup!O&nsG^gci^v9j*Krp39e3({_^idsyYV8>n6?w=q2L+2&z~TWy(1&@HQ1L*(rv z4$yFLec~H+ew@rfuh+?pfQnIs<3w;BK3z;!#WoFs2Y(J)m#|Il&t&;oB@KV_;;L?- zh6G8Z2f`2n?5Gz8BD~8c8wEZ{Bqhw^k{!aRr zc?mdWVnkH_c<19LQ1KvL_>Bmr52FYtI9Kok)WDv|fK}uCPYAqMAZfbk-L%7Ay1QeR zz6Uy+XCwHfx0w4nf`48S>5Z;Q=U#H3NvPZvV^NIgO`bavdEW7{I7!e#Avi{m zKl$YF4QpWkyb34-J>Zk$ipaVfyTIstdI0-}l?NvuIsS&8;;?YC=$nJhciD@#bo=$N zGu0*Rj<5W37$mb~1H8H}97x$JwTf-{cufB0VUr6w&mMFZ(6EflD?F=r?~lei^~U63 zV(6bcG?UG;{m+)&MsR%FVQ_*zy%}*@Gnri_GLYI`SQzC0YvsIyn%dSjex)}lK~Pjc z1B4pD2q+!t0U>}KdR0I`dXW-}QiKGMju0^PqI3lT5fDTWQ6NMKf^>sKq=y#TO*qFn zbDeL#bHAA{f9;v9*|YX~-}SEFTF>4Ov*+$UTmC_Rx<65*$Lw0`_BnsmVC<1Xak)MU z?a^d}&aFljXZY!xCx!uMu1_tPo*a?Jzzng}2Ts=p)IoxUq;AgIlmg*8;Yg8nLC)*2 z5e2?p{Aznm{c$N$$7B90vkdWy&3Bw?4o@eC4yIM1qv>1FGR_yYNmvK~P2a1cSC>I7 zs}ubx!u`e4kLpoWxJ#O)l!C(dtPwjws@SW1D1@o&NjM_==Ga8^?Pl83N@6WBygghC zLoiv=nq)!UtR{Om3r;LIrMpacb^6K(A+dh%6k5(6koU6GP|D)c+#vk@-sk(9uTcGU zT3CzYC{#OyG~9NZ`lEl3FJkQu5tD2m=}DSVZQ8B(9tit}v5qHe!S`PlEKslB1LkpEJ`{qBofo5$`du9bBxJlP~*an@SILfUI}O7=!2QoxKG&W+9FU@|)1f z&DRrAVs>RoJ=(F~|)lgzs z=O|z~U#jEiX+O7cd~$o(ETXzxxRoEiGVHX4LaSxg1}HE_CWH^os3u4css*r)P<%o+3d_10g1erO8ngGz?Pxm{-?-pGnLL-+I~ zAS#<+Yq}Ade+q+IT z?YFb83>+zjlm6C@gF$=$sU7QCzJ$R_%X;^Hnjw9C%XQburJ#?5NZI6^y)ZAWEE?M_MOWN7fhdc6QuI)_Yy0HVr5BPV z{1D}?+JrDzUs*Zmcmg*7rOa%CzdQ3=w9KRnb4L(KcP3p_Bj--DDIJye&FvAeKfS$a zD@7*uA63uX3ny`yRw{5AM?-*j@Sa`9qwa`%pP9{uNkM*HWVtp|-->K_B)KNw`#me0 ztkIbk7%|(uY&O!Glc_A6GTm2nu#T_ycZHBzYH;{rTz}E!! zrFZ8=>@=okZGne;PC~*>8uH|tlTn%ewO{8}W@Pr+GV(=Gq6J>Sv5lhfo@+iy-t1H9%KS znb99fM#g=$&*C)yDt=b8ZoVo$KeHybVTWtCYfC%$fBcXK8+s$*@P&6-H=&i@iMpt3 zzZN`Ad@4sGp}3r%>$+8e_OE5G^V9mfN(R|tRC#gOW` zu5uJqC{P-X)wOcq`?X?GXb$LhKZN1nZ)A%n-{9hZdxHYs5ScTdak)LQiWtrI2{CQK zYGCv@%g4Hy2vetMT1$%LCz@@d-BJJCnc_)cG$L{D z^>jH)&Ps5Ig;)%^sH=6%QeEruErAo`jW}QZ6DxEtRxIFU(7n5xkD{9@OhYc6L48r7 zQN%rNP16%^qFL+E7jKJwS3V;88B(hykj^bbeIP;xOWR{itx=l&)EpWFg8N&sLC5Vl z-l!OA-Tq-HDOJ^bw$8^sT&ne zE9ssRY)gWNSOsslTV!thlY_D;T>OK8otq4dnqRHL(~`B{ou$c9GpR1u;^307`gU=N z@TmNeQ2ktS0HsGc>?JRcd*m4+crdGRJ%nS=!|61=89^F{m|QaaGBdS0xdmPfq?@0J z>y*obIfgz3{WTKCl#!6GRD$IEzb4J^S=V*!IKf(=dreTyMNReI7Y8m@EHwkBOCuZP zF$3lOaGd;L@+mIl|BQD-y+)@C1jJIv`#A?WijJ$!%;t!yixm!(rl&CD3nMbh|LdP1 zaX3TgAOW|1*z>h@YVFAseA&LkzO_47+aQfwvq$Pg*07FIwAOjo3=mP^>fj53_a`zqfu)&%AD_stt(d% z7?Dm!L-@5t8{@Z3+5HO$S?$5&%!!vuULL(lnvdPKB~HtLiSpqr^4n~daN$x}vNH=z zeyhV&Z@!=S9#l<}>LmK;xiK7jqsoB=1Cyz8Cg@a&3~*r2WoQ~Z@7TKMqD?l>Q)J}W z?DYj?ZR9MeS8*z0v$EGtNspN*wV}LrQqF=$RJ4leVx@bi*Z^@Svtd$h1U%;3?lq;} zDXiM>5_04+<~Ysrh2&p0JSqhOm_4JvneaBRw4?|so}habY%ob@hj{hXx8`;MxJtjC zn^y7y_z(xjY+N#zey|{1=q?O!-DQ@n74b4i4%Z_ZlZ()n;k_W0^G~D)-jEt5a+vZi zo7*0~_bIksy)CCcxOR*$?3p^h`$Evk&E;-)da5?_?2ixH-a2=xkg#^;mV0tFa8O<^ zU{ETS-{#p;O54Q)ZiV^9S5sZ~1YQvvqxtaHCem(DM9laryij7N&WB8%5_YDf4v>ZK zLKY@Mrezoqu8bj`5u(K3uEs}&)efjSM38LGD+*S2$&<3;Z*c@XhM9^jXYC*U3mAAw zT&t0ggzbi_o%OiOw@c`KzTaRmlqw zJ-gLJEBOrArgTM|1Rm6o9o%_&qBQ=t?(PHjH5v-4p|c%>nj z{-89{&AAKQD=wNHht{=Zccfn1nXIj@~F5y2VSVs+A#7cG?8#gpAyse_huOA72eXq$}3#+`IZfVU31X4 zm0kn{YF^$x1W~;@mjyG`qXpz)OuS-|7l_Uc2WH9m{m|1Pd201b5Wp>ggcy1ggQLs&D=w_5;LhO03?5 zz>wdq{OndgA(0c%ogt1VG^83WFZx6CU|dN&iqBy4eC_dZjB$u&7;Jl_jcuY~y(?8? z@B@}?mh$ELkIc;|5|L(+k#0rp?u3l!tAlTM-<_%&G2;0O@@&a8_<QonLxck+Z%QN)cacSnb!N=jPxXZKWX=26h-4k#*5&po-($Z7%Xxy4rBSIX< zdVm=mo4`BtaaF+#?Rb=olH2s?+S@WE0N1du3rv)4)Sl;t6wL-^>tf4kU^bT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dependency-injection/etc/dependency-injection.urm.puml b/dependency-injection/etc/dependency-injection.urm.puml deleted file mode 100644 index 80f15fce32a5..000000000000 --- a/dependency-injection/etc/dependency-injection.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.dependency.injection { - class AdvancedWizard { - - tobacco : Tobacco - + AdvancedWizard(tobacco : Tobacco) - + smoke() - } - class App { - + App() - + main(args : String[]) {static} - } - class GuiceWizard { - - tobacco : Tobacco - + GuiceWizard(tobacco : Tobacco) - + smoke() - } - class OldTobyTobacco { - + OldTobyTobacco() - } - class RivendellTobacco { - + RivendellTobacco() - } - class SecondBreakfastTobacco { - + SecondBreakfastTobacco() - } - class SimpleWizard { - - tobacco : OldTobyTobacco - + SimpleWizard() - + smoke() - } - abstract class Tobacco { - - LOGGER : Logger {static} - + Tobacco() - + smoke(wizard : Wizard) - } - interface Wizard { - + smoke() {abstract} - } -} -SimpleWizard --> "-tobacco" OldTobyTobacco -AdvancedWizard --> "-tobacco" Tobacco -GuiceWizard --> "-tobacco" Tobacco -AdvancedWizard ..|> Wizard -GuiceWizard ..|> Wizard -OldTobyTobacco --|> Tobacco -RivendellTobacco --|> Tobacco -SecondBreakfastTobacco --|> Tobacco -SimpleWizard ..|> Wizard -@enduml \ No newline at end of file diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml deleted file mode 100644 index e01d5b68d136..000000000000 --- a/dependency-injection/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - dependency-injection - - - junit - junit - test - - - org.mockito - mockito-core - test - - - com.google.inject - guice - - - diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedSorceress.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedSorceress.java deleted file mode 100644 index 52256fd81264..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedSorceress.java +++ /dev/null @@ -1,65 +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; - -/** - * The MIT License - * Copyright (c) 2014-2017 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. - */ - - -/** - * AdvancedSorceress implements inversion of control. It depends on abstraction that can be injected - * through its setter. - */ -public class AdvancedSorceress implements Wizard { - - private Tobacco tobacco; - - public void setTobacco(Tobacco tobacco) { - this.tobacco = tobacco; - } - - @Override - public void smoke() { - tobacco.smoke(this); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedWizard.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedWizard.java deleted file mode 100644 index 913a8bd6e05a..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedWizard.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * AdvancedWizard implements inversion of control. It depends on abstraction that can be injected - * through its constructor. - * - */ -public class AdvancedWizard implements Wizard { - - private Tobacco tobacco; - - public AdvancedWizard(Tobacco tobacco) { - this.tobacco = tobacco; - } - - @Override - public void smoke() { - tobacco.smoke(this); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/App.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/App.java deleted file mode 100644 index a27160bf19e7..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/App.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -/** - * Dependency Injection pattern deals with how objects handle their dependencies. The pattern - * implements so called inversion of control principle. Inversion of control has two specific rules: - * - High-level modules should not depend on low-level modules. Both should depend on abstractions. - * - Abstractions should not depend on details. Details should depend on abstractions. - *

- * In this example we show you three different wizards. The first one ({@link SimpleWizard}) is a - * naive implementation violating the inversion of control principle. It depends directly on a - * concrete implementation which cannot be changed. - *

- * The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more flexible. - * They do not depend on any concrete implementation but abstraction. They utilizes Dependency Injection - * pattern allowing their {@link Tobacco} dependency to be injected through constructor ({@link AdvancedWizard}) - * or setter ({@link AdvancedSorceress}). This way, handling the dependency is no longer the wizard's - * responsibility. It is resolved outside the wizard class. - *

- * The fourth example takes the pattern a step further. It uses Guice framework for Dependency - * Injection. {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then - * used to create {@link GuiceWizard} object with correct dependencies. - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - SimpleWizard simpleWizard = new SimpleWizard(); - simpleWizard.smoke(); - - AdvancedWizard advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco()); - advancedWizard.smoke(); - - AdvancedSorceress advancedSorceress = new AdvancedSorceress(); - advancedSorceress.setTobacco(new SecondBreakfastTobacco()); - advancedSorceress.smoke(); - - Injector injector = Guice.createInjector(new TobaccoModule()); - GuiceWizard guiceWizard = injector.getInstance(GuiceWizard.class); - guiceWizard.smoke(); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/GuiceWizard.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/GuiceWizard.java deleted file mode 100644 index 89db63f189bb..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/GuiceWizard.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import javax.inject.Inject; - -/** - * - * GuiceWizard implements inversion of control. Its dependencies are injected through its - * constructor by Guice framework. - * - */ -public class GuiceWizard implements Wizard { - - private Tobacco tobacco; - - @Inject - public GuiceWizard(Tobacco tobacco) { - this.tobacco = tobacco; - } - - @Override - public void smoke() { - tobacco.smoke(this); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/OldTobyTobacco.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/OldTobyTobacco.java deleted file mode 100644 index 68f45640526e..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/OldTobyTobacco.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * OldTobyTobacco concrete {@link Tobacco} implementation - * - */ -public class OldTobyTobacco extends Tobacco { -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/RivendellTobacco.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/RivendellTobacco.java deleted file mode 100644 index 29a9c9c21e12..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/RivendellTobacco.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * RivendellTobacco concrete {@link Tobacco} implementation - * - */ -public class RivendellTobacco extends Tobacco { -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SecondBreakfastTobacco.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SecondBreakfastTobacco.java deleted file mode 100644 index 4bc373dbaf48..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SecondBreakfastTobacco.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * SecondBreakfastTobacco concrete {@link Tobacco} implementation - * - */ -public class SecondBreakfastTobacco extends Tobacco { -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SimpleWizard.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SimpleWizard.java deleted file mode 100644 index c800d70a076d..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/SimpleWizard.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * Naive Wizard implementation violating the inversion of control principle. It should depend on - * abstraction instead. - * - */ -public class SimpleWizard implements Wizard { - - private OldTobyTobacco tobacco = new OldTobyTobacco(); - - public void smoke() { - tobacco.smoke(this); - } -} 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 deleted file mode 100644 index 9676e49e81e0..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Tobacco abstraction - * - */ -public abstract class Tobacco { - - private static final Logger LOGGER = LoggerFactory.getLogger(Tobacco.class); - - public void smoke(Wizard wizard) { - LOGGER.info("{} smoking {}", wizard.getClass().getSimpleName(), - this.getClass().getSimpleName()); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/TobaccoModule.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/TobaccoModule.java deleted file mode 100644 index 4f26b78a54cc..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/TobaccoModule.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import com.google.inject.AbstractModule; - -/** - * - * Guice module for binding certain concrete {@link Tobacco} implementation. - * - */ -public class TobaccoModule extends AbstractModule { - - @Override - protected void configure() { - bind(Tobacco.class).to(RivendellTobacco.class); - } -} diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Wizard.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Wizard.java deleted file mode 100644 index d4c4cbbb4842..000000000000 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Wizard.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -/** - * - * Wizard interface - * - */ -public interface Wizard { - - void smoke(); - -} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedSorceressTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedSorceressTest.java deleted file mode 100644 index b2a701d0b00f..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedSorceressTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.junit.Assert.assertEquals; - -/** - * Date: 28/04/17 - 7:40 AM - * - * @author Stanislav Kapinus - */ - -public class AdvancedSorceressTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(Tobacco.class); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * Test if the {@link AdvancedSorceress} smokes whatever instance of {@link Tobacco} is passed to her - * through the setter's parameter - */ - @Test - public void testSmokeEveryThing() throws Exception { - - final Tobacco[] tobaccos = { - new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco() - }; - - for (final Tobacco tobacco : tobaccos) { - final AdvancedSorceress advancedSorceress = new AdvancedSorceress(); - advancedSorceress.setTobacco(tobacco); - advancedSorceress.smoke(); - // Verify if the sorceress is smoking the correct tobacco ... - assertEquals("AdvancedSorceress smoking " + tobacco.getClass().getSimpleName(), appender.getLastMessage()); - - } - - // ... and nothing else is happening. - assertEquals(tobaccos.length, appender.getLogSize()); - - } -} 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 deleted file mode 100644 index 2d6857912683..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.junit.Assert.assertEquals; - -/** - * Date: 12/10/15 - 8:40 PM - * - * @author Jeroen Meulemeester - */ -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 - * through the constructor parameter - */ - @Test - public void testSmokeEveryThing() throws Exception { - - final Tobacco[] tobaccos = { - new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco() - }; - - for (final Tobacco tobacco : tobaccos) { - final AdvancedWizard advancedWizard = new AdvancedWizard(tobacco); - advancedWizard.smoke(); - - // Verify if the wizard is smoking the correct tobacco ... - assertEquals("AdvancedWizard smoking " + tobacco.getClass().getSimpleName(), appender.getLastMessage()); - - } - - // ... and nothing else is happening. - assertEquals(tobaccos.length, appender.getLogSize()); - - } - -} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AppTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AppTest.java deleted file mode 100644 index 41f04c9b3c91..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index e58a9f3b5483..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dependency.injection; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.iluwatar.dependency.injection.utils.InMemoryAppender; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/10/15 - 8:57 PM - * - * @author Jeroen Meulemeester - */ -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 - * through the constructor parameter - */ - @Test - public void testSmokeEveryThingThroughConstructor() throws Exception { - - final Tobacco[] tobaccos = { - new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco() - }; - - for (final Tobacco tobacco : tobaccos) { - final GuiceWizard guiceWizard = new GuiceWizard(tobacco); - guiceWizard.smoke(); - - // Verify if the wizard is smoking the correct tobacco ... - assertEquals("GuiceWizard smoking " + tobacco.getClass().getSimpleName(), appender.getLastMessage()); - } - - // ... and nothing else is happening. - assertEquals(tobaccos.length, appender.getLogSize()); - } - - /** - * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him - * through the Guice google inject framework - */ - @Test - public void testSmokeEveryThingThroughInjectionFramework() throws Exception { - - @SuppressWarnings("unchecked") - final Class[] tobaccos = new Class[]{ - OldTobyTobacco.class, RivendellTobacco.class, SecondBreakfastTobacco.class - }; - - for (final Class tobaccoClass : tobaccos) { - // Configure the tobacco in the injection framework ... - final Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Tobacco.class).to(tobaccoClass); - } - }); - - // ... and create a new wizard with it - final GuiceWizard guiceWizard = injector.getInstance(GuiceWizard.class); - guiceWizard.smoke(); - - // Verify if the wizard is smoking the correct tobacco ... - assertEquals("GuiceWizard smoking " + tobaccoClass.getSimpleName(), appender.getLastMessage()); - } - - // ... and nothing else is happening. - assertEquals(tobaccos.length, appender.getLogSize()); - } - -} 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 deleted file mode 100644 index 4ce69e0950e8..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.junit.Assert.assertEquals; - -/** - * Date: 12/10/15 - 8:26 PM - * - * @author Jeroen Meulemeester - */ -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 - * OldTobyTobacco} - */ - @Test - public void testSmoke() { - final SimpleWizard simpleWizard = new SimpleWizard(); - simpleWizard.smoke(); - assertEquals("SimpleWizard smoking OldTobyTobacco", appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - -} 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 deleted file mode 100644 index b79bf3d40b32..000000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - - -/** - * InMemory Log Appender Util. - */ -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/README.md b/double-checked-locking/README.md deleted file mode 100644 index 582e4aac657c..000000000000 --- a/double-checked-locking/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Double Checked Locking -folder: double-checked-locking -permalink: /patterns/double-checked-locking/ -pumlid: TSdH4SCW203GLTe1bFzkGv1J6qGFeLc_MI1_x-wzkv94uJ1vDVUrFm26LwxTMnonsMYgitgcEQ1BNEXeyCKVfiAxLqqBtTbqmy1z0ygCGpXHOpgv99bqTgt0JW-LmqPUCUGF -categories: Concurrency -tags: - - Java - - Difficulty-Beginner - - Idiom ---- - -## Intent -Reduce the overhead of acquiring a lock by first testing the -locking criterion (the "lock hint") without actually acquiring the lock. Only -if the locking criterion check indicates that locking is required does the -actual locking logic proceed. - -![alt text](./etc/double_checked_locking_1.png "Double Checked Locking") - -## Applicability -Use the Double Checked Locking pattern when - -* there is a concurrent access in object creation, e.g. singleton, where you want to create single instance of the same class and checking if it's null or not maybe not be enough when there are two or more threads that checks if instance is null or not. -* there is a concurrent access on a method where method's behaviour changes according to the some constraints and these constraint change within this method. diff --git a/double-checked-locking/etc/double-checked-locking.png b/double-checked-locking/etc/double-checked-locking.png deleted file mode 100644 index 4c652e27aa67d3ed358b6f9682930f7089357828..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7011 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 PvkN+!h7Zc_KY8^Z5y}C9 diff --git a/double-checked-locking/etc/double-checked-locking.ucls b/double-checked-locking/etc/double-checked-locking.ucls deleted file mode 100644 index 3ec1792287a6..000000000000 --- a/double-checked-locking/etc/double-checked-locking.ucls +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/double-checked-locking/etc/double-checked-locking.urm.puml b/double-checked-locking/etc/double-checked-locking.urm.puml deleted file mode 100644 index 242519fce77c..000000000000 --- a/double-checked-locking/etc/double-checked-locking.urm.puml +++ /dev/null @@ -1,22 +0,0 @@ -@startuml -package com.iluwatar.doublechecked.locking { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Inventory { - - LOGGER : Logger {static} - - inventorySize : int - - items : List - - lock : Lock - + Inventory(inventorySize : int) - + addItem(item : Item) : boolean - + getItems() : List - } - class Item { - + Item() - } -} -Inventory --> "-items" Item -@enduml \ No newline at end of file diff --git a/double-checked-locking/etc/double_checked_locking_1.png b/double-checked-locking/etc/double_checked_locking_1.png deleted file mode 100644 index cced091b9d67fcb73ed5e550e8d128def331157d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11954 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 S - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - double-checked-locking - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index c814f98bc586..000000000000 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * - * Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a - * lock by first testing the locking criterion (the "lock hint") without actually acquiring the - * lock. Only if the locking criterion check indicates that locking is required does the actual - * locking logic proceed. - *

- * In {@link Inventory} we store the items with a given size. However, we do not store more items - * than the inventory size. To address concurrent access problems we use double checked locking to - * add item to inventory. In this method, the thread which gets the lock first adds the item. - * - */ -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) { - final Inventory inventory = new Inventory(1000); - ExecutorService executorService = Executors.newFixedThreadPool(3); - for (int i = 0; i < 3; i++) { - executorService.execute(() -> { - while (inventory.addItem(new Item())) {}; - }); - } - - executorService.shutdown(); - try { - executorService.awaitTermination(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - 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 deleted file mode 100644 index 80f97a215d01..000000000000 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * - * Inventory - * - */ -public class Inventory { - - private static final Logger LOGGER = LoggerFactory.getLogger(Inventory.class); - - private final int inventorySize; - private final List items; - private final Lock lock; - - /** - * Constructor - */ - public Inventory(int inventorySize) { - this.inventorySize = inventorySize; - this.items = new ArrayList<>(inventorySize); - this.lock = new ReentrantLock(); - } - - /** - * Add item - */ - public boolean addItem(Item item) { - if (items.size() < inventorySize) { - lock.lock(); - try { - if (items.size() < inventorySize) { - items.add(item); - LOGGER.info("{}: items.size()={}, inventorySize={}", Thread.currentThread(), items.size(), inventorySize); - return true; - } - } finally { - lock.unlock(); - } - } - return false; - } - - /** - * Get all the items in the inventory - * - * @return All the items of the inventory, as an unmodifiable list - */ - public final List getItems() { - return Collections.unmodifiableList(items); - } - -} diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java deleted file mode 100644 index 7ff8c4965036..000000000000 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doublechecked.locking; - -/** - * - * Item - * - */ -public class Item { -} diff --git a/double-checked-locking/src/main/resources/logback.xml b/double-checked-locking/src/main/resources/logback.xml deleted file mode 100644 index 525f2f6652cf..000000000000 --- a/double-checked-locking/src/main/resources/logback.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - double-checked-locking.log - - double-checked-locking-%d.log - 5 - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - - - - - - - - diff --git a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/AppTest.java b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/AppTest.java deleted file mode 100644 index 672d83f0aca6..000000000000 --- a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doublechecked.locking; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index 0b1487e11239..000000000000 --- a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.slf4j.LoggerFactory; - -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.TestCase.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/10/15 - 9:34 PM - * - * @author Jeroen Meulemeester - */ -public class InventoryTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(Inventory.class); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * The number of threads used to stress test the locking of the {@link Inventory#addItem(Item)} - * method - */ - private static final int THREAD_COUNT = 8; - - /** - * The maximum number of {@link Item}s allowed in the {@link Inventory} - */ - private static final int INVENTORY_SIZE = 1000; - - /** - * Concurrently add multiple items to the inventory, and check if the items were added in order by - * checking the stdOut for continuous growth of the inventory. When 'items.size()=xx' shows up out - * of order, it means that the locking is not ok, increasing the risk of going over the inventory - * item limit. - */ - @Test(timeout = 10000) - public void testAddItem() throws Exception { - // Create a new inventory with a limit of 1000 items and put some load on the add method - final Inventory inventory = new Inventory(INVENTORY_SIZE); - final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT); - for (int i = 0; i < THREAD_COUNT; i++) { - executorService.execute(() -> { - while (inventory.addItem(new Item())) {}; - }); - } - - // Wait until all threads have finished - executorService.shutdown(); - executorService.awaitTermination(5, TimeUnit.SECONDS); - - // Check the number of items in the inventory. It should not have exceeded the allowed maximum - final List items = inventory.getItems(); - assertNotNull(items); - assertEquals(INVENTORY_SIZE, items.size()); - - assertEquals(INVENTORY_SIZE, appender.getLogSize()); - - // ... and check if the inventory size is increasing continuously - for (int i = 0; i < items.size(); i++) { - assertTrue(appender.log.get(i).getFormattedMessage().contains("items.size()=" + (i + 1))); - } - } - - - - private class InMemoryAppender extends AppenderBase { - private List log = new LinkedList<>(); - - public InMemoryAppender(Class clazz) { - ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); - start(); - } - - @Override - protected void append(ILoggingEvent eventObject) { - log.add(eventObject); - } - - public int getLogSize() { - return log.size(); - } - } - -} diff --git a/double-dispatch/README.md b/double-dispatch/README.md deleted file mode 100644 index b0f2185f9a34..000000000000 --- a/double-dispatch/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Double Dispatch -folder: double-dispatch -permalink: /patterns/double-dispatch/ -pumlid: NSbB3iCW303HgpG70Ezx6yTOWSeOv4zp_MRTtUZDCPGa6wV9gqTiVmCOtlKQqVDCPwEbmHgLreGXUMEWmGU_M1hxkBHiZ61JXud-1BILft1fmvz37JZetshQh3kd_000 -categories: Other -tags: - - Java - - Difficulty-Intermediate - - Idiom ---- - -## Intent -Double Dispatch pattern is a way to create maintainable dynamic -behavior based on receiver and parameter types. - -![alt text](./etc/double-dispatch.png "Double Dispatch") - -## Applicability -Use the Double Dispatch pattern when - -* the dynamic behavior is not defined only based on receiving object's type but also on the receiving method's parameter type. - -## Real world examples - -* [ObjectOutputStream](https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html) diff --git a/double-dispatch/etc/double-dispatch.png b/double-dispatch/etc/double-dispatch.png deleted file mode 100644 index 9ee77b499cd8a09e6129ab9ce4c823d1decaf3c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32364 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 HG!OnST!7rL diff --git a/double-dispatch/etc/double-dispatch.ucls b/double-dispatch/etc/double-dispatch.ucls deleted file mode 100644 index 498f77bfc382..000000000000 --- a/double-dispatch/etc/double-dispatch.ucls +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/double-dispatch/etc/double-dispatch.urm.puml b/double-dispatch/etc/double-dispatch.urm.puml deleted file mode 100644 index 447cf3081e7f..000000000000 --- a/double-dispatch/etc/double-dispatch.urm.puml +++ /dev/null @@ -1,68 +0,0 @@ -@startuml -package com.iluwatar.doubledispatch { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class FlamingAsteroid { - + FlamingAsteroid(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - } - abstract class GameObject { - - damaged : boolean - - onFire : boolean - + GameObject(left : int, top : int, right : int, bottom : int) - + collision(GameObject) {abstract} - + collisionResolve(FlamingAsteroid) {abstract} - + collisionResolve(Meteoroid) {abstract} - + collisionResolve(SpaceStationIss) {abstract} - + collisionResolve(SpaceStationMir) {abstract} - + isDamaged() : boolean - + isOnFire() : boolean - + setDamaged(damaged : boolean) - + setOnFire(onFire : boolean) - + toString() : String - } - class Meteoroid { - - LOGGER : Logger {static} - + Meteoroid(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - + collisionResolve(asteroid : FlamingAsteroid) - + collisionResolve(iss : SpaceStationIss) - + collisionResolve(meteoroid : Meteoroid) - + collisionResolve(mir : SpaceStationMir) - } - class Rectangle { - - bottom : int - - left : int - - right : int - - top : int - + Rectangle(left : int, top : int, right : int, bottom : int) - + getBottom() : int - + getLeft() : int - + getRight() : int - + getTop() : int - ~ intersectsWith(r : Rectangle) : boolean - + toString() : String - } - class SpaceStationIss { - + SpaceStationIss(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - } - class SpaceStationMir { - - LOGGER : Logger {static} - + SpaceStationMir(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - + collisionResolve(asteroid : FlamingAsteroid) - + collisionResolve(iss : SpaceStationIss) - + collisionResolve(meteoroid : Meteoroid) - + collisionResolve(mir : SpaceStationMir) - } -} -FlamingAsteroid --|> Meteoroid -GameObject --|> Rectangle -Meteoroid --|> GameObject -SpaceStationIss --|> SpaceStationMir -SpaceStationMir --|> GameObject -@enduml \ No newline at end of file diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml deleted file mode 100644 index 44107f474dc2..000000000000 --- a/double-dispatch/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - double-dispatch - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java deleted file mode 100644 index acb57d457167..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * When a message with a parameter is sent to an object, the resultant behaviour is defined by the implementation of - * that method in the receiver. Sometimes the behaviour must also be determined by the type of the parameter. - *

- * One way to implement this would be to create multiple instanceof-checks for the methods parameter. However, this - * creates a maintenance issue. When new types are added we would also need to change the method's implementation and - * add a new instanceof-check. This violates the single responsibility principle - a class should have only one reason - * to change. - *

- * Instead of the instanceof-checks a better way is to make another virtual call on the parameter object. This way new - * functionality can be easily added without the need to modify existing implementation (open-closed principle). - *

- * In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other. Each object has its - * own coordinates which are checked against the other objects' coordinates. If there is an overlap, then the objects - * collide utilizing the Double Dispatch pattern. - * - */ -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) { - // initialize game objects and print their status - List objects = new ArrayList<>(); - objects.add(new FlamingAsteroid(0, 0, 5, 5)); - 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 -> LOGGER.info(o.toString())); - LOGGER.info(""); - - // collision check - objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> { - if (o1 != o2 && o1.intersectsWith(o2)) { - o1.collision(o2); - } - })); - LOGGER.info(""); - - // output eventual object statuses - objects.stream().forEach(o -> LOGGER.info(o.toString())); - LOGGER.info(""); - } -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/FlamingAsteroid.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/FlamingAsteroid.java deleted file mode 100644 index 6ca8a8f08f07..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/FlamingAsteroid.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -/** - * - * Flaming asteroid game object - * - */ -public class FlamingAsteroid extends Meteoroid { - - public FlamingAsteroid(int left, int top, int right, int bottom) { - super(left, top, right, bottom); - setOnFire(true); - } - - @Override - public void collision(GameObject gameObject) { - gameObject.collisionResolve(this); - } -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/GameObject.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/GameObject.java deleted file mode 100644 index 42c0c9a5eaf5..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/GameObject.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -/** - * - * Game objects have coordinates and some other status information. - * - */ -public abstract class GameObject extends Rectangle { - - private boolean damaged; - private boolean onFire; - - public GameObject(int left, int top, int right, int bottom) { - super(left, top, right, bottom); - } - - @Override - public String toString() { - return String.format("%s at %s damaged=%b onFire=%b", this.getClass().getSimpleName(), - super.toString(), isDamaged(), isOnFire()); - } - - public boolean isOnFire() { - return onFire; - } - - public void setOnFire(boolean onFire) { - this.onFire = onFire; - } - - public boolean isDamaged() { - return damaged; - } - - public void setDamaged(boolean damaged) { - this.damaged = damaged; - } - - public abstract void collision(GameObject gameObject); - - public abstract void collisionResolve(FlamingAsteroid asteroid); - - public abstract void collisionResolve(Meteoroid meteoroid); - - public abstract void collisionResolve(SpaceStationMir mir); - - public abstract void collisionResolve(SpaceStationIss iss); -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java deleted file mode 100644 index 311ffa0e11f8..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Meteoroid game object - * - */ -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); - } - - @Override - public void collision(GameObject gameObject) { - gameObject.collisionResolve(this); - } - - @Override - public void collisionResolve(FlamingAsteroid asteroid) { - LOGGER.info("{} hits {}.", asteroid.getClass().getSimpleName(), this.getClass().getSimpleName()); - } - - @Override - public void collisionResolve(Meteoroid meteoroid) { - LOGGER.info("{} hits {}.", meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName()); - } - - @Override - public void collisionResolve(SpaceStationMir mir) { - LOGGER.info("{} hits {}.", mir.getClass().getSimpleName(), this.getClass().getSimpleName()); - } - - @Override - public void collisionResolve(SpaceStationIss iss) { - LOGGER.info("{} hits {}.", iss.getClass().getSimpleName(), this.getClass().getSimpleName()); - } -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java deleted file mode 100644 index 5e668f4baf53..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -/** - * - * Rectangle has coordinates and can be checked for overlap against other Rectangles. - * - */ -public class Rectangle { - - private int left; - private int top; - private int right; - private int bottom; - - /** - * Constructor - */ - public Rectangle(int left, int top, int right, int bottom) { - this.left = left; - this.top = top; - this.right = right; - this.bottom = bottom; - } - - public int getLeft() { - return left; - } - - public int getTop() { - return top; - } - - public int getRight() { - return right; - } - - public int getBottom() { - return bottom; - } - - boolean intersectsWith(Rectangle r) { - return !(r.getLeft() > getRight() || r.getRight() < getLeft() || r.getTop() > getBottom() || r - .getBottom() < getTop()); - } - - @Override - public String toString() { - return String.format("[%d,%d,%d,%d]", getLeft(), getTop(), getRight(), getBottom()); - } -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationIss.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationIss.java deleted file mode 100644 index 868e8ae813ca..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationIss.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -/** - * - * Space station ISS game object - * - */ -public class SpaceStationIss extends SpaceStationMir { - - public SpaceStationIss(int left, int top, int right, int bottom) { - super(left, top, right, bottom); - } - - @Override - public void collision(GameObject gameObject) { - gameObject.collisionResolve(this); - } -} diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java deleted file mode 100644 index 419be2e30c78..000000000000 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Space station Mir game object - * - */ -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); - } - - @Override - public void collision(GameObject gameObject) { - gameObject.collisionResolve(this); - } - - @Override - public void collisionResolve(FlamingAsteroid asteroid) { - 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) { - LOGGER.info("{} hits {}. {} is damaged!", meteoroid.getClass().getSimpleName(), - this.getClass().getSimpleName(), this.getClass().getSimpleName()); - setDamaged(true); - } - - @Override - public void collisionResolve(SpaceStationMir mir) { - LOGGER.info("{} hits {}. {} is damaged!", mir.getClass().getSimpleName(), - this.getClass().getSimpleName(), this.getClass().getSimpleName()); - setDamaged(true); - } - - @Override - public void collisionResolve(SpaceStationIss iss) { - LOGGER.info("{} hits {}. {} is damaged!", iss.getClass().getSimpleName(), - this.getClass().getSimpleName(), this.getClass().getSimpleName()); - setDamaged(true); - } -} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/AppTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/AppTest.java deleted file mode 100644 index dce6afd86345..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java deleted file mode 100644 index 3dc32905a699..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import static org.junit.Assert.assertEquals; - -import java.util.Objects; - -/** - * Date: 12/10/15 - 8:37 PM - * Test for Collision - * @param Type of GameObject - * @author Jeroen Meulemeester - */ -public abstract class CollisionTest { - - /** - * Get the tested object - * - * @return The tested object, should never return 'null' - */ - abstract O getTestedObject(); - - /** - * Collide the tested item with the other given item and verify if the damage and fire state is as - * expected - * - * @param other The other object we have to collide with - * @param otherDamaged Indicates if the other object should be damaged after the collision - * @param otherOnFire Indicates if the other object should be burning after the collision - * @param thisDamaged Indicates if the test object should be damaged after the collision - * @param thisOnFire Indicates if the other object should be burning after the collision - * @param description The expected description of the collision - */ - void testCollision(final GameObject other, final boolean otherDamaged, final boolean otherOnFire, - final boolean thisDamaged, final boolean thisOnFire, final String description) { - - Objects.requireNonNull(other); - Objects.requireNonNull(getTestedObject()); - - final O tested = getTestedObject(); - - tested.collision(other); - - testOnFire(other, tested, otherOnFire); - testDamaged(other, tested, otherDamaged); - - testOnFire(tested, other, thisOnFire); - testDamaged(tested, other, thisDamaged); - - } - - /** - * Test if the fire state of the target matches the expected state after colliding with the given - * object - * - * @param target The target object - * @param other The other object - * @param expectTargetOnFire The expected state of fire on the target object - */ - private void testOnFire(final GameObject target, final GameObject other, final boolean expectTargetOnFire) { - 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!" - : "Expected [" + targetName + "] not to be on fire after colliding with [" + otherName + "] but it was!"; - - assertEquals(errorMessage, expectTargetOnFire, target.isOnFire()); - } - - /** - * Test if the damage state of the target matches the expected state after colliding with the - * given object - * - * @param target The target object - * @param other The other object - * @param expectedDamage The expected state of damage on the target object - */ - private void testDamaged(final GameObject target, final GameObject other, final boolean expectedDamage) { - final String targetName = target.getClass().getSimpleName(); - 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 + "] not to be damaged after colliding with [" + otherName + "] but it was!"; - - assertEquals(errorMessage, expectedDamage, target.isDamaged()); - } - -} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java deleted file mode 100644 index 120c9a883274..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/10/15 - 11:31 PM - * - * @author Jeroen Meulemeester - */ -public class FlamingAsteroidTest extends CollisionTest { - - @Override - final FlamingAsteroid getTestedObject() { - return new FlamingAsteroid(1, 2, 3, 4); - } - - /** - * Test the constructor parameters - */ - @Test - public void testConstructor() { - final FlamingAsteroid asteroid = new FlamingAsteroid(1, 2, 3, 4); - assertEquals(1, asteroid.getLeft()); - assertEquals(2, asteroid.getTop()); - assertEquals(3, asteroid.getRight()); - assertEquals(4, asteroid.getBottom()); - assertTrue(asteroid.isOnFire()); - assertFalse(asteroid.isDamaged()); - assertEquals("FlamingAsteroid at [1,2,3,4] damaged=false onFire=true", asteroid.toString()); - } - - /** - * Test what happens we collide with an asteroid - */ - @Test - public void testCollideFlamingAsteroid() { - testCollision( - new FlamingAsteroid(1, 2, 3, 4), - false, true, - false, true, - "FlamingAsteroid hits FlamingAsteroid." - ); - } - - /** - * Test what happens we collide with an meteoroid - */ - @Test - public void testCollideMeteoroid() { - testCollision( - new Meteoroid(1, 1, 3, 4), - false, false, - false, true, - "FlamingAsteroid hits Meteoroid." - ); - } - - /** - * Test what happens we collide with ISS - */ - @Test - public void testCollideSpaceStationIss() { - testCollision( - new SpaceStationIss(1, 1, 3, 4), - true, true, - false, true, - "FlamingAsteroid hits SpaceStationIss. SpaceStationIss is damaged! SpaceStationIss is set on fire!" - ); - } - - /** - * Test what happens we collide with MIR - */ - @Test - public void testCollideSpaceStationMir() { - testCollision( - new SpaceStationMir(1, 1, 3, 4), - true, true, - false, true, - "FlamingAsteroid hits SpaceStationMir. SpaceStationMir is damaged! SpaceStationMir is set on fire!" - ); - } - -} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java deleted file mode 100644 index 8eed497c0e42..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * Date: 12/10/15 - 11:31 PM - * - * @author Jeroen Meulemeester - */ -public class MeteoroidTest extends CollisionTest { - - @Override - final Meteoroid getTestedObject() { - return new Meteoroid(1, 2, 3, 4); - } - - /** - * Test the constructor parameters - */ - @Test - public void testConstructor() { - final Meteoroid meteoroid = new Meteoroid(1, 2, 3, 4); - assertEquals(1, meteoroid.getLeft()); - assertEquals(2, meteoroid.getTop()); - assertEquals(3, meteoroid.getRight()); - assertEquals(4, meteoroid.getBottom()); - assertFalse(meteoroid.isOnFire()); - assertFalse(meteoroid.isDamaged()); - assertEquals("Meteoroid at [1,2,3,4] damaged=false onFire=false", meteoroid.toString()); - } - - /** - * Test what happens we collide with an asteroid - */ - @Test - public void testCollideFlamingAsteroid() { - testCollision( - new FlamingAsteroid(1, 1, 3, 4), - false, true, - false, false, - "Meteoroid hits FlamingAsteroid." - ); - } - - /** - * Test what happens we collide with an meteoroid - */ - @Test - public void testCollideMeteoroid() { - testCollision( - new Meteoroid(1, 1, 3, 4), - false, false, - false, false, - "Meteoroid hits Meteoroid." - ); - } - - /** - * Test what happens we collide with ISS - */ - @Test - public void testCollideSpaceStationIss() { - testCollision( - new SpaceStationIss(1, 1, 3, 4), - true, false, - false, false, - "Meteoroid hits SpaceStationIss. SpaceStationIss is damaged!" - ); - } - - /** - * Test what happens we collide with MIR - */ - @Test - public void testCollideSpaceStationMir() { - testCollision( - new SpaceStationMir(1, 1, 3, 4), - true, false, - false, false, - "Meteoroid hits SpaceStationMir. SpaceStationMir is damaged!" - ); - } - -} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java deleted file mode 100644 index 1f4e476de1d8..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -import static junit.framework.TestCase.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Unit test for Rectangle - */ -public class RectangleTest { - - /** - * Test if the values passed through the constructor matches the values fetched from the getters - */ - @Test - public void testConstructor() { - final Rectangle rectangle = new Rectangle(1, 2, 3, 4); - assertEquals(1, rectangle.getLeft()); - assertEquals(2, rectangle.getTop()); - assertEquals(3, rectangle.getRight()); - assertEquals(4, rectangle.getBottom()); - } - - /** - * Test if the values passed through the constructor matches the values in the {@link - * #toString()} - */ - @Test - public void testToString() throws Exception { - final Rectangle rectangle = new Rectangle(1, 2, 3, 4); - assertEquals("[1,2,3,4]", rectangle.toString()); - } - - /** - * Test if the {@link Rectangle} class can detect if it intersects with another rectangle. - */ - @Test - public void testIntersection() { - assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1))); - assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8))); - assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3))); - assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1))); - } - -} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java deleted file mode 100644 index 8cde65d1102d..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * Date: 12/10/15 - 11:31 PM - * - * @author Jeroen Meulemeester - */ -public class SpaceStationIssTest extends CollisionTest { - - @Override - final SpaceStationIss getTestedObject() { - return new SpaceStationIss(1, 2, 3, 4); - } - - /** - * Test the constructor parameters - */ - @Test - public void testConstructor() { - final SpaceStationIss iss = new SpaceStationIss(1, 2, 3, 4); - assertEquals(1, iss.getLeft()); - assertEquals(2, iss.getTop()); - assertEquals(3, iss.getRight()); - assertEquals(4, iss.getBottom()); - assertFalse(iss.isOnFire()); - assertFalse(iss.isDamaged()); - assertEquals("SpaceStationIss at [1,2,3,4] damaged=false onFire=false", iss.toString()); - } - - /** - * Test what happens we collide with an asteroid - */ - @Test - public void testCollideFlamingAsteroid() { - testCollision( - new FlamingAsteroid(1, 1, 3, 4), - false, true, - false, false, - "SpaceStationIss hits FlamingAsteroid." - ); - } - - /** - * Test what happens we collide with an meteoroid - */ - @Test - public void testCollideMeteoroid() { - testCollision( - new Meteoroid(1, 1, 3, 4), - false, false, - false, false, - "SpaceStationIss hits Meteoroid." - ); - } - - /** - * Test what happens we collide with ISS - */ - @Test - public void testCollideSpaceStationIss() { - testCollision( - new SpaceStationIss(1, 1, 3, 4), - true, false, - false, false, - "SpaceStationIss hits SpaceStationIss. SpaceStationIss is damaged!" - ); - } - - /** - * Test what happens we collide with MIR - */ - @Test - public void testCollideSpaceStationMir() { - testCollision( - new SpaceStationMir(1, 1, 3, 4), - true, false, - false, false, - "SpaceStationIss hits SpaceStationMir. SpaceStationMir is damaged!" - ); - } - -} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java deleted file mode 100644 index 3dbab58baa4a..000000000000 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.doubledispatch; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * Date: 12/10/15 - 11:31 PM - * - * @author Jeroen Meulemeester - */ -public class SpaceStationMirTest extends CollisionTest { - - @Override - final SpaceStationMir getTestedObject() { - return new SpaceStationMir(1, 2, 3, 4); - } - - /** - * Test the constructor parameters - */ - @Test - public void testConstructor() { - final SpaceStationMir mir = new SpaceStationMir(1, 2, 3, 4); - assertEquals(1, mir.getLeft()); - assertEquals(2, mir.getTop()); - assertEquals(3, mir.getRight()); - assertEquals(4, mir.getBottom()); - assertFalse(mir.isOnFire()); - assertFalse(mir.isDamaged()); - assertEquals("SpaceStationMir at [1,2,3,4] damaged=false onFire=false", mir.toString()); - } - - /** - * Test what happens we collide with an asteroid - */ - @Test - public void testCollideFlamingAsteroid() { - testCollision( - new FlamingAsteroid(1, 1, 3, 4), - false, true, - false, false, - "SpaceStationMir hits FlamingAsteroid." - ); - } - - /** - * Test what happens we collide with an meteoroid - */ - @Test - public void testCollideMeteoroid() { - testCollision( - new Meteoroid(1, 1, 3, 4), - false, false, - false, false, - "SpaceStationMir hits Meteoroid." - ); - } - - /** - * Test what happens we collide with ISS - */ - @Test - public void testCollideSpaceStationIss() { - testCollision( - new SpaceStationIss(1, 1, 3, 4), - true, false, - false, false, - "SpaceStationMir hits SpaceStationIss. SpaceStationIss is damaged!" - ); - } - - /** - * Test what happens we collide with MIR - */ - @Test - public void testCollideSpaceStationMir() { - testCollision( - new SpaceStationMir(1, 1, 3, 4), - true, false, - false, false, - "SpaceStationMir hits SpaceStationMir. SpaceStationMir is damaged!" - ); - } - -} \ No newline at end of file diff --git a/eip-splitter/README.md b/eip-splitter/README.md deleted file mode 100644 index b5914750499e..000000000000 --- a/eip-splitter/README.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: pattern -title: EIP Splitter -folder: eip-splitter -permalink: /patterns/eip-splitter/ -categories: Enterprise integration -tags: - - Java - - Difficulty-Intermittent - - Enterprise integration ---- - -## Intent -It is very common in integration systems that incoming messages consists of many items bundled together. For example -an invoice document contains multiple invoice lines describing transaction (quantity, name of provided -service/sold goods, price etc.). Such bundled messages may not be accepted by other systems. This is where splitter -pattern comes in handy. It will take the whole document, split it based on given criteria and send individual -items to the endpoint. - -![alt text](./etc/sequencer.gif "Splitter") - -## Applicability -Use the Splitter pattern when - -* You need to split received data into smaller pieces to process them individually -* You need to control the size of data batches you are able to process - -## Credits - -* [Gregor Hohpe, Bobby Woolf - Enterprise Integration Patterns](http://www.enterpriseintegrationpatterns.com/patterns/messaging/Sequencer.html) -* [Apache Camel - Documentation](http://camel.apache.org/splitter.html) - diff --git a/eip-splitter/etc/sequencer.gif b/eip-splitter/etc/sequencer.gif deleted file mode 100644 index a925fa2098777dadbf4c9e9a2006e9513421b8dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2298 zcmVM)j$~<` zXsWJk>%Q9|%W!Sqc&_h!@BbtjVK}4#kI1BQ$!t1p2coq2tXi+wtajUpPNxU1cuX#v z&mZp>jBdN%@c2%>CWhtsynfF|(Cc=6f`f#GOn-m`cZQ6Oj*lmZfQyiomY0>1b(EN$ zo}Y4>Yn-5^rl(n=QlzM@uCG3-fv~i-wlK1+x4XQ(9HP3u!o$8otHH#{%Cs{^%g@lZ z$kEi*nA6tT+J)HL-ru3%;^TVV>7`uiUB1OEd82n6^~ zU;udh61wwOa3Dd00}v{lc#a{&hYlrD-1yDkMSvgwHF6wjt=`9m0SJmD$?}=Wlo(+G zT-mbbFp~rWIs{4c3cjB}g9;r=bf`^nKy#kd*;8H7r%jak)f_n&c7g2gjG43R*KIxHkwrxb?a;PC*FN(S zuW zGOk7Ab2;Xw+l?_4x#B4t`uHM{{Sh%(X{05BB#u^2*rSt%eF&w8B!0GuV`D=0*mGNQ z`6P%zsx_o!f53G}oL8nnr*;=am7kg;;uGZ%gJ6Y)pgw68$4dnyny5jFCR%3>P4cPW zn_E>i#-mW=$!MdSI=ZK%E>e2vrKHZ5X91lqDv+X>q5vock%Fq8s7|~JLaWV{S}6qw zs2V_{sIFQ7t|my4XPYzf=Vq*(DSH_ItxXu4hOS!>>q0$>rW)+8){^i=1CFvy@|imVsZtfuyhwh@Nb;r(A1l zfB^!HT{hVPjGeR}MSs0*qicTvhy)Qg9W%w{o(1!`09SqQ$9Zb)8$?LXTj4#t})~t8`-e~O|V&7s|9z)<+SC;s}k{f+GxQ(CfdgGACn>yHK zuzUH-&UQXSvK3=Yb?8&{6Zldg1r4sRhnu`QudO%FxZ04#`?lA^+WR}Nm_ zRxDx~JEX-MI--aC1B@K!__i^wPlI^`1r|ZL#@O7CiK$u2APH#@Lzc0MXVjwu{Ux;s zJ<^SVq@Z#vcrr^0k%*V;S#UPFx!z4}iEiv*Ut|d$S}I3zm&D^LS$Q2U9;Fv1AtNGp z$xGt+@|U{^<{@9WKocyon4WASGMAyuTpG}W(6r7mr&)_?p7K-Kgv~a&2@7uu^P02S zV>q8CO>*7@m*2e1ROU&~dA8G?#Yo{fhsc_G`tzScxhFoUc}H~WA!i89*+923ziGRmD^p>*)oOLs2xuLvUj0xftMXN^ zcr`0rYv9+w{*|nVl~Y}LQCPu}HLQ*;D_|Y_Rmx_{t%(&ZWcRvQlHS#_d==}X8oO7t ziuSTk%`9MrO4rU746~bkY@TBA+0t@0ve&AuYU`l_PEbXtSMvm+bgK-e+IF(XJxyv= zE8FC@HMyJrjcr)giUQ*X_Zpa;?Q&aNDC(wCt=2t_SP>gq@Gh6I<4vk)y<1)82BE7v z!|r*r>s;3|gSn@zZ)5YSUdVE{1iDCTbVEyExtjIA_N51M2dv+_R`#&FMKFNjV%P^u zSF;jMFku&LS+@E$wHH2ah8YN23xl?~8t#ODeB%OJ%?25_FV-<6)a%^X(pShKrf~>-JJ{wv7{5JMac(8cK*iR$x8r^9 zb}5YH@17U9`6Yy)1Z?EPwz$O`%CZQ&+}5Uqx3_W*S)Sb~Ws&V!cvreIp6l}GDYLZC zmRhf;fAbpOuqpb$jJ|GO3QTD>L%7i+MYLV9>}Ej^`La=FG*!18>MGwy(@Ms{l^N{b zPj8shLWb|8VSQrlrn(iY&T)Oq{A%zTw$;3@v9DJh>?Ge>k-LtytLuzpWfxk^PKK^l zk6lD*b6VD_wzjk9L+m5p_RiG)M5NOk?P8PKyw?6ModI0sO4pjj;f}Yw=S}Z=+xy=5 U&bPkz&F_Bu``-ZHY6JiPJ08586aWAK diff --git a/eip-splitter/pom.xml b/eip-splitter/pom.xml deleted file mode 100644 index fb7e4ca9b15e..000000000000 --- a/eip-splitter/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - 4.0.0 - eip-splitter - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.apache.camel - camel-core - ${camel.version} - - - - org.apache.camel - camel-spring-boot - ${camel.version} - - - - - org.springframework.boot - spring-boot-starter-test - - - - org.apache.camel - camel-test-spring - ${camel.version} - - - - \ No newline at end of file diff --git a/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java b/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java deleted file mode 100644 index 1f52e9569ce8..000000000000 --- a/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.iluwatar.eip.splitter; - -import org.apache.camel.CamelContext; -import org.apache.camel.builder.RouteBuilder; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * It is very common in integration systems that incoming messages consists of many items bundled together. For example - * an invoice document contains multiple invoice lines describing transaction (quantity, name of provided - * service/sold goods, price etc.). Such bundled messages may not be accepted by other systems. This is where splitter - * pattern comes in handy. It will take the whole document, split it based on given criteria and send individual - * items to the endpoint. - * - *

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

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

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

- * - * In this example input/output endpoints names are stored in application.properties file. - */ -@Component -public class SplitterRoute extends RouteBuilder { - - /** - * Configures the route - * @throws Exception in case of exception during configuration - */ - @Override - public void configure() throws Exception { - // Main route - from("{{entry}}").split().body().to("{{endpoint}}"); - } -} diff --git a/eip-splitter/src/main/resources/application.properties b/eip-splitter/src/main/resources/application.properties deleted file mode 100644 index cb879e6e270e..000000000000 --- a/eip-splitter/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -entry=direct:entry -endpoint=direct:endpoint diff --git a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java deleted file mode 100644 index bff2cf0b1c62..000000000000 --- a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.iluwatar.eip.splitter; - -import org.junit.Test; - -/** - * Test for App class - */ -public class AppTest { - - @Test - public void testMain() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java deleted file mode 100644 index 78fc37d91403..000000000000 --- a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.iluwatar.eip.splitter.routes; - -import org.apache.camel.EndpointInject; -import org.apache.camel.Message; -import org.apache.camel.ProducerTemplate; -import org.apache.camel.component.mock.MockEndpoint; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.junit.Assert.assertEquals; - -/** - * Test class for SplitterRoute. - *

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

- */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SplitterRouteTest.class) -@ActiveProfiles("test") -@EnableAutoConfiguration -@ComponentScan -public class SplitterRouteTest { - - @EndpointInject(uri = "{{entry}}") - private ProducerTemplate entry; - - @EndpointInject(uri = "{{endpoint}}") - private MockEndpoint endpoint; - - /** - * Test if endpoint receives three separate messages. - * @throws Exception in case of en exception during the test - */ - @Test - @DirtiesContext - public void testSplitter() throws Exception { - - // Three items in one entry message - entry.sendBody(new String[] {"TEST1", "TEST2", "TEST3"}); - - // Endpoint should have three different messages in the end order of the messages is not important - endpoint.expectedMessageCount(3); - endpoint.assertIsSatisfied(); - } -} diff --git a/eip-splitter/src/test/resources/application-test.properties b/eip-splitter/src/test/resources/application-test.properties deleted file mode 100644 index f657ea5a102c..000000000000 --- a/eip-splitter/src/test/resources/application-test.properties +++ /dev/null @@ -1,2 +0,0 @@ -entry=direct:entry -endpoint=mock:endpoint diff --git a/eip-wire-tap/README.md b/eip-wire-tap/README.md deleted file mode 100644 index d2742aa313f9..000000000000 --- a/eip-wire-tap/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: EIP Wire Tap -folder: eip-wire-tap -permalink: /patterns/eip-wire-tap/ -categories: Enterprise integration -tags: - - Java - - Difficulty-Intermittent - - Enterprise integration ---- - -## Intent -In most integration cases there is a need to monitor the messages flowing through the system. It is usually achieved -by intercepting the message and redirecting it to a different location like console, filesystem or the database. -It is important that such functionality should not modify the original message and influence the processing path. - -![alt text](./etc/wiretap.gif "Wire Tap") - -## Applicability -Use the Wire Tap pattern when - -* You need to monitor messages flowing through the system -* You need to redirect the same, unchanged message to two different endpoints/paths - -## Credits - -* [Gregor Hohpe, Bobby Woolf - Enterprise Integration Patterns](http://www.enterpriseintegrationpatterns.com/patterns/messaging/WireTap.html) -* [Apache Camel - Documentation](http://camel.apache.org/wire-tap.html) diff --git a/eip-wire-tap/etc/wiretap.gif b/eip-wire-tap/etc/wiretap.gif deleted file mode 100644 index 4141737167ca7c590baaef807534a74ec6e46c8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3067 zcmVNk%w1Vg3QN0M!5h|NsB@_xJDb@8{>|%>S9+-`~dfl-JkSx#x?_%*?Xi zhQ7YOrq6t}wY8kXb*-(fnZI+Sq@;|mX_=XsfuUiGi;IPYg>sKpe0+R!b8}{YOlD?g zT5v;JT3StDI#E$kN=iyXLP9!7D?B_rGe9OYGczqXA}T5>At50eAQKrG850-|4-XFw z5DEzi2?YlP0002~0RjL3000000000000000000000000000000000000000000000 z00000A^8La6aX;*EC2ui0R92B000L6K!9*aEE41ejE#QM|Xmz`=aE0K~<+$Hk^e zyr)B>zQWSe)LX>Hq07nJpxwyI-__#d${&Cc8H^8Nm{ z_0ol7=FQ!@e+U!Sn)S-w!GhnkNmNL&A}5BixanhOWLY+F7DI{@$#0~|ljKUGT*>m6 z%9b!=%A85Frp=o;bL!m5v!~DhpFo2O9ZIyQ(W6L{DqYI7sne%Wqnf!#wW`&tShH%~ z%5`JBu3*E81uJf>*|TWLK1<8CZCihC-fw9A@EZw5KJbZ619W6LJ2+O#m# znQF7f>>8e_*}#K4&b<2c-bcD|W76$gu<+;52Q$BY92arU$}de%={&mk+1r6-x0Jkk zqwrNG7S|l1o~kMT0rww<8imGHK`ht3m}S1{=bwPS8RwjJK7pbnU&a^a6C+fx zz@v~xD(R$@R%+>`ls16E0|`8ELI79XiRX8E645B8sHUnas+w}@DX67%X-J}mq5?>% zLOc+{s=W5P>INMoAnXPhgzDm`-r)*>uD&+w?4-a7n*g!3B2m?oc3Q*Xp-W)ohq54G z(7?FlmTT_0=%%ax?z-u2Ds2NQ7>n$E;EK!cz4+#Pue-v+TP;Tr^^&a@v@+p~tYt*_ zfB;1Vz`_IiMl5l@6QCfiuqYhh#KIjNJMVJ}GfafT5KnCK$>mmjaRM0|!7(WK04zn9 z2*d0ew*+;2SwraLf|^&dELwzSF9VRk2@fQ#^wLZ>?ex=7NBwjLAgm06ZA%a>@-7~K z99)E24{@~AWS4Dr*;HGNwGd&iW$oK*F{F>J*Ze%UGjcZsw9TvGoHN|}WVG`^?*!eO z5=C;{KnZ6z?)cdq1bcA@6*!T&$fB~RfCw;{;DC-o6LC2Ji$8Aq=}kwzGUY~$zFS5e z5&qCe_PoRYbK$lZ&Np_l?(OaEum{i06sl#J_yi$Dp#1X8H}CxO&_^#l^dD@nGO@;A zp80wtoU(!e0~Vh>1`i-V{rTvpkAC&nhhXKx*~L6O?FHdJkUDi2*Csv$iN0V@PQDFpadrvK@eo%dgCKf1rm@s4dCT2Bsh!#jfX%5Qt*T* zOyLPF*gh+5Fn)0Roy_b9Gx`B=Anhm^@d${+9(L>=#yVUQinPIHl>mWAOrjE($iyZ( z@rh0Zf%Pu7fh{qCh=t0W0wBP}E_(5cU<@M!Qh*8sgfDbMz@ibM$i_Chv5iu^o)y!m z!7R%EFLwX471tzVJJ`)FfAjMpJGSM&b;!_=`x~B}(8x9n6j2CAd!r;L`Nj`a?P6E6 zoFfaxwFgPy1*W(F=!A#_%{s;zaK)C=Ie@e&)(j)#H6CC>)gzfb|} zkP%6ww+we7B%D$R0%(B+mdVU!I`f&(jHWcF8O;rpU}Ys(fD?|{$p<+A1{8Qugt(bZ zYMS$$=sc%2S9Stz7J-|udx-3W2}t1S50Jr>C;$3JGl=w&Yq-p%B4@_PB#fW~8BC}` ziNt~hNNWKskk^A000Rh!v!F;Q0YVqb(d;$!p%IPMECWizf94aQ0u|^kJJ!oZ`p$0u zy2wY~vY;#rj35Iz&8bdz%F~|u^rt}eX$deOEem`=q7I^{MMqi8C)hNoP>rfoqdL^0 z9#y1+1mX{C=(Bnd4sUy$-{ADQmX<1LZBGaQ3N|p+wz^fS8&H8mSylj~4oImNC1qOI z`qsYsb*FKiD+=n0)w9OaMtXh10#s0f5jgg-kd3TlCrjDNT6VH1U;zkFfL4NL2(L`- ztP>X7*vp#sw5YvoW;ZKZYZWpOI*f#}girtrbo91Z+5iYNw#WfFKm!`!01P|;+|Nk~ zqe-YOZkM|x-SYNdhV`3u5?i0HMF#<(M8yltcwFl4M@D9~P-_D;AmO5d184OAE-j>c z9zue*snyt?cd&bk?WPyL0D0}L+{+{NQs+VDg#mi+J6;35mv;w#&4B1@Ujlb1!R+l1 za^GX!?+ACm4mJ*i_4|j}$|yq!XaRRKOq~rUctjauK!!Z5C=>S=za8=#sU|!b7aJDE zGKLO|Da7G#@%P3p%5ijdoT480A+~&>@qUD?VYM)KaMhvrwkq^ zuV}*`4D($48w@dI zE)A+jU21BadeyLwwX7r1YN=R4Gq%n(RB)~9UN42$z7DogfGzA|`(y$~nt-vFt&;;B z>AB2~HcgOCBxOtc+B0!Bk)Vz3Zm)#e*7mlzQKD^bkNeyfSs=RCU6BDiDrt`*EW77D zjsYO=1uQ6mzW1#H7>vLIfT6d*fgu1ClwboDpmn4g5P=D7U<4tVJmVXGRL51`@|s`bst?dAG$8| zudiI}XwL)LhYt3%yPXbeH~ZV?K8Ltt{p@tlI~(jSb-nvN4SZ+%-v>{Iz_*?7i2s7& z@t*j`Z(;F{kNo2=4)dgY{qB;_{1qUt`OZs$^PUfV6F@Ke(wCC*Ilp?}P0xDKp+4wr zXMF2fPx{%@{`HnGJLYXa``Ytf^uGVS=YubN%@e=)l0QE39k2Z5C%*a4Cp^wQoEL4#yXqLGDK*c4pY9$xl^ zy%vU`;e}+V6lRzoW0;0fSYb}shHhwua5#l>IEPzUhgf)rcnF4i*oA!9hfA@Bo`Hsf zI24399G7;8bhsXd$cR9Zhy)UdkZ2T=xEPOEi9K8kG2nLJ^9H;fbV( z6Q(FaqnL_6v5FAVimtecAGC - - - 4.0.0 - eip-wire-tap - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.apache.camel - camel-core - ${camel.version} - - - - org.apache.camel - camel-spring-boot - ${camel.version} - - - - - org.springframework.boot - spring-boot-starter-test - - - - org.apache.camel - camel-test-spring - ${camel.version} - - - - \ No newline at end of file diff --git a/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java b/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java deleted file mode 100644 index 7bf4ce0d4991..000000000000 --- a/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.iluwatar.eip.wiretap; - -import org.apache.camel.CamelContext; -import org.apache.camel.builder.RouteBuilder; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * In most integration cases there is a need to monitor the messages flowing through the system. It is usually achieved - * by intercepting the message and redirecting it to a different location like console, filesystem or the database. - * It is important that such functionality should not modify the original message and influence the processing path. - * - *

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

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

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

- * - * In this example input/output endpoints names are stored in application.properties file. - */ -@Component -public class WireTapRoute extends RouteBuilder { - - /** - * Configures the route - * @throws Exception in case of exception during configuration - */ - @Override - public void configure() throws Exception { - // Main route - from("{{entry}}").wireTap("direct:wireTap").to("{{endpoint}}"); - - // Wire tap route - from("direct:wireTap").log("Message: ${body}").to("{{wireTapEndpoint}}"); - } -} diff --git a/eip-wire-tap/src/main/resources/application.properties b/eip-wire-tap/src/main/resources/application.properties deleted file mode 100644 index 6dabe6ccc9ee..000000000000 --- a/eip-wire-tap/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -entry=direct:entry -endpoint=direct:endpoint -wireTapEndpoint=direct:wireTapEndpoint \ No newline at end of file diff --git a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java deleted file mode 100644 index 25b9d8550f4c..000000000000 --- a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.iluwatar.eip.wiretap; - -import org.junit.Test; - -/** - * Test for App class - */ -public class AppTest { - - @Test - public void testMain() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java deleted file mode 100644 index a7b15f45eb93..000000000000 --- a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.iluwatar.eip.wiretap.routes; - -import org.apache.camel.EndpointInject; -import org.apache.camel.Message; -import org.apache.camel.ProducerTemplate; -import org.apache.camel.component.mock.MockEndpoint; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.junit.Assert.assertEquals; - -/** - * Test class for WireTapRoute. - *

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

- */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = WireTapRouteTest.class) -@ActiveProfiles("test") -@EnableAutoConfiguration -@ComponentScan -public class WireTapRouteTest { - - @EndpointInject(uri = "{{entry}}") - private ProducerTemplate entry; - - @EndpointInject(uri = "{{endpoint}}") - private MockEndpoint endpoint; - - @EndpointInject(uri = "{{wireTapEndpoint}}") - private MockEndpoint wireTapEndpoint; - - /** - * Test if both endpoints receive exactly one message containing the same, unchanged body. - * @throws Exception in case of en exception during the test - */ - @Test - @DirtiesContext - public void testWireTap() throws Exception { - entry.sendBody("TEST"); - - endpoint.expectedMessageCount(1); - wireTapEndpoint.expectedMessageCount(1); - - endpoint.assertIsSatisfied(); - wireTapEndpoint.assertIsSatisfied(); - - Message endpointIn = endpoint.getExchanges().get(0).getIn(); - Message wireTapEndpointIn = wireTapEndpoint.getExchanges().get(0).getIn(); - - assertEquals("TEST", endpointIn.getBody()); - assertEquals("TEST", wireTapEndpointIn.getBody()); - } -} diff --git a/eip-wire-tap/src/test/resources/application-test.properties b/eip-wire-tap/src/test/resources/application-test.properties deleted file mode 100644 index 1719c8ca4ab4..000000000000 --- a/eip-wire-tap/src/test/resources/application-test.properties +++ /dev/null @@ -1,3 +0,0 @@ -entry=direct:entry -endpoint=mock:endpoint -wireTapEndpoint=mock:wireTapEndpoint \ No newline at end of file diff --git a/event-aggregator/README.md b/event-aggregator/README.md deleted file mode 100644 index ce7f358de9f8..000000000000 --- a/event-aggregator/README.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: pattern -title: Event Aggregator -folder: event-aggregator -permalink: /patterns/event-aggregator/ -pumlid: PSf13iCW30NHgxG70Ezx6uTOX0eCih-JwvTzTwEdUJSjFKu9wwyBMFuXCdvoRRZY21ShKo6ANEQWrkDXiD6NRqwdUAkQ5WDYwZJOTv3SUqzSgqbbp0qeVvZ3Hbun-Wy0 -categories: Structural -tags: - - Java - - Difficulty-Beginner - - Reactive ---- - -## Intent -A system with lots of objects can lead to complexities when a -client wants to subscribe to events. The client has to find and register for -each object individually, if each object has multiple events then each event -requires a separate subscription. An Event Aggregator acts as a single source -of events for many objects. It registers for all the events of the many objects -allowing clients to register with just the aggregator. - -![alt text](./etc/classes.png "Event Aggregator") - -## Applicability -Use the Event Aggregator pattern when - -* Event Aggregator is a good choice when you have lots of objects that are - potential event sources. Rather than have the observer deal with registering - with them all, you can centralize the registration logic to the Event - Aggregator. As well as simplifying registration, a Event Aggregator also - simplifies the memory management issues in using observers. - -## Credits - -* [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html) diff --git a/event-aggregator/etc/classes.png b/event-aggregator/etc/classes.png deleted file mode 100644 index 295719ea37125d8b49bb8967e2269355d6901c6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45639 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 z 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 E2VMR^U;qFB diff --git a/event-aggregator/etc/classes.ucls b/event-aggregator/etc/classes.ucls deleted file mode 100644 index 4a869b9d24e2..000000000000 --- a/event-aggregator/etc/classes.ucls +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/event-aggregator/etc/event-aggregator.urm.puml b/event-aggregator/etc/event-aggregator.urm.puml deleted file mode 100644 index 341d7d65e02c..000000000000 --- a/event-aggregator/etc/event-aggregator.urm.puml +++ /dev/null @@ -1,74 +0,0 @@ -@startuml -package com.iluwatar.event.aggregator { - class App { - + App() - + main(args : String[]) {static} - } - enum Event { - + STARK_SIGHTED {static} - + TRAITOR_DETECTED {static} - + WARSHIPS_APPROACHING {static} - - description : String - + toString() : String - + valueOf(name : String) : Event {static} - + values() : Event[] {static} - } - abstract class EventEmitter { - - observers : List - + EventEmitter() - + EventEmitter(obs : EventObserver) - # notifyObservers(e : Event) - + registerObserver(obs : EventObserver) - + timePasses(Weekday) {abstract} - } - interface EventObserver { - + onEvent(Event) {abstract} - } - class KingJoffrey { - - LOGGER : Logger {static} - + KingJoffrey() - + onEvent(e : Event) - } - class KingsHand { - + KingsHand() - + KingsHand(obs : EventObserver) - + onEvent(e : Event) - + timePasses(day : Weekday) - } - class LordBaelish { - + LordBaelish() - + LordBaelish(obs : EventObserver) - + timePasses(day : Weekday) - } - class LordVarys { - + LordVarys() - + LordVarys(obs : EventObserver) - + timePasses(day : Weekday) - } - class Scout { - + Scout() - + Scout(obs : EventObserver) - + timePasses(day : Weekday) - } - enum Weekday { - + FRIDAY {static} - + MONDAY {static} - + SATURDAY {static} - + SUNDAY {static} - + THURSDAY {static} - + TUESDAY {static} - + WEDNESDAY {static} - - description : String - + toString() : String - + valueOf(name : String) : Weekday {static} - + values() : Weekday[] {static} - } -} -EventEmitter --> "-observers" EventObserver -KingJoffrey ..|> EventObserver -KingsHand ..|> EventObserver -KingsHand --|> EventEmitter -LordBaelish --|> EventEmitter -LordVarys --|> EventEmitter -Scout --|> EventEmitter -@enduml \ No newline at end of file diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml deleted file mode 100644 index a3e7f96cf503..000000000000 --- a/event-aggregator/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - event-aggregator - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/App.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/App.java deleted file mode 100644 index 2c489ff5b002..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/App.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * A system with lots of objects can lead to complexities when a client wants to subscribe to - * events. The client has to find and register for each object individually, if each object has - * multiple events then each event requires a separate subscription. - *

- * An Event Aggregator acts as a single source of events for many objects. It registers for all the - * events of the many objects allowing clients to register with just the aggregator. - *

- * In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to - * {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to - * {@link KingJoffrey}. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - KingJoffrey kingJoffrey = new KingJoffrey(); - KingsHand kingsHand = new KingsHand(kingJoffrey); - - List emitters = new ArrayList<>(); - emitters.add(kingsHand); - emitters.add(new LordBaelish(kingsHand)); - emitters.add(new LordVarys(kingsHand)); - emitters.add(new Scout(kingsHand)); - - for (Weekday day : Weekday.values()) { - for (EventEmitter emitter : emitters) { - emitter.timePasses(day); - } - } - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Event.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Event.java deleted file mode 100644 index daa3a9674031..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Event.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * Event enumeration. - * - */ -public enum Event { - - STARK_SIGHTED("Stark sighted"), WARSHIPS_APPROACHING("Warships approaching"), TRAITOR_DETECTED( - "Traitor detected"); - - private String description; - - Event(String description) { - this.description = description; - } - - public String toString() { - return description; - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java deleted file mode 100644 index af19727b2959..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import java.util.LinkedList; -import java.util.List; - -/** - * - * EventEmitter is the base class for event producers that can be observed. - * - */ -public abstract class EventEmitter { - - private List observers; - - public EventEmitter() { - observers = new LinkedList<>(); - } - - public EventEmitter(EventObserver obs) { - this(); - registerObserver(obs); - } - - public final void registerObserver(EventObserver obs) { - observers.add(obs); - } - - protected void notifyObservers(Event e) { - for (EventObserver obs : observers) { - obs.onEvent(e); - } - } - - public abstract void timePasses(Weekday day); -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventObserver.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventObserver.java deleted file mode 100644 index e88d571fbf70..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventObserver.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * Observers of events implement this interface. - * - */ -public interface EventObserver { - - void onEvent(Event e); - -} 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 deleted file mode 100644 index 9e341f1c78fd..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * KingJoffrey observes events from {@link KingsHand}. - * - */ -public class KingJoffrey implements EventObserver { - - private static final Logger LOGGER = LoggerFactory.getLogger(KingJoffrey.class); - - @Override - public void onEvent(Event e) { - LOGGER.info("Received event from the King's Hand: {}", e.toString()); - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingsHand.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingsHand.java deleted file mode 100644 index 2de7021b34d6..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingsHand.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * KingsHand observes events from multiple sources and delivers them to listeners. - * - */ -public class KingsHand extends EventEmitter implements EventObserver { - - public KingsHand() { - super(); - } - - public KingsHand(EventObserver obs) { - super(obs); - } - - @Override - public void onEvent(Event e) { - notifyObservers(e); - } - - @Override - public void timePasses(Weekday day) { - // NOP - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordBaelish.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordBaelish.java deleted file mode 100644 index 9204aa572cae..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordBaelish.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * LordBaelish produces events. - * - */ -public class LordBaelish extends EventEmitter { - - public LordBaelish() { - super(); - } - - public LordBaelish(EventObserver obs) { - super(obs); - } - - @Override - public void timePasses(Weekday day) { - if (day.equals(Weekday.FRIDAY)) { - notifyObservers(Event.STARK_SIGHTED); - } - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordVarys.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordVarys.java deleted file mode 100644 index dc6009b8ccc9..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordVarys.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * LordVarys produces events. - * - */ -public class LordVarys extends EventEmitter { - - public LordVarys() { - super(); - } - - public LordVarys(EventObserver obs) { - super(obs); - } - - @Override - public void timePasses(Weekday day) { - if (day.equals(Weekday.SATURDAY)) { - notifyObservers(Event.TRAITOR_DETECTED); - } - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Scout.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Scout.java deleted file mode 100644 index c8dcf5ba33cd..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Scout.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * Scout produces events. - * - */ -public class Scout extends EventEmitter { - - public Scout() { - super(); - } - - public Scout(EventObserver obs) { - super(obs); - } - - @Override - public void timePasses(Weekday day) { - if (day.equals(Weekday.TUESDAY)) { - notifyObservers(Event.WARSHIPS_APPROACHING); - } - } -} diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Weekday.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Weekday.java deleted file mode 100644 index 2072e227c838..000000000000 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/Weekday.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * - * Weekday enumeration - * - */ -public enum Weekday { - - MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY( - "Friday"), SATURDAY("Saturday"), SUNDAY("Sunday"); - - private String description; - - Weekday(String description) { - this.description = description; - } - - public String toString() { - return description; - } -} diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/AppTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/AppTest.java deleted file mode 100644 index 6cd678704c15..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java deleted file mode 100644 index a67272789cfd..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import static org.mockito.Matchers.eq; -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.mockito.Mockito.verifyZeroInteractions; - -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Supplier; -import org.junit.Test; - -/** - * Date: 12/12/15 - 10:58 PM - * Tests for Event Emitter - * @param Type of Event Emitter - * @author Jeroen Meulemeester - */ -public abstract class EventEmitterTest { - - /** - * Factory used to create a new instance of the test object with a default observer - */ - private final Function factoryWithDefaultObserver; - - /** - * Factory used to create a new instance of the test object without passing a default observer - */ - private final Supplier factoryWithoutDefaultObserver; - - /** - * The day of the week an event is expected - */ - private final Weekday specialDay; - - /** - * The expected event, emitted on the special day - */ - private final Event event; - - /** - * Create a new event emitter test, using the given test object factories, special day and event - */ - EventEmitterTest(final Weekday specialDay, final Event event, - final Function factoryWithDefaultObserver, - final Supplier factoryWithoutDefaultObserver) { - - this.specialDay = specialDay; - this.event = event; - this.factoryWithDefaultObserver = Objects.requireNonNull(factoryWithDefaultObserver); - this.factoryWithoutDefaultObserver = Objects.requireNonNull(factoryWithoutDefaultObserver); - } - - /** - * Go over every day of the month, and check if the event is emitted on the given day. This test - * is executed twice, once without a default emitter and once with - */ - @Test - public void testAllDays() { - testAllDaysWithoutDefaultObserver(specialDay, event); - testAllDaysWithDefaultObserver(specialDay, event); - } - - /** - * Pass each week of the day, day by day to the event emitter and verify of the given observers - * received the correct event on the special day. - * - * @param specialDay The special day on which an event is emitted - * @param event The expected event emitted by the test object - * @param emitter The event emitter - * @param observers The registered observer mocks - */ - private void testAllDays(final Weekday specialDay, final Event event, final E emitter, - final EventObserver... observers) { - - for (final Weekday weekday : Weekday.values()) { - // Pass each week of the day, day by day to the event emitter - emitter.timePasses(weekday); - - if (weekday == specialDay) { - // On a special day, every observer should have received the event - for (final EventObserver observer : observers) { - verify(observer, times(1)).onEvent(eq(event)); - } - } else { - // On any other normal day, the observers should have received nothing at all - verifyZeroInteractions(observers); - } - } - - // The observers should not have received any additional events after the week - verifyNoMoreInteractions(observers); - } - - /** - * Go over every day of the month, and check if the event is emitted on the given day. Use an - * event emitter without a default observer - * - * @param specialDay The special day on which an event is emitted - * @param event The expected event emitted by the test object - */ - private void testAllDaysWithoutDefaultObserver(final Weekday specialDay, final Event event) { - final EventObserver observer1 = mock(EventObserver.class); - final EventObserver observer2 = mock(EventObserver.class); - - final E emitter = this.factoryWithoutDefaultObserver.get(); - emitter.registerObserver(observer1); - emitter.registerObserver(observer2); - - testAllDays(specialDay, event, emitter, observer1, observer2); - } - - /** - * Go over every day of the month, and check if the event is emitted on the given day. - * - * @param specialDay The special day on which an event is emitted - * @param event The expected event emitted by the test object - */ - private void testAllDaysWithDefaultObserver(final Weekday specialDay, final Event event) { - final EventObserver defaultObserver = mock(EventObserver.class); - final EventObserver observer1 = mock(EventObserver.class); - final EventObserver observer2 = mock(EventObserver.class); - - final E emitter = this.factoryWithDefaultObserver.apply(defaultObserver); - emitter.registerObserver(observer1); - emitter.registerObserver(observer2); - - testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2); - } - -} diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java deleted file mode 100644 index 54c511f8c73e..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/12/15 - 2:52 PM - * - * @author Jeroen Meulemeester - */ -public class EventTest { - - /** - * Verify if every event has a non-null, non-empty description - */ - @Test - public void testToString() { - for (final Event event : Event.values()) { - final String toString = event.toString(); - assertNotNull(toString); - assertFalse(toString.trim().isEmpty()); - } - } - -} \ No newline at end of file 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 deleted file mode 100644 index 1743c32118df..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/12/15 - 3:04 PM - * - * @author Jeroen Meulemeester - */ -public class KingJoffreyTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(KingJoffrey.class); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * Test if {@link KingJoffrey} tells us what event he received - */ - @Test - public void testOnEvent() { - final KingJoffrey kingJoffrey = new KingJoffrey(); - - 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(); - assertEquals(expectedMessage, appender.getLastMessage()); - assertEquals(i + 1, appender.getLogSize()); - } - - } - - 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/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java deleted file mode 100644 index ba1327182116..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import org.junit.Test; - -import static org.mockito.Matchers.eq; -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; - -/** - * Date: 12/12/15 - 10:57 AM - * - * @author Jeroen Meulemeester - */ -public class KingsHandTest extends EventEmitterTest { - - /** - * Create a new test instance, using the correct object factory - */ - public KingsHandTest() { - super(null, null, KingsHand::new, KingsHand::new); - } - - /** - * The {@link KingsHand} is both an {@link EventEmitter} as an {@link EventObserver} so verify if every - * event received is passed up to it's superior, in most cases {@link KingJoffrey} but now just a - * mocked observer. - */ - @Test - public void testPassThrough() throws Exception { - final EventObserver observer = mock(EventObserver.class); - final KingsHand kingsHand = new KingsHand(observer); - - // The kings hand should not pass any events before he received one - verifyZeroInteractions(observer); - - // Verify if each event is passed on to the observer, nothing less, nothing more. - for (final Event event : Event.values()) { - kingsHand.onEvent(event); - verify(observer, times(1)).onEvent(eq(event)); - verifyNoMoreInteractions(observer); - } - - } - -} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java deleted file mode 100644 index 5042c8f8d00b..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * Date: 12/12/15 - 10:57 AM - * - * @author Jeroen Meulemeester - */ -public class LordBaelishTest extends EventEmitterTest { - - /** - * Create a new test instance, using the correct object factory - */ - public LordBaelishTest() { - super(Weekday.FRIDAY, Event.STARK_SIGHTED, LordBaelish::new, LordBaelish::new); - } - -} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java deleted file mode 100644 index 7af5d9be8f19..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * Date: 12/12/15 - 10:57 AM - * - * @author Jeroen Meulemeester - */ -public class LordVarysTest extends EventEmitterTest { - - /** - * Create a new test instance, using the correct object factory - */ - public LordVarysTest() { - super(Weekday.SATURDAY, Event.TRAITOR_DETECTED, LordVarys::new, LordVarys::new); - } - -} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java deleted file mode 100644 index 87ed209d472a..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -/** - * Date: 12/12/15 - 10:57 AM - * - * @author Jeroen Meulemeester - */ -public class ScoutTest extends EventEmitterTest { - - /** - * Create a new test instance, using the correct object factory - */ - public ScoutTest() { - super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new); - } - -} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java deleted file mode 100644 index ab25d7ccc237..000000000000 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.event.aggregator; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/12/15 - 2:12 PM - * - * @author Jeroen Meulemeester - */ -public class WeekdayTest { - - @Test - public void testToString() throws Exception { - for (final Weekday weekday : Weekday.values()) { - final String toString = weekday.toString(); - assertNotNull(toString); - assertEquals(weekday.name(), toString.toUpperCase()); - } - } - -} \ No newline at end of file diff --git a/event-asynchronous/README.md b/event-asynchronous/README.md deleted file mode 100644 index 4c26e0a3caa6..000000000000 --- a/event-asynchronous/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: Event-based Asynchronous -folder: event-asynchronous -permalink: /patterns/event-asynchronous/ -categories: Concurrency -tags: - - difficulty-intermediate - - performance - - Java ---- - -## Intent -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. - -![alt text](./etc/event-asynchronous.png "Event-based Asynchronous") - -## Applicability -Use the Event-based Asynchronous pattern(s) when - -* Time-consuming tasks are needed to run in the background without disrupting the current application. - -## Credits - -* [Event-based Asynchronous Pattern Overview](https://msdn.microsoft.com/en-us/library/wewwczdw%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) diff --git a/event-asynchronous/etc/event-asynchronous.png b/event-asynchronous/etc/event-asynchronous.png deleted file mode 100644 index a46ffe1c5d17773d38dac792349cc547adc06955..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31413 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/event-asynchronous/etc/event-asynchronous.urm.puml b/event-asynchronous/etc/event-asynchronous.urm.puml deleted file mode 100644 index 0d683d27d77f..000000000000 --- a/event-asynchronous/etc/event-asynchronous.urm.puml +++ /dev/null @@ -1,66 +0,0 @@ -@startuml -package com.iluwatar.event.asynchronous { - class App { - - LOGGER : Logger {static} - + PROP_FILE_NAME : String {static} - ~ interactiveMode : boolean - + App() - + main(args : String[]) {static} - + quickRun() - + run() - + runInteractiveMode() - + setUp() - } - class Event { - - LOGGER : Logger {static} - - eventId : int - - eventListener : ThreadCompleteListener - - eventTime : int - - isComplete : boolean - - isSynchronous : boolean - - thread : Thread - + Event(eventId : int, eventTime : int, isSynchronous : boolean) - + addListener(listener : ThreadCompleteListener) - - completed() - + isSynchronous() : boolean - + removeListener(listener : ThreadCompleteListener) - + run() - + start() - + status() - + stop() - } - class EventManager { - + MAX_EVENT_TIME : int {static} - + MAX_ID : int {static} - + MAX_RUNNING_EVENTS : int {static} - + MIN_ID : int {static} - - currentlyRunningSyncEvent : int - - eventPool : Map - - rand : Random - + EventManager() - + cancel(eventId : int) - + completedEventHandler(eventId : int) - + create(eventTime : int) : int - + createAsync(eventTime : int) : int - - createEvent(eventTime : int, isSynchronous : boolean) : int - - generateId() : int - + getEventPool() : Map - + numOfCurrentlyRunningSyncEvent() : int - + shutdown() - + start(eventId : int) - + status(eventId : int) - + statusOfAllEvents() - } - interface IEvent { - + start() {abstract} - + status() {abstract} - + stop() {abstract} - } - interface ThreadCompleteListener { - + completedEventHandler(int) {abstract} - } -} -Event --> "-eventListener" ThreadCompleteListener -Event ..|> IEvent -EventManager ..|> ThreadCompleteListener -@enduml \ No newline at end of file diff --git a/event-asynchronous/pom.xml b/event-asynchronous/pom.xml deleted file mode 100644 index afb3213f1465..000000000000 --- a/event-asynchronous/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - event-asynchronous - - - junit - junit - test - - - 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 deleted file mode 100644 index 6e9138d3c518..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -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; - - /** - * Program entry point. - * - * @param args command line args - */ - public static void main(String[] args) { - App app = new App(); - - app.setUp(); - app.run(); - } - - /** - * App can run in interactive mode or not. Interactive mode == Allow user interaction with command line. - * Non-interactive is a quick sequential run through the available {@link EventManager} operations. - */ - public void setUp() { - Properties prop = new Properties(); - - InputStream inputStream = App.class.getClassLoader().getResourceAsStream(PROP_FILE_NAME); - - if (inputStream != null) { - try { - prop.load(inputStream); - } catch (IOException e) { - LOGGER.error("{} was not found. Defaulting to non-interactive mode.", PROP_FILE_NAME, e); - } - String property = prop.getProperty("INTERACTIVE_MODE"); - if (property.equalsIgnoreCase("YES")) { - interactiveMode = true; - } - } - } - - /** - * Run program in either interactive mode or not. - */ - public void run() { - if (interactiveMode) { - runInteractiveMode(); - } else { - quickRun(); - } - } - - /** - * Run program in non-interactive mode. - */ - public void quickRun() { - EventManager eventManager = new EventManager(); - - try { - // Create an Asynchronous event. - int aEventId = eventManager.createAsync(60); - LOGGER.info("Async Event [{}] has been created.", aEventId); - eventManager.start(aEventId); - LOGGER.info("Async Event [{}] has been started.", aEventId); - - // Create a Synchronous event. - int sEventId = eventManager.create(60); - LOGGER.info("Sync Event [{}] has been created.", sEventId); - eventManager.start(sEventId); - LOGGER.info("Sync Event [{}] has been started.", sEventId); - - eventManager.status(aEventId); - eventManager.status(sEventId); - - eventManager.cancel(aEventId); - LOGGER.info("Async Event [{}] has been stopped.", aEventId); - eventManager.cancel(sEventId); - LOGGER.info("Sync Event [{}] has been stopped.", sEventId); - - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException - | InvalidOperationException e) { - LOGGER.error(e.getMessage()); - } - } - - /** - * Run program in interactive mode. - */ - public void runInteractiveMode() { - EventManager eventManager = new EventManager(); - - Scanner s = new Scanner(System.in); - int option = -1; - while (option != 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(); - LOGGER.info("Boil multiple eggs at once (A) or boil them one-by-one (S)?: "); - String eventType = s.nextLine(); - 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); - LOGGER.info("Egg [{}] is being boiled.", eventId); - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } else if (eventType.equalsIgnoreCase("S")) { - try { - int eventId = eventManager.create(eventTime); - eventManager.start(eventId); - LOGGER.info("Egg [{}] is being boiled.", eventId); - } catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException - | EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } else { - LOGGER.info("Unknown event type."); - } - } else if (option == 2) { - LOGGER.info("Which egg?: "); - int eventId = s.nextInt(); - try { - eventManager.cancel(eventId); - LOGGER.info("Egg [{}] is removed from boiler.", eventId); - } catch (EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } else if (option == 3) { - s.nextLine(); - LOGGER.info("Just one egg (O) OR all of them (A) ?: "); - String eggChoice = s.nextLine(); - - if (eggChoice.equalsIgnoreCase("O")) { - LOGGER.info("Which egg?: "); - int eventId = s.nextInt(); - try { - eventManager.status(eventId); - } catch (EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } else if (eggChoice.equalsIgnoreCase("A")) { - eventManager.statusOfAllEvents(); - } - } else if (option == 4) { - eventManager.shutdown(); - } - } - - s.close(); - } - -} 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 deleted file mode 100644 index 5dc069bc7032..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -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; - private Thread thread; - private boolean isComplete = false; - private ThreadCompleteListener eventListener; - - /** - * - * @param eventId event ID - * @param eventTime event time - * @param isSynchronous is of synchronous type - */ - public Event(final int eventId, final int eventTime, final boolean isSynchronous) { - this.eventId = eventId; - this.eventTime = eventTime; - this.isSynchronous = isSynchronous; - } - - public boolean isSynchronous() { - return isSynchronous; - } - - @Override - public void start() { - thread = new Thread(this); - thread.start(); - } - - @Override - public void stop() { - if (null == thread) { - return; - } - thread.interrupt(); - } - - @Override - public void status() { - if (!isComplete) { - LOGGER.info("[{}] is not done.", eventId); - } else { - LOGGER.info("[{}] is done.", eventId); - } - } - - @Override - public void run() { - long currentTime = System.currentTimeMillis(); - long endTime = currentTime + (eventTime * 1000); - while (System.currentTimeMillis() < endTime) { - try { - Thread.sleep(1000); // Sleep for 1 second. - } catch (InterruptedException e) { - return; - } - } - isComplete = true; - completed(); - } - - public final void addListener(final ThreadCompleteListener listener) { - this.eventListener = listener; - } - - public final void removeListener(final ThreadCompleteListener listener) { - this.eventListener = null; - } - - private final void completed() { - if (eventListener != null) { - eventListener.completedEventHandler(eventId); - } - } - -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventDoesNotExistException.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventDoesNotExistException.java deleted file mode 100644 index e7a5e75b6d4b..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventDoesNotExistException.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Custom Exception Class for Non Existent Event - */ -public class EventDoesNotExistException extends Exception { - - private static final long serialVersionUID = -3398463738273811509L; - - public EventDoesNotExistException(String message) { - super(message); - } -} 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 deleted file mode 100644 index 729900620aa0..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java +++ /dev/null @@ -1,218 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; - -/** - * - * EventManager handles and maintains a pool of event threads. {@link Event} threads are created upon user request. Thre - * are two types of events; Asynchronous and Synchronous. There can be multiple Asynchronous events running at once but - * only one Synchronous event running at a time. Currently supported event operations are: start, stop, and getStatus. - * Once an event is complete, it then notifies EventManager through a listener. The EventManager then takes the event - * out of the pool. - * - */ -public class EventManager implements ThreadCompleteListener { - - public static final int MAX_RUNNING_EVENTS = 1000; // Just don't wanna have too many running events. :) - public static final int MIN_ID = 1; - public static final int MAX_ID = MAX_RUNNING_EVENTS; - public static final int MAX_EVENT_TIME = 1800; // in seconds / 30 minutes. - private int currentlyRunningSyncEvent = -1; - private Random rand; - private Map eventPool; - - /** - * EventManager constructor. - * - */ - public EventManager() { - rand = new Random(1); - eventPool = new ConcurrentHashMap(MAX_RUNNING_EVENTS); - - } - - /** - * 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. - * @throws InvalidOperationException No new synchronous events can be created when one is already running. - * @throws LongRunningEventException Long running events are not allowed in the app. - */ - public int create(int eventTime) - throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException { - if (currentlyRunningSyncEvent != -1) { - throw new InvalidOperationException( - "Event [" + currentlyRunningSyncEvent + "] is still running. Please wait until it finishes and try again."); - } - - int eventId = createEvent(eventTime, true); - currentlyRunningSyncEvent = eventId; - - return eventId; - } - - /** - * 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. - * @throws LongRunningEventException Long running events are not allowed in the app. - */ - public int createAsync(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException { - return createEvent(eventTime, false); - } - - private int createEvent(int eventTime, boolean isSynchronous) - throws MaxNumOfEventsAllowedException, LongRunningEventException { - if (eventPool.size() == MAX_RUNNING_EVENTS) { - throw new MaxNumOfEventsAllowedException("Too many events are running at the moment. Please try again later."); - } - - if (eventTime >= MAX_EVENT_TIME) { - throw new LongRunningEventException( - "Maximum event time allowed is " + MAX_EVENT_TIME + " seconds. Please try again."); - } - - int newEventId = generateId(); - - Event newEvent = new Event(newEventId, eventTime, isSynchronous); - newEvent.addListener(this); - eventPool.put(newEventId, newEvent); - - return newEventId; - } - - /** - * Starts event. - * - * @param eventId The event that needs to be started. - * @throws EventDoesNotExistException If event does not exist in our eventPool. - */ - public void start(int eventId) throws EventDoesNotExistException { - if (!eventPool.containsKey(eventId)) { - throw new EventDoesNotExistException(eventId + " does not exist."); - } - - eventPool.get(eventId).start(); - } - - /** - * Stops event. - * - * @param eventId The event that needs to be stopped. - * @throws EventDoesNotExistException If event does not exist in our eventPool. - */ - public void cancel(int eventId) throws EventDoesNotExistException { - if (!eventPool.containsKey(eventId)) { - throw new EventDoesNotExistException(eventId + " does not exist."); - } - - if (eventId == currentlyRunningSyncEvent) { - currentlyRunningSyncEvent = -1; - } - - eventPool.get(eventId).stop(); - eventPool.remove(eventId); - } - - /** - * Get status of a running event. - * - * @param eventId The event to inquire status of. - * @throws EventDoesNotExistException If event does not exist in our eventPool. - */ - public void status(int eventId) throws EventDoesNotExistException { - if (!eventPool.containsKey(eventId)) { - throw new EventDoesNotExistException(eventId + " does not exist."); - } - - eventPool.get(eventId).status(); - } - - /** - * Gets status of all running events. - */ - @SuppressWarnings("rawtypes") - public void statusOfAllEvents() { - Iterator it = eventPool.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = (Map.Entry) it.next(); - ((Event) pair.getValue()).status(); - } - } - - /** - * Stop all running events. - */ - @SuppressWarnings("rawtypes") - public void shutdown() { - Iterator it = eventPool.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = (Map.Entry) it.next(); - ((Event) pair.getValue()).stop(); - } - } - - /** - * Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most - * Integer.MAX_VALUE - 1. - */ - private int generateId() { - // nextInt is normally exclusive of the top value, - // so add 1 to make it inclusive - int randomNum = rand.nextInt((MAX_ID - MIN_ID) + 1) + MIN_ID; - while (eventPool.containsKey(randomNum)) { - randomNum = rand.nextInt((MAX_ID - MIN_ID) + 1) + MIN_ID; - } - - return randomNum; - } - - /** - * Callback from an {@link Event} (once it is complete). The Event is then removed from the pool. - */ - @Override - public void completedEventHandler(int eventId) { - eventPool.get(eventId).status(); - if (eventPool.get(eventId).isSynchronous()) { - currentlyRunningSyncEvent = -1; - } - eventPool.remove(eventId); - } - - /** - * Getter method for event pool. - */ - public Map getEventPool() { - return eventPool; - } - - /** - * Get number of currently running Synchronous events. - */ - public int numOfCurrentlyRunningSyncEvent() { - return currentlyRunningSyncEvent; - } -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java deleted file mode 100644 index bfb5d4f0433b..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Events that fulfill the start stop and list out current status behaviour - * follow this interface - */ -public interface IEvent { - - void start(); - - void stop(); - - void status(); - -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/InvalidOperationException.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/InvalidOperationException.java deleted file mode 100644 index 7ca5cfc9a6a4..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/InvalidOperationException.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Type of Exception raised when the Operation being invoked is Invalid - */ -public class InvalidOperationException extends Exception { - - private static final long serialVersionUID = -6191545255213410803L; - - public InvalidOperationException(String message) { - super(message); - } - -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/LongRunningEventException.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/LongRunningEventException.java deleted file mode 100644 index b11f1a33597f..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/LongRunningEventException.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Type of Exception raised when the Operation being invoked is Long Running - */ -public class LongRunningEventException extends Exception { - - private static final long serialVersionUID = -483423544320148809L; - - public LongRunningEventException(String message) { - super(message); - } -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/MaxNumOfEventsAllowedException.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/MaxNumOfEventsAllowedException.java deleted file mode 100644 index 17b46fd882e8..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/MaxNumOfEventsAllowedException.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Type of Exception raised when the max number of allowed events is exceeded - */ -public class MaxNumOfEventsAllowedException extends Exception { - - private static final long serialVersionUID = -8430876973516292695L; - - public MaxNumOfEventsAllowedException(String message) { - super(message); - } -} diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java deleted file mode 100644 index 7a37f7614849..000000000000 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -/** - * Interface with listener behaviour related to Thread Completion. - */ -public interface ThreadCompleteListener { - void completedEventHandler(final int eventId); -} diff --git a/event-asynchronous/src/main/resources/config.properties b/event-asynchronous/src/main/resources/config.properties deleted file mode 100644 index f76c07bb4dfc..000000000000 --- a/event-asynchronous/src/main/resources/config.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -INTERACTIVE_MODE=NO \ No newline at end of file diff --git a/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/AppTest.java b/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/AppTest.java deleted file mode 100644 index 2056dcf185d8..000000000000 --- a/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/AppTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -import java.io.IOException; - -import org.junit.Test; - -/** - * Tests that EventAsynchronous example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index 8e0860286d8b..000000000000 --- a/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/** - * The MIT License Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.iluwatar.event.asynchronous; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.junit.Assert.assertTrue; - -/** - * - * Application test - * - */ -public class EventAsynchronousTest { - App app; - - private static final Logger LOGGER = LoggerFactory.getLogger(EventAsynchronousTest.class); - - @Before - public void setUp() { - app = new App(); - } - - @Test - public void testAsynchronousEvent() { - EventManager eventManager = new EventManager(); - try { - int aEventId = eventManager.createAsync(60); - eventManager.start(aEventId); - assertTrue(eventManager.getEventPool().size() == 1); - assertTrue(eventManager.getEventPool().size() < EventManager.MAX_RUNNING_EVENTS); - assertTrue(eventManager.numOfCurrentlyRunningSyncEvent() == -1); - eventManager.cancel(aEventId); - assertTrue(eventManager.getEventPool().size() == 0); - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } - - @Test - public void testSynchronousEvent() { - EventManager eventManager = new EventManager(); - try { - int sEventId = eventManager.create(60); - eventManager.start(sEventId); - assertTrue(eventManager.getEventPool().size() == 1); - assertTrue(eventManager.getEventPool().size() < EventManager.MAX_RUNNING_EVENTS); - assertTrue(eventManager.numOfCurrentlyRunningSyncEvent() != -1); - eventManager.cancel(sEventId); - assertTrue(eventManager.getEventPool().size() == 0); - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException - | InvalidOperationException e) { - LOGGER.error(e.getMessage()); - } - } - - @Test(expected = InvalidOperationException.class) - public void testUnsuccessfulSynchronousEvent() throws InvalidOperationException { - EventManager eventManager = new EventManager(); - try { - int sEventId = eventManager.create(60); - eventManager.start(sEventId); - sEventId = eventManager.create(60); - eventManager.start(sEventId); - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } - - @Test - public void testFullSynchronousEvent() { - EventManager eventManager = new EventManager(); - try { - int eventTime = 1; - - int sEventId = eventManager.create(eventTime); - assertTrue(eventManager.getEventPool().size() == 1); - eventManager.start(sEventId); - - long currentTime = System.currentTimeMillis(); - long endTime = currentTime + (eventTime + 2 * 1000); // +2 to give a bit of buffer time for event to - // complete - // properly. - while (System.currentTimeMillis() < endTime) { - } - - assertTrue(eventManager.getEventPool().size() == 0); - - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException - | InvalidOperationException e) { - LOGGER.error(e.getMessage()); - } - } - - @Test - public void testFullAsynchronousEvent() { - EventManager eventManager = new EventManager(); - try { - int eventTime = 1; - - int aEventId1 = eventManager.createAsync(eventTime); - int aEventId2 = eventManager.createAsync(eventTime); - int aEventId3 = eventManager.createAsync(eventTime); - assertTrue(eventManager.getEventPool().size() == 3); - - eventManager.start(aEventId1); - eventManager.start(aEventId2); - eventManager.start(aEventId3); - - long currentTime = System.currentTimeMillis(); - long endTime = currentTime + (eventTime + 2 * 1000); // +2 to give a bit of buffer time for event to complete - // properly. - while (System.currentTimeMillis() < endTime) { - } - - assertTrue(eventManager.getEventPool().size() == 0); - - } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - LOGGER.error(e.getMessage()); - } - } -} diff --git a/event-driven-architecture/README.md b/event-driven-architecture/README.md deleted file mode 100644 index a263defecd34..000000000000 --- a/event-driven-architecture/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: pattern -title: Event Driven Architecture -folder: event-driven-architecture -permalink: /patterns/event-driven-architecture/ -pumlid: TOhH3SCW30LNQGS0_tSRnrZ15H1adfFromBzkfFktZQaHT7mzgh0N1yYvoUVXXf7B7Mv1dGWozN9MZmCTlhopQdeidEaoO3wMDHvRI6zzvwAssPYbsfGGRYIGlxN7DxpZDv- -categories: Architectural -tags: - - Java - - Difficulty-Intermediate - - Reactive ---- - -## Intent -Send and notify state changes of your objects to other applications using an Event-driven Architecture. - -![alt text](./etc/eda.png "Event Driven Architecture") - -## Applicability -Use an Event-driven architecture when - -* you want to create a loosely coupled system -* you want to build a more responsive system -* you want a system that is easier to extend - -## Real world examples - -* SendGrid, an email API, sends events whenever an email is processed, delivered, opened etc... (https://sendgrid.com/docs/API_Reference/Webhooks/event.html) -* Chargify, a billing API, exposes payment activity through various events (https://docs.chargify.com/api-events) -* Amazon's AWS Lambda, lets you execute code in response to events such as changes to Amazon S3 buckets, updates to an Amazon DynamoDB table, or custom events generated by your applications or devices. (https://aws.amazon.com/lambda) -* MySQL runs triggers based on events such as inserts and update events happening on database tables. - -## Credits - -* [Event-driven architecture - Wikipedia](https://en.wikipedia.org/wiki/Event-driven_architecture) -* [Fundamental Components of an Event-Driven Architecture](http://giocc.com/fundamental-components-of-an-event-driven-architecture.html) -* [Real World Applications/Event Driven Applications](https://wiki.haskell.org/Real_World_Applications/Event_Driven_Applications) -* [Event-driven architecture definition](http://searchsoa.techtarget.com/definition/event-driven-architecture) diff --git a/event-driven-architecture/etc/eda.png b/event-driven-architecture/etc/eda.png deleted file mode 100644 index 7437264518029acca6c2db4781b69d3b36c1a91a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58476 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

*&nI)sQ1C8^KMhLOi}&PndASpm%;RT(W=9PU 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/event-driven-architecture/etc/event-driven-architecture.urm.puml b/event-driven-architecture/etc/event-driven-architecture.urm.puml deleted file mode 100644 index 2eb79e438a5d..000000000000 --- a/event-driven-architecture/etc/event-driven-architecture.urm.puml +++ /dev/null @@ -1,64 +0,0 @@ -@startuml -package com.iluwatar.eda.handler { - class UserCreatedEventHandler { - - LOGGER : Logger {static} - + UserCreatedEventHandler() - + onEvent(event : UserCreatedEvent) - } - class UserUpdatedEventHandler { - - LOGGER : Logger {static} - + UserUpdatedEventHandler() - + onEvent(event : UserUpdatedEvent) - } -} -package com.iluwatar.eda.event { - abstract class AbstractEvent { - + AbstractEvent() - + getType() : Class - } - class UserCreatedEvent { - - user : User - + UserCreatedEvent(user : User) - + getUser() : User - } - class UserUpdatedEvent { - - user : User - + UserUpdatedEvent(user : User) - + getUser() : User - } -} -package com.iluwatar.eda.framework { - interface Event { - + getType() : Class {abstract} - } - class EventDispatcher { - - handlers : Map, Handler> - + EventDispatcher() - + dispatch(event : E extends Event) - + registerHandler(eventType : Class, handler : Handler) - } - interface Handler { - + onEvent(E extends Event) {abstract} - } -} -package com.iluwatar.eda.model { - class User { - - username : String - + User(username : String) - + getUsername() : String - } -} -package com.iluwatar.eda { - class App { - + App() - + main(args : String[]) {static} - } -} -UserUpdatedEvent --> "-user" User -UserCreatedEvent --> "-user" User -AbstractEvent ..|> Event -UserCreatedEvent --|> AbstractEvent -UserUpdatedEvent --|> AbstractEvent -UserCreatedEventHandler ..|> Handler -UserUpdatedEventHandler ..|> Handler -@enduml \ No newline at end of file diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml deleted file mode 100644 index 4db6b6c0c696..000000000000 --- a/event-driven-architecture/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - - event-driven-architecture - - - - junit - junit - test - - - - org.mockito - mockito-core - test - - - \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java deleted file mode 100644 index 5ed2b2ad8542..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda; - -import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.event.UserUpdatedEvent; -import com.iluwatar.eda.framework.Event; -import com.iluwatar.eda.framework.EventDispatcher; -import com.iluwatar.eda.handler.UserCreatedEventHandler; -import com.iluwatar.eda.handler.UserUpdatedEventHandler; -import com.iluwatar.eda.model.User; - -/** - * An event-driven architecture (EDA) is a framework that orchestrates behavior around the - * production, detection and consumption of events as well as the responses they evoke. An event is - * any identifiable occurrence that has significance for system hardware or software.

The - * example below uses an {@link EventDispatcher} to link/register {@link Event} objects to their - * respective handlers once an {@link Event} is dispatched, it's respective handler is invoked and - * the {@link Event} is handled accordingly. - * - */ -public class App { - - /** - * Once the {@link EventDispatcher} is initialised, handlers related to specific events have to be - * made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is - * bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the - * {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events. - * When a user is saved, the {@link UserCreatedEvent} can be dispatched. - * On the other hand, when a user is updated, {@link UserUpdatedEvent} can be dispatched. - * - */ - public static void main(String[] args) { - - EventDispatcher dispatcher = new EventDispatcher(); - dispatcher.registerHandler(UserCreatedEvent.class, new UserCreatedEventHandler()); - dispatcher.registerHandler(UserUpdatedEvent.class, new UserUpdatedEventHandler()); - - User user = new User("iluwatar"); - dispatcher.dispatch(new UserCreatedEvent(user)); - dispatcher.dispatch(new UserUpdatedEvent(user)); - } - -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java deleted file mode 100644 index be6d70ec1f87..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.event; - -import com.iluwatar.eda.framework.EventDispatcher; -import com.iluwatar.eda.framework.Event; - -/** - * The {@link AbstractEvent} class serves as a base class for defining custom events happening with your - * system. In this example we have two types of events defined. - *

    - *
  • {@link UserCreatedEvent} - used when a user is created
  • - *
  • {@link UserUpdatedEvent} - used when a user is updated
  • - *
- * Events can be distinguished using the {@link #getType() getType} method. - */ -public abstract class AbstractEvent implements Event { - - /** - * Returns the event type as a {@link Class} object - * In this example, this method is used by the {@link EventDispatcher} to - * dispatch events depending on their type. - * - * @return the AbstractEvent type as a {@link Class}. - */ - public Class getType() { - return getClass(); - } -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java deleted file mode 100644 index af209f4a9c6e..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.event; - -import com.iluwatar.eda.model.User; - -/** - * The {@link UserCreatedEvent} should should be dispatched whenever a user has been created. - * This class can be extended to contain details about the user has been created. In this example, - * the entire {@link User} object is passed on as data with the event. - */ -public class UserCreatedEvent extends AbstractEvent { - - private User user; - - public UserCreatedEvent(User user) { - this.user = user; - } - - public User getUser() { - return user; - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java deleted file mode 100644 index e1046cdcbb72..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.event; - -import com.iluwatar.eda.model.User; - -/** - * The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated. - * This class can be extended to contain details about the user has been updated. In this example, - * the entire {@link User} object is passed on as data with the event. - */ -public class UserUpdatedEvent extends AbstractEvent { - - private User user; - - public UserUpdatedEvent(User user) { - this.user = user; - } - - public User getUser() { - return user; - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java deleted file mode 100644 index fdcd00584e2d..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.framework; - -/** - * A {@link Event} is an object with a specific type that is associated - * to a specific {@link Handler}. - */ -public interface Event { - - /** - * Returns the message type as a {@link Class} object. In this example the message type is - * used to handle events by their type. - * @return the message type as a {@link Class}. - */ - Class getType(); -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java deleted file mode 100644 index 427d7bd36bb9..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.framework; - -import java.util.HashMap; -import java.util.Map; - -/** - * Handles the routing of {@link Event} messages to associated handlers. - * A {@link HashMap} is used to store the association between events and their respective handlers. - */ -public class EventDispatcher { - - private Map, Handler> handlers; - - public EventDispatcher() { - handlers = new HashMap<>(); - } - - /** - * Links an {@link Event} to a specific {@link Handler}. - * - * @param eventType The {@link Event} to be registered - * @param handler The {@link Handler} that will be handling the {@link Event} - */ - public void registerHandler(Class eventType, - Handler handler) { - handlers.put(eventType, handler); - } - - /** - * Dispatches an {@link Event} depending on it's type. - * - * @param event The {@link Event} to be dispatched - */ - @SuppressWarnings("unchecked") - public void dispatch(E event) { - Handler handler = (Handler) handlers.get(event.getClass()); - if (handler != null) { - handler.onEvent(event); - } - } - -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java deleted file mode 100644 index 3208e1edf1eb..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.framework; - -/** - * This interface can be implemented to handle different types of messages. - * Every handler is responsible for a single of type message - * @param Handler can handle events of type E - */ -public interface Handler { - - /** - * The onEvent method should implement and handle behavior related to the event. - * This can be as simple as calling another service to handle the event on publishing the event on - * a queue to be consumed by other sub systems. - * @param event the {@link Event} object to be handled. - */ - void onEvent(E event); -} 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 deleted file mode 100644 index 3d8e2779fc42..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.handler; - -import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.framework.Handler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles the {@link UserCreatedEvent} message. - */ -public class UserCreatedEventHandler implements Handler { - - private static final Logger LOGGER = LoggerFactory.getLogger(UserCreatedEventHandler.class); - - @Override - public void onEvent(UserCreatedEvent event) { - 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 deleted file mode 100644 index eef5f67854e3..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.handler; - -import com.iluwatar.eda.event.UserUpdatedEvent; -import com.iluwatar.eda.framework.Handler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles the {@link UserUpdatedEvent} message. - */ -public class UserUpdatedEventHandler implements Handler { - - private static final Logger LOGGER = LoggerFactory.getLogger(UserUpdatedEventHandler.class); - - @Override - public void onEvent(UserUpdatedEvent event) { - LOGGER.info("User '{}' has been Updated!", event.getUser().getUsername()); - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java deleted file mode 100644 index 92ea232bcb53..000000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.model; - -import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.event.UserUpdatedEvent; - -/** - * This {@link User} class is a basic pojo used to demonstrate user data sent along with - * the {@link UserCreatedEvent} and {@link UserUpdatedEvent} events. - */ -public class User { - - private String username; - - public User(String username) { - this.username = username; - } - - public String getUsername() { - return username; - } -} diff --git a/event-driven-architecture/src/test/java/com/iluwatar/eda/AppTest.java b/event-driven-architecture/src/test/java/com/iluwatar/eda/AppTest.java deleted file mode 100644 index e7d642b9527b..000000000000 --- a/event-driven-architecture/src/test/java/com/iluwatar/eda/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Event Driven Architecture example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java b/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java deleted file mode 100644 index 6e95f5fd2f94..000000000000 --- a/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.event; - -import com.iluwatar.eda.model.User; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * {@link UserCreatedEventTest} tests and verifies {@link AbstractEvent} behaviour. - */ -public class UserCreatedEventTest { - - /** - * This unit test should correctly return the {@link AbstractEvent} class type when calling the - * {@link AbstractEvent#getType() getType} method. - */ - @Test - public void testGetEventType() { - User user = new User("iluwatar"); - UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); - assertEquals(UserCreatedEvent.class, userCreatedEvent.getType()); - } -} diff --git a/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java b/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java deleted file mode 100644 index 7501653f68d4..000000000000 --- a/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.eda.framework; - -import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.event.UserUpdatedEvent; -import com.iluwatar.eda.handler.UserCreatedEventHandler; -import com.iluwatar.eda.handler.UserUpdatedEventHandler; -import com.iluwatar.eda.model.User; - -import org.junit.Test; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Event Dispatcher unit tests to assert and verify correct event dispatcher behaviour - */ -public class EventDispatcherTest { - - /** - * This unit test should register events and event handlers correctly with the event dispatcher - * and events should be dispatched accordingly. - */ - @Test - public void testEventDriverPattern() { - - EventDispatcher dispatcher = spy(new EventDispatcher()); - UserCreatedEventHandler userCreatedEventHandler = spy(new UserCreatedEventHandler()); - UserUpdatedEventHandler userUpdatedEventHandler = spy(new UserUpdatedEventHandler()); - dispatcher.registerHandler(UserCreatedEvent.class, userCreatedEventHandler); - dispatcher.registerHandler(UserUpdatedEvent.class, userUpdatedEventHandler); - - User user = new User("iluwatar"); - - UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); - UserUpdatedEvent userUpdatedEvent = new UserUpdatedEvent(user); - - //fire a userCreatedEvent and verify that userCreatedEventHandler has been invoked. - dispatcher.dispatch(userCreatedEvent); - verify(userCreatedEventHandler).onEvent(userCreatedEvent); - verify(dispatcher).dispatch(userCreatedEvent); - - //fire a userCreatedEvent and verify that userUpdatedEventHandler has been invoked. - dispatcher.dispatch(userUpdatedEvent); - verify(userUpdatedEventHandler).onEvent(userUpdatedEvent); - verify(dispatcher).dispatch(userUpdatedEvent); - } - -} diff --git a/event-queue/README.md b/event-queue/README.md deleted file mode 100644 index 081c0144970c..000000000000 --- a/event-queue/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Event Queue -folder: event-queue -permalink: /patterns/event-queue/ -categories: Concurrency -tags: - - Java - - Difficulty Intermediate - - Queue ---- - -## Intent -Event Queue is a good pattern if You have a limited accessibility resource (for example: -Audio or Database), but You need to handle all the requests that want to use that. -It puts all the requests in a queue and process them asynchronously. -Gives the resource for the event when it is the next in the queue and in same time -removes it from the queue. - -![alt text](./etc/model.png "Event Queue") - -## Applicability -Use the Event Queue pattern when - -* You have a limited accessibility resource and the asynchronous process is acceptable to reach that - -## Credits - -* [Mihaly Kuprivecz - Event Queue] (http://gameprogrammingpatterns.com/event-queue.html) diff --git a/event-queue/etc/Bass-Drum-1.aif b/event-queue/etc/Bass-Drum-1.aif deleted file mode 100644 index f1eae69db029ffa97252279b94c94930d5f74ad9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220938 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 z 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ð@(2S0xu$k+!mOA5hDZa8FtIs<_@PNrEXZuQJwVHSZqsy|q#5 z4KF<=&nLk^?;iE8ALyfufqMN(yw_l!E`#;sQ0*P157-|(O~RRd35$Fp?>VjNrms4Jc4l@5qx?u5 z$DZ>33cPt;AKu|ZlVJ5E0ZBb4i#0(t>gt6`ECPk4O-=f`8ru{-5!*~&*vp6eK=d%F z?=oMd`>~U_?*lmOeNj9}^rm<>V{4)pV%vnCi#9AY=&FCE90ddeM2XHpGQU25@j~DL^&qI{|syM^c zVWg2558fipj*|XGah~$r-}ipXcr<#?TFz)4=OtkkrQs@y=g8+>HuO5Vxf{U`B*zyd z$2(+(tuwP;=*d*H5hpVa<`Y%qLzyht-~x=8=1HP9FS=mgwGN6H-t^9e%> zMrMaHkEq+fu;x{831+HGfMhpI4h6tOA|k^Z{~unUwh%-2Dq2vJDkE z?)j2Z&U=4Ji5KDQi%PnsMz_HoIQSAuu^moch>x1&_h>q&XVw12*jD-NK@*Ou^9ebf z(U#LN&q=uF1ey6DOmxJ%3%IiDuwimoFFi_~7sbqoQf7!#$f2m!%P8mwJkvX{@&5OumYz zI;}5{;6eAuWvBk#gB#g{avb4neE`3C1b?=J?6I5N9{lOI=)2YIsB3*Em!TRJ$?m1~ zX&LD&fr{c(BNf&n3$-Ed4=`>o^RxSq@7#1_@e`ToNAJGW_Y=fWPP3TB+ ze}w)036kwge2_-5wvUe_But8=uy;BI`%n_4Md>ik(J!2pdJkE5zm$i?K1W8s%+tWl zDoz!u#G{~su!#NR*&?az|IXp5gp+s5`%=!A(oQeR<4ej&8fntl37)~e@f`M`mv zQ_uaJnKYCSz}rrM`WU?Le57~mSAW?~_<_6(+SyV5kbUa)+}7GqZcXLhM!J^rYAfv{ z@_NLnJAD#1u;46+JnxL(A*^4ovG@#S@flaj*uUcH-9Zwnue@yO<8n$(Oo>2kR4=-JjxTcT`ZC3?A=Hy7Mk4dMNQ8_lY~{} zF6qJ15W)JQCo}1zJbE>YeMp(qHWTRKeY&PUFGxE^)U3;okNb`i}SK*-dNmO6xtFOpaU&B_PliEIqTizqNeW))clDj^ni+SJb zn8*wF9V_N-m|++!_nH;>8tm{oY%q-WV+_s4+h8~ zJ$d!^<V=-SMcHfP z9}3{464?j-<<)VLo$5TUASsR@E9zTZNu}s1iusilH^eTF%SwjhOe4&U>rIa? zjvc|*?Xu%x6@QP7Yy~Uuh3mat>)l#>uS&S6H*Sw zFAigCdxt0R7~v>9fk%CE4(bC?f|y-;Cbp#MR|chkSU*+Rpq>yUtR)8+$bIQtai#Q_fL5>~xhwv1b$a#~w*M>Hgl!v2xNEjwWLr zOo(MoyzRWk%h6ckx#)G_DV`^LqN(x9IkYvewq(*LNuusbj9yN>9z7}CVlV$9{=u_- zpT?ge?5zLPzTp`>E++GC`I299*xx>h|L}X!ih8CdyJG`A)=+P@p*vjvoe2)j% z!TxIW^XTi~O9GwZi@$OsSzGplA3QQpZyl)&v^VuHETkmPI!&7+eH^>;{dGdY2{xbs){|z30 z4$JC~cEqB1O29rmh5Vy|z{Ks{3X!}e-4g5_G{iJHTPPRD|6lf%ME@R5o5qFbc# zL|8i=Y@Qn?cjlMB2k;6N@o^8r(KYF>nt~>%NK@bI!^V~H2Zix}+2HN8aC}xe>U?mt z-IG$kD~){zaV}&LUH)2hZxc>w9sX}4&huB?%+;-u3j{AOAcup%$;EwjwO0R*FmuvZQ`hgAb_W`*25=ey8Z_uyd(CzwM zLsNKwkIr!%+7;Z@JseH~+L^?+>vqzd!D(&9@vTN5=E3g^;P)TtCYIm^SHR_4(SY4J zv=cO!7ilyv_0b`%@d_xZ>pv$S*0y5|) z&r+r%J+L_7b&rE5%+(ka{-LEU%$8 zTS`{@ovikQH{YN!vq?0wX|3i+^P5?^$jtr6*G=fm5x>rQ$C{#@o3-K}E#0Ano!%W4 z2LAnmd3(kC+iG-ExmW$2(lZDB+Nf8S34il$u5aH7=Lmn)6Mw4bANcz}$OC_(g!9em zpUvZ0c=RvX>86>_Q)rSVqN4Ainj@{3G1kLalEuf?#20w`1>*lD?rL&DuwQIIk;8qJ zdyVQzewC-$`p#PuH~Cdwq=C9g7Q1W>{Yxe|qs(xd{6RYHW9o1cCBCSPYt}?cYa^32 zP{P_M$BI!cF7M>=lmSna%)AH|kL&3COhNvCu+iW*OXnYJsVp$?*_01J>&b6c(o_3r2)boc%Mhu^xERhda(rd!zVps-Mw!8 zjlr2slILVR&=>ws7tUfCnoU~!PT8}h{0=8JLy14&zNV?g_ez{)rT&h0TcrN$$pO2y z;glMj$8%kl{}pw;D*Yv#;w9YJHS*k5EB=o8dCjc8?)ifLIB8ZN(-SAHfeU!M+gcpu zw-jO33-?GSk^gmNod&yMk5#zR`PReNR^*q)VyeELZmv%yi+-oqegZ7Nb`7LtHB3WC zA7zzHVn6l`tMwK;)5SPl{-1GBfr%|NYx8b`_!DmKqrn*mqIcMO7C*hUf z(T^ka;j88We$6Ok(^I+iRDNSrUd%>fboTdznJ^gNJk(gdZuExw8^W?X7>7I9JQ!^J zM~OWiR{aQm{#ZB-E}mwNeQdscrdNaQa3-AkxjFQ;d}o+hKd=gZLk^tJ_WT3h`FkVu zgWCQ8H!qD#eWmzMS2t?)oTSw}l94A`8Yg09XMasic1b4h8|rx}KH`In&Iltv4!Gx5 z{m#nspjmNHPwbW7F|$5+047Oj8p+^B(0n}Pa@ti=fEQd!zZ1-^v+8|7n$2d_CX`~6 z6>>n`kK)}=8<~^V$uYfr02bV5xIMdfGmbL~fnpx%G>S9)KRwJH_w&(^u@CCT) z1PpbU-sX_M12EPBx}8HX*glwSJ1x})TAe>(y`{eW<=bNK7SRa(3_Hz5xo4x?Q)!3Z zV?jkiETXG(4Y3RK&(TQcCL(7FD$c`7uM`u=8S%v*B zCHJCo%&&}GIF0~0#VJ9^i_`yC)UFz|d9CQj zdeWoy*RE%1zj`U7yZ9~SQb)bQ-64&5*>qCgW8{kAT0H@W6Fgu(lHy&@BeZQaj%Oq* z;=A(xRQo2;U*@kJuNE*J0DAmVKd7DN?oCM3f0n>RM)ZP+Mid{&YtzlD)LN2y@`xaMyidGoB5o*phQYNb`R!pg$61>}&*{J)M$ zoo0ivTiaS_WSw+I;kw|TdZI;LVZmnf1`VVrFJ(!zCI|UFC7hQ+%kL^Bk*@3#nt4s? zvuNv8E9er*G*QlX@tpVYrnf!cW9_-6lshbpm-XC5I>)_A+Ji1H_d7tKy^HzPEXRYc zW)a$m*W7?+Zvxv<$vwEIv*O=ot-Ot2y(_;<_}9xUO6Sqx6X3Aldxcw#<|gmgmbNV_h^CPLPpLHaNC#7%bVs@#13rUZMcyt=2|H_-n{sotnfnE7m~ma??&t|dhc~? z1sm81wz3ZGrvLtj#bSMQPi!R#<8N~H7M7Py=oaS)tfeRa)h>%)?6R1{ ze(+;#X!HmEd*lT05-Z6QB%T4$v8+2Ev3N{l@o@K+H1(q2v3$(6cWNdHW*W)pOH$7? za{2cpsh>&Pi&G^O|%Sc}5# zE7?E>`J@F2(Itr&qJJhHh^|Up>#Wwf(e;T_JdgAI1{fDz?IgaXiC;ulCjRXCx9D2& zb|o%#rt9M9zQpgMyAwZ&?oFH!-6a09#8;I0iqraDj=r5Z%z3bb-TE>zelO6t#CM$d z_djRLzN>C;J4bfBvc|f1h{s>z2hl@`@5yh9=c&s5()SOX2Kb&^WyUy9_HF0VPIPC+ zr%w3$(y4wwI|Xolw69$vk0-8os^3<34jmD1zp{>cKI6pJ>vrBo>^9CyA}>HPFX^v3 zslB#cCv`~T4M^6FNXT9EY9GBjf}}i}reg}t$294Fw1eUgJ1n+}dB$@zT9pJ{i58&< zNwg4)RtZpwuW@~na0^zhNA0v37;6@N-pOQ7@rrz!-|sV?pN(~n4rY%U%x3hO6C_@Z zJ-Igr)&EWK2F#0oO){n&fhBbW^NjUhH9Fs1beQ*}0KZSOj zk@7J4_Z*sY9OXFA0(A=Y2zJ$QpLz;+=H}+HP~K@IjpI8V%fP<1V7_J~tuAqm*_(E8 zyv&nfoOi>W95ca?Tpu2h@8pfSqU4pn1!BM<$AgIXm0AIe&$4u7F|OHilfd|sCO zyz2cv~`R3zBSGbf+m=@(?bs29C81p12IpuA;c$Qs`7^ zTyF(X$M4_~8P1Xldl*a58RSR9@(Od|fD8Iw2=`nLJ*H{X zi$qWnM_+}MQr>Rn$}Acc=?!Z0+>`}|Z|XiD&pp@gZ&Ae`#Q#w(=Be3SHTeqf|1lq+k-YSt#DVrDPxT{>^~ZI;;Olej zBtvoGuamMysofB=$CEV9y~zXJJohD!^z!>z=?C*Cdeyt(q_H8=JQvR^$YI~8(f3Ms zx`X^)l+!S|gdIUIY0Fb_4SE}t`BDA%lsM!uV|sp zjmZeL)T)vk^C&TuS$4^aIfD;5#AELiN$Vjb-QC^D_i=B#;bUJOR*rrI)*vd#@r`Z;d{p9zYNV(X2;lfDX*s@3} zRQ^243SaGH+x_5(6?4Ry_h;mFPMQmmhny7BHg+)L>^b4ONR!y#5qqt`!AP^%#YlU0 zj~)q`BagC!^kO6F#3u5v-w!4@E!eK3igvSv6GrNiDx25=)RsKbo;{|E-8dcW=ILnH zO)EQ)8rsQTjisufolI%VEVLPWWca2nY z&qYvcD1ybJ;k&#jjcVom@cX_0sQwk=H-pq;EvxB$y~q>ZzM?KKYt1WefO)}b z(a*Xi<4NZ>Kjru1?(^s$$?L|CylxlC=U$k6^2p~)G5u81|H^)s@xHqIF3QAjC+Y4> zH|ILHixl)Ozi(OfaxSqmh@Z)qH2OVBBqM8G6286HX%8-uSC9IC%6Oe1qh9j$awHck zVLmruWVO3EB@5UsnBW50{sax;aoFLk)qTaxzDHkh-z-iP=NixE^Dw|}-#3^8;p~RR zR>-eb%0iOmFV^oYSmraUJ)HA0&T1TLwZCR153)+%gcHVD%@eJ||9Kv31rD+1x?8y| zSVybEfn}}NV9UzyO&&6QHaIUOoR*ZGDj6O>{N;r)i_=6@Bkxwlzn6zai_vPN=W%e? z-&wk{z5f5Vdu0!bx`&o+GuT3>7JO6J0DJcRZ6l}d^!*_Ex(6-YLthlVmcXC8>P7Lr)#N z_|}mOe*-_zJ4YZ>iI$u(qg1;L7YOtNOxQbl) zJ1*jTT*MqQ@lT|_g~H#YTg<<8F)xoLe6Hq^On;Jop64HVnasj7xD`!ns^HP<;Y4bY zF>B#Ls*pR2kzezZq;tzHyD$&gvKYO4S#o4ua&1FCCT+xRPUdb*R<0qeB2HQIrkkYr zSOxjH2hOLf=kWVsd9?!darw3FczBT1T$}t{3;$9}`fBniue9>y;}ZIyq>{=2UYKg! z$#Xb4^kM!sb=b@vh(_(Bxy|};ozIaQvZME%;EY(#p@HSMrj!v*OY0aP@t>UjI;y zKjhCdNl71R`Mc`)meOAmKJ8myrFSt3kC3IG#Nmzbb)uLv=>ZnTrqd69WyI!@-IvSH zIf(eX!FafrNK>PX`FP>~=uJzG1VVyP=UUiMJ@jHc^4)v<9A|9*b&|xbAie zAC?dJoxF*M8HN8CiO(2GKRXIv!rshRrURa(E54=!J4SEm`_Xd`CV{`h^71RFnqCsnE z#kWO08{$fu;)H5~y8c%b$Nn*xp(X8Pck8~lTJthqbZ%xNQWiss4r$7I)OtOn!79ZnlPn5_R2S@&si-S=X?uQMx`nt}7J zg#~!`rN-9jOGdAQ-z{kX9B+Dhqeh4hr7x7prRjIeIn#n)g_zx*|&aTKUq}~IuI#xwptEoN- zygtdLDQG0$hE`j3tE*!4GXKXTY=QgPB6qV7^1x)9{+BF#h6VWyOQoHAWS?AO7ACuw zBDaW+&FpHoiTq{trp}AFO5p{);7diPH_{J0W2f%lJ&Pq!a5&_kF#8l!xX( zd3RA}BYjZL30AqK$?R0Zj3oQ~&SNOb-doXWP?cGYA5hbB_UjiXrxs#|FByF;T1xn! zZ;e=;+llAAKlPnPy8V)*`?>Ek#h(!^#!mbIa2BAtPGa33@4SXl&ITAx-hER&{>MW6 zHBG}3Z&oVdZ`R}0V*bgly9%#10XKQv!Qn7hOMe$||N!?(A+n z(*J6OggqaB%VjxQun?V`V-0|RcB`x+Pj5kg1Bb9*ncJ0r6fNDQ++(o7Vf6nD zj1W#WiPC{b@ct>;K$A-qr4zd@uT%Jd6KM4=wAxvWenoNZ;ij(J@(VUXyPMQ$9SpRY z=FAPZIQg`+Z0TUGZ0s)C;n!?(&rai*hpbo{UakxmKS+kG0%upJw<{0I$iJerm8GQ( zfcY-L?RW4{5tua@T40Yk{QRtVuSjQaD{bo!;4AX)kHT+hRloNPt%gN<->PC0&#@ z_!c|VO?y$U^U;gp3sbPfq=);npbbUwh859@2k?j0Kxy(=SrS+UvSJNVVIA-=>8vdZ z(bK!&4>*m{YWVV-4im_zdkCfsJO|o1L zt;j%%OvRR--uEo1PHy=YB>xqccNwKsBx6=XnQF581zEYOG~vv$O3p7UM`kXD5*8rS z=D_`CCi7;~;!IkeN4)&XDx;Ow}d4pjL(bkIm%T3jORZx4udlDE9yZw4%2+eWYoR zZ*GTfK1?(Hu<}}w>D#DF2VvMH_K0@&rBCRuO#`+433YzjyQlShUnM+=AMYvF06F#W zu5&z1F*V99pN!t7Q_svGgV6}5H5OKiz1{k%x&CV=eoy)JH>!`5i=Sc1>?LhKx`|HW zw)d`;S(v#YV0+sG_wj<2t8Hq|!k%6ng&++0ps6>u33h+AD)*|&1)k=Oeq zanIL+=3}r*6*u2Y<4sDLdxco5^5Y6JdzYSmJgIq|)H+YJ4)0ipcdgn>*5PIR{~7Nu zTj~G8CO6=RTl9E|u*)4>LKGIdhet}vk2FCUscFXT?TxSRJJLJr7SFaD-@Y5}2!75h zaRv+U++UFj+@kESRkL--b_`e z$z+SkQcl9Pgi{{ARQGR{@jbiRw=l>zFv~2pnx%!aNEy~2i6siNor6Pn;dhqe^}}AD znK0jXY-@91!JlEpdGPTPoXQdww-s>m7MOFt{LX`$JR*|87)j(2Q}R_Q&cv;D;l!pT z{uYAY{a>g~%lu#C{|>F&t-K?iPr%rhc2;pBolFiIv^tvu{g7nW?n-s7BFnC~=8ie0QmBnPcpN;aAd ztROi(mk?HjDeJ&w_1G{TVi{>JO$)Q4ov;&|Q+wFCgE*b&Si15sW-*J~K)bMW^q_MI z-p>Q24ZAd7f`NyyTaAD%!~KV0_p+YD1+Rh$11G(WZfFm?)dAo3(zfn_S+~T!r$;Jd zggi#Fs}2$GS1o~CYC{;BYb&O_RYwIB++}L;C zzU)~sSSDbI6zZ4~Exc!BZ=i=4h1dMPfG&pFaE@GbLSCoYw$AWBxdg8BL%**DX<*Wf z(&yE#LiD9MK^DIfv@02_)xY%S7u4${Y2g$fl{4yf-i%9xbuwvvF@0D=Kh@Bphd>SK ztI4Y(d{#K#!dylr2h5m4JCm7DQ74^H6F)d=uE0`nY(1_~7dge@XxV(eBy1~hvyl-b7JfwaN%){U}Tp!d` zPCYTgS$R#x>S%tomp<&f4{t)+-tz7(#?x^5ATSzj7_Il;R${o*fL9T^l?#MZCUcm{ zIi$-gO<}+DpkqbQHz(SOGsaANUr&xP{^R3vCr^3fJzncSFm4~}y{UTcOX+88=Ql>= zTQFM>24DS|^83~dpJu$jQ0`aqo+a;j=IJl;UM=4>=I##pZ8N|A(WC2(;WGIxlzxG9 z^M$|2XQ6uj3I6t-hZqfSeo&BhHwP_P2HtduG_<#!+kBa)+_gv=-sLH+*n9H4Da}!H zZ67#{`#3D#74h!61tSIRY^vDVNG4ibyE(vF_K~ZRN$`V7*@>cj zcp^BW)P85y=N0vH6JycSxb&yD?~bc!ZwwpYcB;@Fl<>YVeLxZEis8t@*$t&}Vx{N{ z!k*uv=0tJhANarr%;p9-lU6vBemI(NQuJ`M^K~<91nf1)tP8gYb}{#wo9%T$3G=6@ zS(?*a%xP}slRCc{Sl-vhR%+lyf=AJKqdCqK1r>l z6tGL8Fu8S;AWRCwB*Hds4!0hA>zSuuji+F%$Iyw6aqM*%XMWy#zl1xuf(~CtLoeg- zFTs4_6vV@E+LTUQ_tC(ghtckfXzT@)?na#YT|fcPql5>Ay8~|`#wNL~wffh}c?G%P zZ@K;IIruF85-7g!zscoSG;^W&zro6LNhq^W&dKt9R~ciJF;aeGh2w?q;v7Cy>PKq% zzK~x(&fpAP*KRV^Cc3P@?9Xx^725y2@EI@w-!c&84qhcsspAW{n4xI-Tj>7;ve&0L zo=@cdIql|ju|B8M_=V!{rxHYlP>KyGGhprkssI5!R;h5 z?jZpl5+0@r*-wvhkTzr=t;A0I;>f7{0xsF%c|Nw2AHYG+`)E7%M6dA+xELd+@(XZs z5jaHiaUyCiNB@kS<&}Ic`djRDbiQ+hzKiXpTi6ku8e1K8-%fN&Y(aE#>|5ctc5%+K zTk@7E6LVdJZ)y_-%Pi#n|#07 z+pXmDt)BO=ai1X5pCRGjB;nsyT5{oi`h*yrz%|bo!8tPjd4B(=z(pE@3-*g%a~}2u zI*3cO0$1z@xa`|y>25~HiSwrCm*ZNMqqGVqc)*_!_l#2rPw-zjBJL4!_p-MiqSrV9 zPRsKQpLn;Ks{I(+nNXi8!s*JGN|*4ZxS!Cnd`4R|$*zUTv@;WFDn1uZvNvHGZNkUk zBYylJi1(59y|0{4=psJ#{EhPFX?N(0RpM`;f!RuDu~siFr+rwWf96LIgM<9n59yno zeCl`b&e$&IE;%3ab-&sk(emADwM{RqSHn%bfxc-MzmKiXa@xg9eHY)5 z!||IVy3>U8Fy_zFQw@p!XpiaFPB;409?;3L_w@X`(ebg#(YIq0qhr|rN1Gc?8Hm0X z`#w6tURCmSbhtS+H0IRC*l*r1oLbVVp>3J(`8!RXg8bv^JloJA8%C@pb!0N71;9rD+*XQ#sU%e}czC zS29CqsoIk%x{)3pCFMLpLUG2U7&}-5PFU^7Xdh3~VjhPt&d}~0g=da{V{pxBnBfvV z%q>3o3GD7^X;-SDvw?{GupR4V)RDUo<>Rfg6G8TgHk<$KW>3iv_OBF`QHu)6y)SVXwNt>6D&ZJ zR^e&>^z{#Mz7_Xp@U?e8qG@w+`ioF8=O3|~k3v1)_H7)B`9HMjLmX0g^9>FtoQA&G zmqn=OAE@XOnv>s1{)_;c`BZG*39jj!l}N9hmxMbfhJrc3DPTf0aKeR4}{uLv)ou@_O_E8^buJ;EZK z-Z_)G6Iw(HCNzl@ah_xeY04(_iIjGRW>HYg*^POfqnXF}zfP3B4afjyd&_2WeS%FhHRx<*+WmARGGd$)SHNlThv#S3>|{H*W4 z!z<44=1b*IQ{#`7Kh=oO_7_f3o~wm(jr||yz+Xmky-^LP$saJn$2}ir9o?-5_ThFm z@p9OtRvU#I#NUWVvSUJx-xF`L_#gB6{Zx%V_5LF@c~^cD)N+^_hy0(>@+ZuO{$|iX zwHm-L<54x~jT3%Es&>M5IO8Vj+}3j&b?)eWS2gOcPae@%UCsYCc(7(>ZzFFTcpEsb zhpmT>xUG(2bjOwT^rbgGKk#CY$#H;K1EqR`PUso@)3dm)C&*Ecl3@B+lO6Gyy>Lg5 z;HG-vDf@uFB&0{d6L`}X<8YZ|e1SjCdD8beT-FWX9vysYXS{nWYq~kUw1u>7$XxBM z*!IHC)_E7-oJaxA)9qkFjs ztDVN_T)=biG4y^1PHsD?ZWlgmHym@6UH3EzkH=NQgV7q za!v|zQyQ{bYTSBC^CvAxg{RNrT~?4!oZKLb7}=#s1-FO)DRJzX&7aKXO3*PBFggW2 z7nOTSacaip`5b0!R(@PD`i6TX@+)?bUM7`a{7*VpdNcE+jWU~{2(98_W-~pVcM2AdXYW#1Z~bCp2*?0z@z5zZZ_Fd{B%$7)4isgtMnW9^=y=+lrpZ5sHxV$ zlG#kHI*?Afg6`y_-dgpjy7knKaEn4mebR%h*%lS*f?Bl_zjH!i@$*`C(TLrn0lTk1V(>u{`6buZ zRO*!uwN2%BI_0EN_i)QZ(0XOmhOB-EtyWoOl?LT}3t>@V9&N~?PARo3EuBV!FUhnf znO3BdA_X~*e#rPV@VkNUb(CA(?^^0m-S_gom(i!iw7;0A{P0yCF*DO}WRNnMIU2Ku zqUQNsG6tsoH7?qm*YlQ{R?A=!7VJmMR%y1Yl6!yKHv^vkjOP64z>*CyuYoK!Yon2np;lzCM z%B{S@e&;bp+4V~%>o2Mnx5Pf9501eh`@tbO?ITGZhYgQf>*wPV>P0y6w7<(Rz)^oE z#MwnUI}B&>)b?gA4se~?ti-jg)05$T#MR($xMzu8T>_8%uI5X84`+oeP{!}#{{gSK z%ToH2F!33*CXXl`Z4x@{B&=L%;H?zA zG*jSR!>MamNxa8#zP;hRt6q|cF{FXN!E;&iX!fN$WeFOY>V;f@cn>!0L1 z;9fxOYNstNmBD+D9K4sm%Xa%ww(}$Thd;q?9sy3n@%~xxI{9~qbT4}Dp{JYqR#i_F z1I0<-`SnzB*tmiocP5AYR`b@`An%R5Th`#*m#N=Ubze*i@P{@nh}!|)#L17)+UN1o z1MQ~m&*ssC4Bv|%a=6>~3A%w7@bAOGa4-rFKc3t$Mo+w{He=Lq6n_6Lsm2M%>XmVF z8o|HeInUu9qV8JUO^dr}QE#mdC*TYg{wHO$)yH*tywos0#b_&v7^4FEzJwZ-1>uy| zy2`FkBk_>*EtJ$yKQ`0vb>q+d`R??N`y;jD2hr58hsZN^BT8Id*h!>)oi_yi2GFX4G|@H6D_C&}TDler%wUq4BPe=$0Nls}%tKAyxr z+MAK2_R*yFH%a7glD>y~_nL2m!Hb>-`+JqIL4XnR8E-fINIn;DfoIh13AaMD<)6^p zuex?XJjlbLw)QoYTRr);l3#n!S{>WbBs5mvCQ7U!x4Pi-#S%D39~ zt-f*(COyY+DF!Kh7+ue+^c#X}s?~QTh?Yn?)MRW##oVnmP`lvts{wtO(`nTsr=Jns; z4|6@t@#XYW%VW8s>%`sUc@y8B0NeTIYzDjBG_jX=&|yA#r>uhu*2C3Uf#_{{2H(7U zo}*S-GQJ+!`7DKfcP03URNz-s&+o>x5aF)+w){jMiTfT_f-Ne*Q)S_y(r|1cIIkES zlNVko1viwZVXRK8Sd|8#GD~JP+Qc%T8k}957BN6$ylDerYv0?lOop>Po56fd=`-u# zQ|rNmjX_JlTca~QV95S><3T9Et1$AL^tNMh*W=OuF<>-oJ`6Q@4HbA*oWZbsIK%T3 z^mZnyHD8=XaVnOG`wf)M>2hf7T(or#8a|yZ>I=3iyIpyqg?n!cu+rvWUCm^_KpGr- zI{MwzC|TM#96@>i1#W`CFXh8^zhgfn?Zhdw>Sy$C6eOs z_|0uU$Mp|yktRpm8SpNf$9v@5iF6L1kt(N>v40{7e=p5^67W1)jUP#!bL>3*iB$TX z9j-r;aOaU&{~|B1Aj5CwLA)iB)X70<-GP=S;X)({SvGhkpAc>nbAxa_IX65Xb^6g| z(t4s3h7!oTx4pUO`%$^=_dmoqZV&7gnt`jn-zDMS_3eiI{`KyZ*!$(a$C*GoXcczw zS>Gp@!~B^qNEP6&JnkkOp=;PiSFtmaEnzcV$(l$mp6uD&pOl(LAx6T#uH_d=_7_R@ zSGDQ3=X=_IGvNpAnNNT5qj>Yw^A~w7h-3koc*GZUe_L+%j^q-i2MJ{HTYBmuZNYhP zSsqvEITGCc#-gQPrbRM?@ElH1y^fo{i?hB&J8+ve;3_-D4de7Lj{S@gK8mB?!fw1C zXTE|r<$B|{88^Ng95(7lapy;jxYL96%m}^on(#H>UXJTPc1XXC)V>b)z0o{aiOXI= zue8<-+MtYexbFa~l(m-Bum<<(p`=h@62lcuLME$F41=#j=oy%`Ni*md2^Yzfew zR;8!e@+f%GTzQSA>>Zl155X5&|0Vd^`>Ebfq}TX>re&PJk>=|Ntr#K2Xs!N0>!)hP zm)_0uZjK(|yQJ^mH~T*J>|`+-jPN{P9*d>;O+6Nxxk2ByK#Lcu!2-2js|RkIUHI8V!SQthr7flJzOPhAqliIGEMv|VZ4c9O!aDdZU=)jE=aRxD4# z}+PMj)wcAnJ(6n`Plh`B9({dkT zq@Qwo(y(yHk@N=YwnOH)Y$1P*&6TVaT8QSrQc6@AxPB-(X zsp}8w_=`AyMeO<4)@6~19!#Wzyr%cA=-G>U@Txg+!+g7KU0t)z!b-ZW7w?#xxAod( zbN93u$ISO5-fp*6wurUD^D274mFD-VNOC%=`*Obt`-EOU4I>?)4LwB17qnZ)jmA;B zsdGl+h!MSLG)@@#^VY;Uq5U{&^q$`ntoI2(_au}RFRwYC+Z<05hn4X0a=3U&LLsX-pV?MOt%Cn^ zCNnfSNXp~mp81)~Tumv=Y|i9}Ym)oH*Zt`#dXh_fkOw=`9dr?|vv(ck*({F3v%%gu zl$wRqn2zL{TyCjJp-v(}Ar;0?n_1udnL4j1;AW1wcW3 zLNSt4S$?J!g%5aJ8_(gML;lVG;^cQan`jF^=GD$7+K3b18RuAv;#dksPvC0y<8ZbK zSL0sR;MSM3-YsXvTPO`%rRN86N_ANAaDwuj!B={=aHjWjy!%F)xnLG9X*MZfChlpH z=a1z1w%=oYdjqF5h9vQt@<(|08t!N)&*w30ckaW+ecvY?q?Ug;V=0TWvdAy1-|1K= zQ%9%sU=C+5%>v&^^9{?@e9u3z9xje^ZCP++S)vE+hB)i@RdCnyJ$~m&*i2Kz!<^1Q z$jR3>mz@pS@m-npWF|e9j?9zANMynf2P6Qvs z<-$jKrS&CEcf|*F0nU0f*1v-lzW-$;SCiZRF|u25QwLap_JSigrvv1=Bc#oPeAxE# zliP+@+hWFS;ko;d8MD*({c=Ap3_EIXo3lw-ymRomDoW0;XxDlfTvHj^*y3~)`PkA^ z)`9o{|c?Q{{rH|GvL$9;4Dy7_;FAK7)<;LGxk zS~p=YQD*Bt3w>68>ocD>d8Ei|#RXrX!g4AFD$@7Wt-f>g zEVpPuFDm5%9pG7Tly6fwP2dFm;89*_dwHSliF=`Sp@r>j<+cG2)09>RRlF-ngOX2c zgN8V@FcrN|0&`5`#J8Pw%fNf6c>7&B4_|l8w1dpQ_%$AlWEwx`6^igUpaZ?XCh6_HZe-BB2 zM6Vy!&&R+~IR{V4y|~(*K zaAy^oq;R%L1;5L{vc=_+$Je~#xZmEF!rtZ-*I9tDMk)BD7@02Y#!3sPCX1ei&yL%5 zaR#2c1Sj2%WsD|DnKFL5VJf=|?vhdO@ea64yONB?C4Ng7Nihe>F=zC?9RUe)kH|d* zJe7i^n9|OG%HmT=;1qm(I{y1XWj+Y+)mP64>62>0brrR^ zl9Uzvs)CZ#)noNhpeB0rAx{r^)0D=jkyf{sCYWY=j{>*v<#G%NOd8q6Q9;rV9XBHG7a;K}7? z<2-@9xv@3I@d$38fL$L@ov*+V-*MK`;>9(MaeGjW?(!JVb=0xR@^Rr=5#4}d{>;h1^}-7p0|{~*rSut9h~ zmwjguPhNIa80k5j)&TH?-~IJPfA0peay<@XxkW&{aJuO(HqM>$+RE;^Lteq#c&B_1 z_+gJQG+`RENYfb`yFAi3p|u7JGCu*;MeR$xb} zEWePpCa8`_C6mx6w2@b9;lthsZ-|!k3aypinogl5j%K3>;2d2G~241<=s5=b%9+)>(pZd8oApF3-vf)mF%}#4yxAyeQ*>U;YWYc z%si^EPHFRgv-q&S+Tz_d--18=YCiUByyKVRcLy`Rt^C@F+e-hnHRB&9-?TN`8w(o< zA2OpG8iQ75xSJH^d){gd*8j7{=!_M1(W<&)h2Aq(cg)gcAi3F?*(}axHWxATin8mK zH{Zjal(J@Faq~1E8(&_tKd0HB#as^0Sv}|Vt+=!$&E6_zaoBxYOFm6#)0)etwHf^1 z{4Ym#t7TR;FvHu>YP2y+JDBwy$ZoBKZKP~3eiu(2{j~>;{R%s8Dhk8to&}}PYgH5i zZtPaap}voha)=z8k(x{RrI12^c-39B`tm~fL?f>Z2A&- z-mHIK>z)-pt&IOp5KZS>N;cSg;5uA%%`E@dEDdL^AC8|f)y{0~0#AjTc{|~_I>6~2 zjbclri-yg`<@|&;&h>Sk@N400F+L|*Oc(nr zZ@xmc=AbG+fM0x>M`oCh>-h!8^F3-f7lq`dC*JEIJP$|r-tujnawjU~KUjuaTEeGo z5xV@N?{iSu*}_@Ud_`WFff|2>%6{qjD{(%T=Ol67Bc;AC{1`?4f}Jar@vSmK`aq?B zR_;$cXn*nillSvTxuH(;z|Y?Of*1ImY_tep@HY-%4cLUwSR2C@NQ7>7$eTz|f#4@3O!;`SG>C+H?#uorgJCp~bmozx8F#ZS%g zZJu{?#hV+ieGlI{8-q4#(n?89~_Yk zr@C}g+rBvAzWBERavq@nddRt_H{F#!K*|C5>2Sh9Hzjn$B{sn?H;ltW_`bj^w!ta3 z@V~hfHKl(*+`{Tz(7W6qA1*SVdgd1+FD|mM5(}DZ-1n>J^_=B>=#D%E3xN-AC>!4JnUz647A>!HQS!Sb3P?}&bl0EO%5?D zU&K)kGF$C~(&Ov&_y*&=L;ib}b3*T)GdkCe{5{W!o^RrsgZAjAyUUV0c|8FSml>qT zb7jTbWg}^2AyK7umQr%kRD#)c4}X^=HX6Pd1BW6lRpt+09{wrexdPl%h8$f3)oF<01j^L`73qqycSm_Tp|b70Z|!?4 z6f02e?kL{l@ZJ;RKJNSD@LoUsR`4I|0DpEumD=MRy3q6W!aMcBiGyG3Oy4=^-__I6H&7yo)gHoG4#iC z{9DL1KpGS;B^s0lMDP@M_1ty67ETFt10}j%4!td?r;5V-x$#H^eJ>)9691oX6}7IT z%=+?aq_r)ywiOE0S}%lsp@GiUiMJ%Pnx{j@va3^iWoJd9Gpc(Q_5M%eSq2TRtVWf@ z3ghV6xI{{4g{Hb@J z3cpahFZJ4YMj_k}@tqN#ZFIxV=h-OjZ2dh`pUf~?Gx4F{gP*neFXOVr=q?v`sXqTh zyx)z}A~Wn)GtABezfZYw@3`=&vo%jTh3&ljZrDwI!_Ms6PV2Z~SM@FDUtY6Y`@H8% z&bK`0_c>=$ov|nJJihjj(>;#xNZX8W+JsM9Zx(MdySI@l4xs#p;=ETIWi`i3JuGb# z(8BMBeQRx1w4k49ZY9)}riPVaXA$0VD_(O4ioe5Z+=J&lU_Knd%O0j>I&7ux^?R3< zz0q7*WwkG*J^ITE|C1EC+{#`^B3y|2|4dWleoGX0KT322O+Sh%oj{GkE$3(9rYq>c zH8|-C{B#8+J0Z?FG$h<08FuyW^n6fw41G8bj!C~q+O6Pkce3d zzsS_f;jNXPm-xTP-vUoRD{G+?KjS2R5py1#_lr2;e1HY9eSYnc?ilOwakTlgT+YIL zVfXF{<%KhbPKe0-(VdXI@pK9^JX^;-@w5#**Y#YBRx#XBRK^S~Y)rD7ow=-*OwwmZ1G1U* zCB+L`=5ofXobM&b`-Rb$z~g4a-=@azrbbB<(Vqk!OBYeu3%H^Kc*Nai=T^MgEi&>uPIZ!&0K8tqHK8{Wou{ww@f7|xWxg}z4gLuM;Gw=^a7Ge0zx z!x@75HOK~)eGBxr6yCq6u%N!n1q)<}!wTgsMcbDtYn^f2AkKDue8AWpgl&!*yCd{H z0fJ6_x3S*|v+S2oz%mD=Jt&W(bWSIY!C7#Qyy4VzSTtz#-SUHOW-^1b!r9?g+w6X4 zG=o#eDPN$JMa{B;RzM;1u&^~!It~w5A!R@Xf2F)DCQS)+skFD{#jh%URXH{?o0~}8 zTnR1Z+}iKX=6eq%_3*C0_1P1p?&SGlv%aC z`VGB#LvP&l91|z0dgK)5Lhr-w>QZtmuEwRL2)l$!T0i-fUR10?N+~YC!g4IC^*QC6 zE1q{TF>|YbUSIR5Nr5;tS7swQH21cJl+DCwBu)b>wU+*=Z4Fjat6KW&Ka7C0fOpDR zrDd$#O2UfPZEbOzO4COAAm?^gqp+_x_$YT*&(3>cA!Ikv4&U?!{oT41G zJx!Dq_ITG5ufF$<o>)lBhbE0Mkv&rpW%LwP(! z8N5Yx9tz=%5hp7ewaLUV?N5B4q^CdB+IN*V-Z=l4 zCM(@m4)L?_-^nU%7TjnCTxTlnNv%DB(@dc!QmS`q+JaQ-n_f8?#0@v}W@01Hs4ZFa zN-jNH(7Y|9cf!g0)wH^j-_`X@xV@wlj;n-OQ%v6!)+;6ce-@R~Go{5UD|R>mprl+% zsZH>k4jf;>c$i1M!~0Uw7S@g;@xKE9KaWePQJ7;D10}NxisDXl;d-)J6@fNp@-DSG zlfml9pqDaw&g^{}I3NX_5bm%`4o3w0SlF|X6pl#_rzgP3w_wnJ(d=;k#6Hhk(CUr; z2iOKrJ8L?wH@^zoUWwE3O}u&6cwR+ku_Vq5Y=VO~z_P1pFE+yK>wOES3T_7B=IgD} z?iOx?wYQ78L*Covu~nM&U=3I<&SGzVQKz5eIuDij74-<`4XuFH!!02HuwQOux7?)G zTTq&fTDL_@HfZ5CtqK;sy?%$CDgW&hPQdF$q)AjG@!9U(6eI0bbqjXTE84&g3Qma^ z=RQbiSL7A;A)gcf1dM+O2eV%G`qk)(%CV2o<=pUsmD2Wh$`Eurf~0lxcH(m zxL}+P!Sma3h+F+$k4CIBUMoC@9VvmfER^ymoZ&)v9A7NVjxJ<-5r2gGyzY6VccbJH zPQ4#1UU+u9AIK_xX6NT+bpJ_u@?~1q#N_18pvMQ$ z!~o%Dmu)!L&0s5f9AG2byag8<_{_~H@JfHnQSn9Q!k2~XH-GzEg)a@?{s7@z zm2jrY0&(Vg`;DAJ?z4=-S4L#E(VGg~dx-Z9T*h`a+k!XVP7kvw&i{TZ%>tz^G-?Y- z=Sy&{Bnr>xJzv9P+>`rV^N9bv@jj}R7tF6K)=z@}F{7JYm>8cG_l zVH1|f06T>9Dso%V*-@H2R&X9`xinf+4&4d#GtjxJ@!wV9z?$AYUs$CF zjN2O~ZB35uOk3Z9hQ2cl))Q762s=K*vu6ESd73K|pGo1qwJkMr({swlQA)LYUXa=cnwj93mG!HEB z^tTvmc$%%|p|qS=*Bo@`W+}f6t ze42%vnuK=~KSgWXjByJ08K;0B@x0%?P}_xj{60W_JrTcm%6?p@hF>LrM%6J1NG^YS zH$BeiIwAj}wlB-`$K(YZ4%xxe)f_ zX4eZjv_2mxKDT+2Ps@vevY?VV^Z?pa2Ys%Cax~Gp`eN5c9cs(1VVu7RC$6MG$SZ^VgAZ;F zl2azUUFJBySx@?UsN8>N*#`SrH8a1uT2@eg&|{RgJ_6?#c(uy7rHWF=IV#kyl+_qK zMvCEX3*mIb4xkcNq%+@1FL%I6lFSLx%|=}ETH!(x&9AuS0Ke1cETSR%K^iBP#kFYT zV7IWFdIU`U27LdH)jkm}4<}tshXh?n+jfMrN4~M^2O5ERy*bvp)6uQ}o@_$=dZ}}TVig8y6m_~M)DaO}wpW*ix{|}SZ=wmv@x9KG(fN`Eb0F&q* zzwqr#vQM}>eir@Z*J}GU&FL5PnA79h?I*SO33)#y&u7JZM*Jtm3GZL<{7gLjO!{f^ znNEj2Rh?$2%QW)Tba6h{>M6o0bf6Qxn?Tn&5smmjy!W;0e_HUdx1V_zTKSp!e-1v9 z*CcT#Nb|nDKM;m`PZoaY{fBWq`C#n{dAD&j zD7SFJY`8t(BQ2POVtfkQ2d{vs=*y(IRJmAx{jO&7!0%H0F6DCZSAlh&H+a8M4OeT$ zDy?6th0FBbGU0l)*sMl-)#9*t`_$qD-SS@P_Nmi0_1GDQPvUx^)d*3NR5 z`&qf3k=q6Ra}Pbf#afz_oSKY0n;fKKSxrIq<&CB#ztM01Vg>!|_Z+M12fV{9e9I4> zzrn+N4}JklXwBBp9qgd1*hZ(Y->TeUh3+EZ?XtpmSm6iB!Uyp{$8mB&9~5>AUstZ1 z!SK9UNrYh^Ye|@)BFtO^)P%3XNqIHlp$B2epuzd?biCYfN*+9W0kk0S-$nhEjC0wA z;H2Wd6@<@9qT@~8y+RD{c_z+)Bh>t#S`*to3t<>0Zh@+&7r1)P2bVP!ei z^sX_?^$>j750(4Z@&gvcX>|IcgU`-GEvHQWbJ(L$tF$?lrcl>-Wx~?AD+AFSS zKgX(jlJ5N|e~F{~H4ZtS@+g1WL(UxD?FOGc?%dw(?8$>Po=2UwcEOpI=bcA++qWCE zp10ipa9Mc4yK^+5=bSxxfrj)9&FOLB5$6^i1lv)c-F|OJwRX{{Zl<~2<_@$y|3}kZ zz-?J%eE=qu?(R-02}J=>Fj2(r?p)Umb=SaNV|90J*VtXxSi4YcMG+(fmG176l2Y-z z{`ceeKELx$ojDWt#5pr(X1q&1qs$1q^{=tN1?LU3+$-X|Dn0s&-jZG@?OEc7)+{t; zd4*_-`!1(=KVz1#@7xAAN4nFQ3(Sbl>*LVx74Prd_n~(;^JeBB>70F|VXOa0P#FG!?tyXB+)bK>tW^guD(YV49gAngsK#b!CQF zNh5A~v7RzO{;~!(m?qs&v&KPq@*}j%eL-LOZlgY0i`!KGa=txpg11$Uj^gYmJTuK9 z%z^NZEND%&YCIpEdBSGFnQwNQWfoejea`^1wCyR(3EKG>?frA>IHN)CF&z*0TX~*k z6>)~Ri>)Zm0C7(-bIq~>GGDx9Xwb%1SJ{#1<$Lzv&Ra&^i}2_-W*smZ&-3Mb4*N{} zeAe-3ZG-w|N3Ry?yWi+j(~L5+NjOVMMN3II(Og_$gqcgWna^Ad7V^uBkE`+gYmHo6 z_4Doe`&JzDX7Se=t%|z|g)9}GQ?T=eEHiUP>vV;<^9s7l@aQY>;kiq|Jw^QIf<;EY zr6}eV$BoRNB109cSgZB+Wk!!Rq>&BG9o*YVH@gZ6tD4?ZT@S0u%aCelZ%9Gaghj7E~*Ge^$fN`@89pT?;6uSC_{{Rl%!N z$D!24)wt^e93$>2=$xvj1=7P$QX?mk{Eh`f(I14yap)b3{%PWzLr%CHt*k%%LGQmt zIsYh6*DBkU;$Eekm-4$z54cP|FHo*a!3EN~LRweB`F#^(Kh#jSTC&WU~Ri zwMK}Qz&RIRez=}yKho{C)A%ibv(V_VjNb~Q!ZN*YncleAzR5zpc0O~4UOCGRbBo;9 zxEjtzaW{jcyA_Rf^1F`PSs6Hg(#o!deE+j={RboAwdnu3puYvK)A7psd-WFGBzvPIpgQWS4tovUe>GfZtzu{KH_UU? z<9WXPDZY`n(DlY$diKwH?`|A#?oG{_WOMc30k_%NH^_Z9xjCRVZZ)sbW_4{(P{9n6 z?_0xqSabG9M*l|IL1Qs+-K|mZ&GCTH029 z_Qu*#Q(SGr?XY+v(A zZ@7KnX3exG+`W}BZ=JWdPMOkm6{ig|uirFO;@pW)3ol<2Z(rAZ(@bqO=WatpRW(zUF&epr zg!!eB;uB-T2&2?UBgXsu^VZq~+`$C?Spyn}8ySnvcre3gyH|}x9~hI~#SMLEd>RQpV1EaX^^vh_1pe+lD^c%D zeWYE95AaFRym=qrGy*UGDUNLvYMmVZwK5Lp-Q~AwgW~FN;{%Sft z>l^XD!GC=tN0ZSRhX?xx$NC*kdvf9bymCH|*2~t*va0bS`wM72W5wfHBkXf%{nw~! z76$Xcd^GaH?kt)liwkaWlCk$&V{gXa$!aopyG$nC+%!bw@>cPvpbQNpS zHLYFLkyd?s==ITPVeO)sJak}hBb_eN>&EOMe_f@um$9wAHJ&!i*3xe-A5Fz+ZvCUV zb)MGN08;kORzdo)51?5w485a;oru;c=$tII(F9@Np8}+Z&FLQ;b3nw(%i!@XJh|jgt;9zdn@xsIJd+3ixlr;e@N;N z`92Rz?QuAdFdr-Yj^%fX+B(j9&uP}2juCbo+(Fz2sHNU&X&>&M!uAIPeTAdc*fHoH zBi_mUj^}p*zhn8GDNm=#>&0s4O#jbUg7b}87qaJf5xB(v{4VGFd#PV1_AN?rgHqfm z*MDYSFO@$TTmNJ{yGl;3GM4?(H@Hr{U+Y`b!(neMyuLX3?oE_9&`=H1N#GCUaPB0A7i!%l(;)aG=ZaElaK1<}S_LMY0}$w9**1R{sm($kD0Q;kd$j58CB0ppDwV~sb_FU-3=k6}& zv#cx36=zC;e}?o=MdM_-I>G39yfODgqv7$!&Qp!I3BOoguQE#g4xQ`J{}bAG%IAGX z-M9mee3JAS{B_%XHch|%$3 zqv_v`u6bkdNiy}bM$c#Y{g3&A(LAd(ufTgj?Yu1HP455seI)!Nz8~}ZQrPFkNd1^v zxkrxwDyKKg_3i99FKYy|tRc+izW}T@vag4~4Xq#5_|NG4g2s>FC+>~XjsFkK-E^5N zI+Ih~%6?tY)T(|1yXy_;H`gUu*E5&3vcBc5H0|RZ62(Z;#0YI?gq`D&_@EC+1)q}; z#*kX3(Pvr$R&j46L98cPY=yf4;Fs`C(M{^B{SP*i4=`)z6#XFPV4TCjAo{@v=^F
nwwRiw?e=DQ|t>O+8cCaz$a3k>$W6dGr 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%0D|n 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 diff --git a/event-queue/etc/Bass-Drum-1.wav b/event-queue/etc/Bass-Drum-1.wav deleted file mode 100644 index 566181d942aa4542f36826d55161845f9ed0ad53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221080 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
  • 60JcG?;$VvR*l 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%0DPyWASwtTqG(=xxC$ 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 rmv?{vs>IF30Y5hZl=p7_t~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/event-queue/pom.xml b/event-queue/pom.xml deleted file mode 100644 index cbfc0976da64..000000000000 --- a/event-queue/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - event-queue - - - junit - junit - test - - - \ No newline at end of file diff --git a/event-queue/src/main/java/com/iluwatar/event/queue/App.java b/event-queue/src/main/java/com/iluwatar/event/queue/App.java deleted file mode 100644 index ea107d6ca4cd..000000000000 --- a/event-queue/src/main/java/com/iluwatar/event/queue/App.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.event.queue; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -import javax.sound.sampled.UnsupportedAudioFileException; - -/** - * Event or message queues provide an asynchronous communications protocol, meaning that the sender - * and receiver of the message do not need to interact with the message queue at the same time. - * Events or messages placed onto the queue are stored until the recipient retrieves them. Event - * or message queues have implicit or explicit limits on the size of data that may be transmitted - * in a single message and the number of messages that may remain outstanding on the queue. - * A queue stores a series of notifications or requests in first-in, first-out order. - * Sending a notification enqueues the request and returns. The request processor then processes - * items from the queue at a later time. - */ -public class App { - /** - * Program entry point. - * - * @param args command line args - * @throws IOException when there is a problem with the audio file loading - * @throws UnsupportedAudioFileException when the loaded audio file is unsupported - */ - public static void main(String[] args) throws UnsupportedAudioFileException, IOException { - Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f); - Audio.playSound(Audio.getAudioStream("./etc/Closed-Hi-Hat-1.wav"), -8.0f); - - System.out.println("Press Enter key to stop the program..."); - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - br.read(); - Audio.stopService(); - } -} diff --git a/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java b/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java deleted file mode 100644 index f8f1b1e3cddf..000000000000 --- a/event-queue/src/main/java/com/iluwatar/event/queue/Audio.java +++ /dev/null @@ -1,169 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.event.queue; - -import java.io.File; -import java.io.IOException; - -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.Clip; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.UnsupportedAudioFileException; - -/** - * This class implements the Event Queue pattern. - * @author mkuprivecz - * - */ -public class Audio { - - private static final int MAX_PENDING = 16; - - private static int headIndex; - - private static int tailIndex; - - private static Thread updateThread = null; - - private static PlayMessage[] pendingAudio = new PlayMessage[MAX_PENDING]; - - /** - * This method stops the Update Method's thread. - */ - public static synchronized void stopService() { - if (updateThread != null) { - updateThread.interrupt(); - } - } - - /** - * This method stops the Update Method's thread. - * @return boolean - */ - public static synchronized boolean isServiceRunning() { - if (updateThread != null && updateThread.isAlive() ) { - return true; - } else { - return false; - } - } - - /** - * Starts the thread for the Update Method pattern if it was not started previously. - * Also when the thread is is ready initializes the indexes of the queue - */ - public static void init() { - if (updateThread == null) { - updateThread = new Thread(new Runnable() { - public void run() { - while (!Thread.currentThread().isInterrupted()) { - Audio.update(); - } - } - }); - } - startThread(); - } - - /** - * This is a synchronized thread starter - */ - public static synchronized void startThread() { - if (!updateThread.isAlive()) { - updateThread.start(); - headIndex = 0; - tailIndex = 0; - } - } - - /** - * This method adds a new audio into the queue. - * @param stream is the AudioInputStream for the method - * @param volume is the level of the audio's volume - */ - public static void playSound(AudioInputStream stream, float volume) { - init(); - // Walk the pending requests. - for (int i = headIndex; i != tailIndex; i = (i + 1) % MAX_PENDING) { - if (getPendingAudio()[i].getStream() == stream) { - // Use the larger of the two volumes. - getPendingAudio()[i].setVolume(Math.max(volume, getPendingAudio()[i].getVolume())); - - // Don't need to enqueue. - return; - } - } - getPendingAudio()[tailIndex] = new PlayMessage(stream, volume); - tailIndex = (tailIndex + 1) % MAX_PENDING; - } - - /** - * This method uses the Update Method pattern. - * It takes the audio from the queue and plays it - */ - public static void update() { - // If there are no pending requests, do nothing. - if (headIndex == tailIndex) { - return; - } - Clip clip = null; - try { - AudioInputStream audioStream = getPendingAudio()[headIndex].getStream(); - headIndex++; - clip = AudioSystem.getClip(); - clip.open(audioStream); - clip.start(); - } catch (LineUnavailableException e) { - System.err.println("Error occoured while loading the audio: The line is unavailable"); - e.printStackTrace(); - } catch (IOException e) { - System.err.println("Input/Output error while loading the audio"); - e.printStackTrace(); - } catch (IllegalArgumentException e) { - System.err.println("The system doesn't support the sound: " + e.getMessage()); - } - } - - /** - * Returns the AudioInputStream of a file - * @param filePath is the path of the audio file - * @return AudioInputStream - * @throws UnsupportedAudioFileException when the audio file is not supported - * @throws IOException when the file is not readable - */ - public static AudioInputStream getAudioStream(String filePath) - throws UnsupportedAudioFileException, IOException { - return AudioSystem.getAudioInputStream(new File(filePath).getAbsoluteFile()); - } - - /** - * Returns with the message array of the queue - * @return PlayMessage[] - */ - public static PlayMessage[] getPendingAudio() { - return pendingAudio; - } - -} diff --git a/event-queue/src/main/java/com/iluwatar/event/queue/PlayMessage.java b/event-queue/src/main/java/com/iluwatar/event/queue/PlayMessage.java deleted file mode 100644 index 5ced2e3b3811..000000000000 --- a/event-queue/src/main/java/com/iluwatar/event/queue/PlayMessage.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.event.queue; - -import javax.sound.sampled.AudioInputStream; - -/** - * The Event Queue's queue will store the instances of this class. - * @author mkuprivecz - * - */ -public class PlayMessage { - - private AudioInputStream stream; - - private float volume; - - public PlayMessage(AudioInputStream stream, float volume) { - setStream(stream); - setVolume(volume); - } - - public AudioInputStream getStream() { - return stream; - } - - private void setStream(AudioInputStream stream) { - this.stream = stream; - } - - public float getVolume() { - return volume; - } - - public void setVolume(float volume) { - this.volume = volume; - } -} diff --git a/event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java b/event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java deleted file mode 100644 index 8e31ec6c3816..000000000000 --- a/event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.event.queue; -import static org.junit.Assert.*; - -import java.io.IOException; - -import javax.sound.sampled.UnsupportedAudioFileException; - -import org.junit.Test; - -/** - * Testing the Audio service of the Queue - * @author mkuprivecz - * - */ -public class AudioTest { - - /** - * Test here that the playSound method works correctly - * @throws UnsupportedAudioFileException when the audio file is not supported - * @throws IOException when the file is not readable - * @throws InterruptedException when the test is interrupted externally - */ - @Test - public void testPlaySound() throws UnsupportedAudioFileException, IOException, InterruptedException { - Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f); - // test that service is started - assertTrue(Audio.isServiceRunning()); - // adding a small pause to be sure that the sound is ended - Thread.sleep(5000); - // test that service is finished - assertFalse(!Audio.isServiceRunning()); - } - - /** - * Test here that the Queue - * @throws UnsupportedAudioFileException when the audio file is not supported - * @throws IOException when the file is not readable - * @throws InterruptedException when the test is interrupted externally - */ - @Test - public void testQueue() throws UnsupportedAudioFileException, IOException, InterruptedException { - Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f); - Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f); - Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f); - assertTrue(Audio.getPendingAudio().length > 0); - // test that service is started - assertTrue(Audio.isServiceRunning()); - // adding a small pause to be sure that the sound is ended - Thread.sleep(10000); - // test that service is finished - assertFalse(!Audio.isServiceRunning()); - } - -} diff --git a/event-sourcing/README.md b/event-sourcing/README.md deleted file mode 100644 index 1079405fa885..000000000000 --- a/event-sourcing/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: pattern -title: Event Sourcing -folder: event-sourcing -permalink: /patterns/event-sourcing/ -categories: Architectural -tags: - - Java - - Difficulty Intermediate - - Performance ---- - -## Intent -Instead of storing just the current state of the data in a domain, use an append-only store to record the full series of actions taken on that data. The store acts as the system of record and can be used to materialize the domain objects. This can simplify tasks in complex domains, by avoiding the need to synchronize the data model and the business domain, while improving performance, scalability, and responsiveness. It can also provide consistency for transactional data, and maintain full audit trails and history that can enable compensating actions. - -![alt text](./etc/event-sourcing.png "Event Sourcing") - -## Applicability -Use the Event Sourcing pattern when - -* You need very high performance on persisting your application state even your application state have a complex relational data structure -* You need log of changes of your application state and ability to restore a state of any moment in time. -* You need to debug production problems by replaying the past events. - -## Real world examples - -* [The Lmax Architecture] (https://martinfowler.com/articles/lmax.html) - -## Credits - -* [Martin Fowler - Event Sourcing] (https://martinfowler.com/eaaDev/EventSourcing.html) -* [Event Sourcing | Microsoft Docs] (https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing) -* [Reference 3: Introducing Event Sourcing] (https://msdn.microsoft.com/en-us/library/jj591559.aspx) diff --git a/event-sourcing/etc/event-sourcing.png b/event-sourcing/etc/event-sourcing.png deleted file mode 100644 index 0b0098546300e34203b06fefec325f0a81e1d1f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60339 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%0AKM&}B6&mY86G=qr~XfB};B`_tT#9i`_L z(7Xc6%eqv&?UHtT7iV7XC1!((wai=i6$b<4Q3FJ>vTjL-Bj4cLq@nn>LEWV)9ax`V z-Er*nKWp&$pM9$&8qQDctbcFka#8!o;y5YmGBB4h_Q2|uFH~F8=|f+(g08ISj=v~( z5yxSO4lME1UO}Y2!)NQ2;^T0(jWC7lun(Be(dr}0CZMAgZQAz{14fouYq{@OmE*)5 z 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 diff --git a/event-sourcing/etc/event-sourcing.ucls b/event-sourcing/etc/event-sourcing.ucls deleted file mode 100644 index 2df56a4796da..000000000000 --- a/event-sourcing/etc/event-sourcing.ucls +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/event-sourcing/etc/event-sourcing.urm.puml b/event-sourcing/etc/event-sourcing.urm.puml deleted file mode 100644 index 207d238e67e4..000000000000 --- a/event-sourcing/etc/event-sourcing.urm.puml +++ /dev/null @@ -1,184 +0,0 @@ -@startuml -package com.iluwatar.event.sourcing.journal { - class JsonFileJournal { - - aFile : File - - events : List - - index : int - + JsonFileJournal() - + readNext() : DomainEvent - + reset() - + write(domainEvent : DomainEvent) - } -} -package com.iluwatar.event.sourcing.processor { - class DomainEventProcessor { - - precessorJournal : ProcessorJournal - + DomainEventProcessor() - + process(domainEvent : DomainEvent) - + recover() - + setPrecessorJournal(precessorJournal : ProcessorJournal) - } -} -package com.iluwatar.event.sourcing.service { - class AccountService { - - eventProcessor : EventProcessor - + AccountService(eventProcessor : EventProcessor) - + createAccount(accountNo : int, owner : String) - } - class MoneyTransactionService { - - eventProcessor : EventProcessor - + MoneyTransactionService(eventProcessor : EventProcessor) - + depositMoney(accountNo : int, money : BigDecimal) - + transferMoney(accountNoFrom : int, accountNoTo : int, money : BigDecimal) - + withdrawalMoney(accountNo : int, money : BigDecimal) - } - class SequenceIdGenerator { - - sequenceId : long {static} - + SequenceIdGenerator() - + nextSequenceId() : long {static} - } -} -package com.iluwatar.event.sourcing.event { - class AccountCreateEvent { - - accountNo : int - - owner : String - + AccountCreateEvent(sequenceId : long, createdTime : long, accountNo : int, owner : String) - + getAccountNo() : int - + getOwner() : String - + process() - } - class MoneyDepositEvent { - - accountNo : int - - money : BigDecimal - + MoneyDepositEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal) - + getAccountNo() : int - + getMoney() : BigDecimal - + process() - } - class MoneyTransferEvent { - - accountNoFrom : int - - accountNoTo : int - - money : BigDecimal - + MoneyTransferEvent(sequenceId : long, createdTime : long, money : BigDecimal, accountNoFrom : int, accountNoTo : int) - + getAccountNoFrom() : int - + getAccountNoTo() : int - + getMoney() : BigDecimal - + process() - } - class MoneyWithdrawalEvent { - - accountNo : int - - money : BigDecimal - + MoneyWithdrawalEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal) - + getAccountNo() : int - + getMoney() : BigDecimal - + process() - } -} -package com.iluwatar.event.sourcing.gateway { - class AccountCreateContractSender { - + AccountCreateContractSender() - + sendContractInfo(account : Account) - } - class Gateways { - - accountCreateContractSender : AccountCreateContractSender {static} - - transactionLogger : TransactionLogger {static} - + Gateways() - + getAccountCreateContractSender() : AccountCreateContractSender {static} - + getTransactionLogger() : TransactionLogger {static} - } - class TransactionLogger { - + TransactionLogger() - + log(transaction : Transaction) - } -} -package com.iluwatar.event.sourcing.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.event.sourcing.state { - class AccountAggregate { - - accounts : Map {static} - + AccountAggregate() - + getAccount(accountNo : int) : Account {static} - + putAccount(account : Account) {static} - + resetState() {static} - } -} -package com.iluwatar.event.sourcing.domain { - class Account { - - accountNo : int - - money : BigDecimal - - owner : String - - transactions : List - + Account(accountNo : int, owner : String) - + copy() : Account - - depositMoney(money : BigDecimal) : Transaction - + getAccountNo() : int - + getMoney() : BigDecimal - + getOwner() : String - + getTransactions() : List - - handleDeposit(money : BigDecimal, realTime : boolean) - + handleEvent(accountCreateEvent : AccountCreateEvent) - + handleEvent(moneyDepositEvent : MoneyDepositEvent) - + handleEvent(moneyWithdrawalEvent : MoneyWithdrawalEvent) - + handleTransferFromEvent(moneyTransferEvent : MoneyTransferEvent) - + handleTransferToEvent(moneyTransferEvent : MoneyTransferEvent) - - handleWithdrawal(money : BigDecimal, realTime : boolean) - + setMoney(money : BigDecimal) - + setTransactions(transactions : List) - + toString() : String - - withdrawMoney(money : BigDecimal) : Transaction - } - class Transaction { - - accountNo : int - - lastBalance : BigDecimal - - moneyIn : BigDecimal - - moneyOut : BigDecimal - + Transaction(accountNo : int, moneyIn : BigDecimal, moneyOut : BigDecimal, lastBalance : BigDecimal) - + getAccountNo() : int - + getLastBalance() : BigDecimal - + getMoneyIn() : BigDecimal - + getMoneyOut() : BigDecimal - + toString() : String - } -} -package com.iluwatar.event.sourcing.api { - abstract class DomainEvent { - - createdTime : long - - eventClassName : String - - realTime : boolean - - sequenceId : long - + DomainEvent(sequenceId : long, createdTime : long, eventClassName : String) - + getCreatedTime() : long - + getEventClassName() : String - + getSequenceId() : long - + isRealTime() : boolean - + process() {abstract} - + setRealTime(realTime : boolean) - } - interface EventProcessor { - + process(DomainEvent) {abstract} - + recover() {abstract} - + setPrecessorJournal(ProcessorJournal) {abstract} - } - interface ProcessorJournal { - + readNext() : DomainEvent {abstract} - + reset() {abstract} - + write(DomainEvent) {abstract} - } -} -Gateways --> "-accountCreateContractSender" AccountCreateContractSender -DomainEventProcessor --> "-precessorJournal" ProcessorJournal -Account --> "-transactions" Transaction -Gateways --> "-transactionLogger" TransactionLogger -AccountService --> "-eventProcessor" EventProcessor -MoneyTransactionService --> "-eventProcessor" EventProcessor -AccountCreateEvent --|> DomainEvent -MoneyDepositEvent --|> DomainEvent -MoneyTransferEvent --|> DomainEvent -MoneyWithdrawalEvent --|> DomainEvent -JsonFileJournal ..|> ProcessorJournal -DomainEventProcessor ..|> EventProcessor -@enduml \ No newline at end of file diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml deleted file mode 100644 index ac7745fbeb4c..000000000000 --- a/event-sourcing/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - 4.0.0 - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - event-sourcing - - - junit - junit - test - - - - com.google.code.gson - gson - 2.8.1 - - - - \ No newline at end of file diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/app/App.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/app/App.java deleted file mode 100644 index 50e9b503edbd..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/app/App.java +++ /dev/null @@ -1,115 +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.event.sourcing.app; - -import com.iluwatar.event.sourcing.event.AccountCreateEvent; -import com.iluwatar.event.sourcing.event.MoneyDepositEvent; -import com.iluwatar.event.sourcing.event.MoneyTransferEvent; -import com.iluwatar.event.sourcing.processor.DomainEventProcessor; -import com.iluwatar.event.sourcing.state.AccountAggregate; -import java.math.BigDecimal; -import java.util.Date; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Event Sourcing : Instead of storing just the current state of the data in a domain, use an - * append-only store to record the full series of actions taken on that data. The store acts as the - * system of record and can be used to materialize the domain objects. This can simplify tasks in - * complex domains, by avoiding the need to synchronize the data model and the business domain, - * while improving performance, scalability, and responsiveness. It can also provide consistency for - * transactional data, and maintain full audit trails and history that can enable compensating - * actions. - * - * This App class is an example usage of Event Sourcing pattern. As an example, two bank account is - * created, then some money deposit and transfer actions are taken so a new state of accounts is - * created. At that point, state is cleared in order to represent a system shot down. After the shot - * down, system state is recovered by re-creating the past events from event journal. Then state is - * printed so a user can view the last state is same with the state before system shot down. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - /** - * The constant ACCOUNT OF DAENERYS. - */ - public static final int ACCOUNT_OF_DAENERYS = 1; - /** - * The constant ACCOUNT OF JON. - */ - public static final int ACCOUNT_OF_JON = 2; - - /** - * The entry point of application. - * - * @param args the input arguments - */ - public static void main(String[] args) { - - DomainEventProcessor eventProcessor = new DomainEventProcessor(); - - - LOGGER.info("Running the system first time............"); - eventProcessor.reset(); - - LOGGER.info("Creating th accounts............"); - - eventProcessor.process(new AccountCreateEvent( - 0, new Date().getTime(), ACCOUNT_OF_DAENERYS, "Daenerys Targaryen")); - - eventProcessor.process(new AccountCreateEvent( - 1, new Date().getTime(), ACCOUNT_OF_JON, "Jon Snow")); - - LOGGER.info("Do some money operations............"); - - eventProcessor.process(new MoneyDepositEvent( - 2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal("100000"))); - - eventProcessor.process(new MoneyDepositEvent( - 3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal("100"))); - - eventProcessor.process(new MoneyTransferEvent( - 4, new Date().getTime(), new BigDecimal("10000"), ACCOUNT_OF_DAENERYS, - ACCOUNT_OF_JON)); - - LOGGER.info("...............State:............"); - LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString()); - LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString()); - - LOGGER.info("At that point system had a shot down, state in memory is cleared............"); - AccountAggregate.resetState(); - - LOGGER.info("Recover the system by the events in journal file............"); - - eventProcessor = new DomainEventProcessor(); - eventProcessor.recover(); - - LOGGER.info("...............Recovered State:............"); - LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString()); - LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString()); - } - - -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java deleted file mode 100644 index d2e5f429b5d4..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java +++ /dev/null @@ -1,186 +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.event.sourcing.domain; - -import com.iluwatar.event.sourcing.event.AccountCreateEvent; -import com.iluwatar.event.sourcing.event.MoneyDepositEvent; -import com.iluwatar.event.sourcing.event.MoneyTransferEvent; -import com.iluwatar.event.sourcing.state.AccountAggregate; -import java.math.BigDecimal; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This is the Account class that holds the account info, the account number, - * account owner name and money of the account. Account class also have the business logic of events - * that effects this account. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class Account { - - private static final Logger LOGGER = LoggerFactory.getLogger(Account.class); - - private final int accountNo; - private final String owner; - private BigDecimal money; - - /** - * Instantiates a new Account. - * - * @param accountNo the account no - * @param owner the owner - */ - public Account(int accountNo, String owner) { - this.accountNo = accountNo; - this.owner = owner; - money = BigDecimal.ZERO; - } - - /** - * Gets account no. - * - * @return the account no - */ - public int getAccountNo() { - return accountNo; - } - - /** - * Gets owner. - * - * @return the owner - */ - public String getOwner() { - return owner; - } - - /** - * Gets money. - * - * @return the money - */ - public BigDecimal getMoney() { - return money; - } - - /** - * Sets money. - * - * @param money the money - */ - public void setMoney(BigDecimal money) { - this.money = money; - } - - - /** - * Copy account. - * - * @return the account - */ - public Account copy() { - Account account = new Account(accountNo, owner); - account.setMoney(money); - return account; - } - - @Override - public String toString() { - return "Account{" - + "accountNo=" + accountNo - + ", owner='" + owner + '\'' - + ", money=" + money - + '}'; - } - - private void depositMoney(BigDecimal money) { - this.money = this.money.add(money); - } - - private void withdrawMoney(BigDecimal money) { - this.money = this.money.subtract(money); - } - - private void handleDeposit(BigDecimal money, boolean realTime) { - depositMoney(money); - AccountAggregate.putAccount(this); - if (realTime) { - LOGGER.info("Some external api for only realtime execution could be called here."); - } - } - - private void handleWithdrawal(BigDecimal money, boolean realTime) { - if (this.money.compareTo(money) == -1) { - throw new RuntimeException("Insufficient Account Balance"); - } - - withdrawMoney(money); - AccountAggregate.putAccount(this); - if (realTime) { - LOGGER.info("Some external api for only realtime execution could be called here."); - } - } - - /** - * Handles the MoneyDepositEvent. - * - * @param moneyDepositEvent the money deposit event - */ - public void handleEvent(MoneyDepositEvent moneyDepositEvent) { - handleDeposit(moneyDepositEvent.getMoney(), moneyDepositEvent.isRealTime()); - } - - - /** - * Handles the AccountCreateEvent. - * - * @param accountCreateEvent the account create event - */ - public void handleEvent(AccountCreateEvent accountCreateEvent) { - AccountAggregate.putAccount(this); - if (accountCreateEvent.isRealTime()) { - LOGGER.info("Some external api for only realtime execution could be called here."); - } - } - - /** - * Handles transfer from account event. - * - * @param moneyTransferEvent the money transfer event - */ - public void handleTransferFromEvent(MoneyTransferEvent moneyTransferEvent) { - handleWithdrawal(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime()); - } - - /** - * Handles transfer to account event. - * - * @param moneyTransferEvent the money transfer event - */ - public void handleTransferToEvent(MoneyTransferEvent moneyTransferEvent) { - handleDeposit(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime()); - } - - -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java deleted file mode 100644 index c526396f3976..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java +++ /dev/null @@ -1,82 +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.event.sourcing.event; - -import com.iluwatar.event.sourcing.domain.Account; -import com.iluwatar.event.sourcing.state.AccountAggregate; - -/** - * This is the class that implements account create event. - * Holds the necessary info for an account create event. - * Implements the process function that finds the event related - * domain objects and calls the related domain object's handle event functions - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class AccountCreateEvent extends DomainEvent { - - private final int accountNo; - private final String owner; - - /** - * Instantiates a new Account create event. - * - * @param sequenceId the sequence id - * @param createdTime the created time - * @param accountNo the account no - * @param owner the owner - */ - public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) { - super(sequenceId, createdTime, "AccountCreateEvent"); - this.accountNo = accountNo; - this.owner = owner; - } - - /** - * Gets account no. - * - * @return the account no - */ - public int getAccountNo() { - return accountNo; - } - - /** - * Gets owner. - * - * @return the owner - */ - public String getOwner() { - return owner; - } - - @Override - public void process() { - Account account = AccountAggregate.getAccount(accountNo); - if (account != null) { - throw new RuntimeException("Account already exists"); - } - account = new Account(accountNo, owner); - account.handleEvent(this); - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java deleted file mode 100644 index fa6539a4fba2..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java +++ /dev/null @@ -1,101 +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.event.sourcing.event; - -import java.io.Serializable; - -/** - * This is the base class for domain events. All events must extend this class. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public abstract class DomainEvent implements Serializable { - - private final long sequenceId; - private final long createdTime; - private final String eventClassName; - private boolean realTime = true; - - /** - * Instantiates a new Domain event. - * - * @param sequenceId the sequence id - * @param createdTime the created time - * @param eventClassName the event class name - */ - public DomainEvent(long sequenceId, long createdTime, String eventClassName) { - this.sequenceId = sequenceId; - this.createdTime = createdTime; - this.eventClassName = eventClassName; - } - - /** - * Gets sequence id. - * - * @return the sequence id - */ - public long getSequenceId() { - return sequenceId; - } - - /** - * Gets created time. - * - * @return the created time - */ - public long getCreatedTime() { - return createdTime; - } - - /** - * Is real time boolean. - * - * @return the boolean - */ - public boolean isRealTime() { - return realTime; - } - - /** - * Sets real time. - * - * @param realTime the real time - */ - public void setRealTime(boolean realTime) { - this.realTime = realTime; - } - - /** - * Process. - */ - public abstract void process(); - - /** - * Gets event class name. - * - * @return the event class name - */ - public String getEventClassName() { - return eventClassName; - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java deleted file mode 100644 index 1629263a7ec6..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java +++ /dev/null @@ -1,82 +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.event.sourcing.event; - -import com.iluwatar.event.sourcing.domain.Account; -import com.iluwatar.event.sourcing.state.AccountAggregate; -import java.math.BigDecimal; - -/** - * This is the class that implements money deposit event. - * Holds the necessary info for a money deposit event. - * Implements the process function that finds the event related - * domain objects and calls the related domain object's handle event functions - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class MoneyDepositEvent extends DomainEvent { - - private final BigDecimal money; - private final int accountNo; - - /** - * Instantiates a new Money deposit event. - * - * @param sequenceId the sequence id - * @param createdTime the created time - * @param accountNo the account no - * @param money the money - */ - public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) { - super(sequenceId, createdTime, "MoneyDepositEvent"); - this.money = money; - this.accountNo = accountNo; - } - - /** - * Gets money. - * - * @return the money - */ - public BigDecimal getMoney() { - return money; - } - - /** - * Gets account no. - * - * @return the account no - */ - public int getAccountNo() { - return accountNo; - } - - @Override - public void process() { - Account account = AccountAggregate.getAccount(accountNo); - if (account == null) { - throw new RuntimeException("Account not found"); - } - account.handleEvent(this); - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java deleted file mode 100644 index 0307d3af712f..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java +++ /dev/null @@ -1,101 +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.event.sourcing.event; - -import com.iluwatar.event.sourcing.domain.Account; -import com.iluwatar.event.sourcing.state.AccountAggregate; -import java.math.BigDecimal; - -/** - * This is the class that implements money transfer event. - * Holds the necessary info for a money transfer event. - * Implements the process function that finds the event related - * domain objects and calls the related domain object's handle event functions - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class MoneyTransferEvent extends DomainEvent { - - private final BigDecimal money; - private final int accountNoFrom; - private final int accountNoTo; - - /** - * Instantiates a new Money transfer event. - * - * @param sequenceId the sequence id - * @param createdTime the created time - * @param money the money - * @param accountNoFrom the account no from - * @param accountNoTo the account no to - */ - public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom, - int accountNoTo) { - super(sequenceId, createdTime, "MoneyTransferEvent"); - this.money = money; - this.accountNoFrom = accountNoFrom; - this.accountNoTo = accountNoTo; - } - - /** - * Gets money. - * - * @return the money - */ - public BigDecimal getMoney() { - return money; - } - - /** - * Gets account no which the money comes from. - * - * @return the account no from - */ - public int getAccountNoFrom() { - return accountNoFrom; - } - - /** - * Gets account no which the money goes to. - * - * @return the account no to - */ - public int getAccountNoTo() { - return accountNoTo; - } - - @Override - public void process() { - Account accountFrom = AccountAggregate.getAccount(accountNoFrom); - if (accountFrom == null) { - throw new RuntimeException("Account not found " + accountNoFrom); - } - Account accountTo = AccountAggregate.getAccount(accountNoTo); - if (accountTo == null) { - throw new RuntimeException("Account not found" + accountTo); - } - - accountFrom.handleTransferFromEvent(this); - accountTo.handleTransferToEvent(this); - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java deleted file mode 100644 index 05308c7c1f3a..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java +++ /dev/null @@ -1,69 +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.event.sourcing.processor; - -import com.iluwatar.event.sourcing.event.DomainEvent; - -/** - * This is the implementation of event processor. - * All events are processed by this class. - * This processor uses processorJournal to persist and recover events. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class DomainEventProcessor { - - private final JsonFileJournal processorJournal = new JsonFileJournal(); - - /** - * Process. - * - * @param domainEvent the domain event - */ - public void process(DomainEvent domainEvent) { - domainEvent.process(); - processorJournal.write(domainEvent); - } - - /** - * Reset. - */ - public void reset() { - processorJournal.reset(); - } - - /** - * Recover. - */ - public void recover() { - DomainEvent domainEvent; - while (true) { - domainEvent = processorJournal.readNext(); - if (domainEvent == null) { - break; - } else { - domainEvent.process(); - } - } - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java deleted file mode 100644 index 870d8d00ffe3..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java +++ /dev/null @@ -1,144 +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.event.sourcing.processor; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.iluwatar.event.sourcing.event.AccountCreateEvent; -import com.iluwatar.event.sourcing.event.DomainEvent; -import com.iluwatar.event.sourcing.event.MoneyDepositEvent; -import com.iluwatar.event.sourcing.event.MoneyTransferEvent; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; - -/** - * This is the implementation of event journal. - * This implementation serialize/deserialize the events with JSON - * and writes/reads them on a Journal.json file at the working directory. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class JsonFileJournal { - - private final File aFile; - private final List events = new ArrayList<>(); - private int index = 0; - - /** - * Instantiates a new Json file journal. - */ - public JsonFileJournal() { - aFile = new File("Journal.json"); - if (aFile.exists()) { - try (BufferedReader input = new BufferedReader( - new InputStreamReader(new FileInputStream(aFile), "UTF-8"))) { - String line; - while ((line = input.readLine()) != null) { - events.add(line); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } else { - reset(); - } - } - - - /** - * Write. - * - * @param domainEvent the domain event - */ - public void write(DomainEvent domainEvent) { - Gson gson = new Gson(); - JsonElement jsonElement; - if (domainEvent instanceof AccountCreateEvent) { - jsonElement = gson.toJsonTree(domainEvent, AccountCreateEvent.class); - } else if (domainEvent instanceof MoneyDepositEvent) { - jsonElement = gson.toJsonTree(domainEvent, MoneyDepositEvent.class); - } else if (domainEvent instanceof MoneyTransferEvent) { - jsonElement = gson.toJsonTree(domainEvent, MoneyTransferEvent.class); - } else { - throw new RuntimeException("Journal Event not recegnized"); - } - - try (Writer output = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(aFile, true), "UTF-8"))) { - String eventString = jsonElement.toString(); - output.write(eventString + "\r\n"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - - /** - * Reset. - */ - public void reset() { - aFile.delete(); - } - - - /** - * Read next domain event. - * - * @return the domain event - */ - public DomainEvent readNext() { - if (index >= events.size()) { - return null; - } - String event = events.get(index); - index++; - - JsonParser parser = new JsonParser(); - JsonElement jsonElement = parser.parse(event); - String eventClassName = jsonElement.getAsJsonObject().get("eventClassName").getAsString(); - Gson gson = new Gson(); - DomainEvent domainEvent; - if (eventClassName.equals("AccountCreateEvent")) { - domainEvent = gson.fromJson(jsonElement, AccountCreateEvent.class); - } else if (eventClassName.equals("MoneyDepositEvent")) { - domainEvent = gson.fromJson(jsonElement, MoneyDepositEvent.class); - } else if (eventClassName.equals("MoneyTransferEvent")) { - domainEvent = gson.fromJson(jsonElement, MoneyTransferEvent.class); - } else { - throw new RuntimeException("Journal Event not recegnized"); - } - - domainEvent.setRealTime(false); - return domainEvent; - } -} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java deleted file mode 100644 index 2d957268ec9e..000000000000 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java +++ /dev/null @@ -1,71 +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.event.sourcing.state; - -import com.iluwatar.event.sourcing.domain.Account; -import java.util.HashMap; -import java.util.Map; - -/** - * This is the static accounts map holder class. - * This class holds the state of the accounts. - * - * Created by Serdar Hamzaogullari on 06.08.2017. - */ -public class AccountAggregate { - - private static Map accounts = new HashMap<>(); - - private AccountAggregate() { - } - - /** - * Put account. - * - * @param account the account - */ - public static void putAccount(Account account) { - accounts.put(account.getAccountNo(), account); - } - - /** - * Gets account. - * - * @param accountNo the account no - * @return the copy of the account or null if not found - */ - public static Account getAccount(int accountNo) { - Account account = accounts.get(accountNo); - if (account == null) { - return null; - } - return account.copy(); - } - - /** - * Reset state. - */ - public static void resetState() { - accounts = new HashMap<>(); - } -} diff --git a/event-sourcing/src/test/java/IntegrationTest.java b/event-sourcing/src/test/java/IntegrationTest.java deleted file mode 100644 index 5a3f5718aa9c..000000000000 --- a/event-sourcing/src/test/java/IntegrationTest.java +++ /dev/null @@ -1,99 +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. - */ - -import static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_DAENERYS; -import static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_JON; - -import com.iluwatar.event.sourcing.domain.Account; -import com.iluwatar.event.sourcing.event.AccountCreateEvent; -import com.iluwatar.event.sourcing.event.MoneyDepositEvent; -import com.iluwatar.event.sourcing.event.MoneyTransferEvent; -import com.iluwatar.event.sourcing.processor.DomainEventProcessor; -import com.iluwatar.event.sourcing.state.AccountAggregate; -import java.math.BigDecimal; -import java.util.Date; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Intergartion Test for Event Sourcing state recovery - * - * Created by Serdar Hamzaogullari on 19.08.2017. - */ -public class IntegrationTest { - - /** - * The Domain event processor. - */ - private DomainEventProcessor eventProcessor; - - /** - * Initialize. - */ - @Before - public void initialize() { - eventProcessor = new DomainEventProcessor(); - } - - /** - * Test state recovery. - */ - @Test - public void testStateRecovery() { - eventProcessor.reset(); - - eventProcessor.process(new AccountCreateEvent( - 0, new Date().getTime(), ACCOUNT_OF_DAENERYS, "Daenerys Targaryen")); - - eventProcessor.process(new AccountCreateEvent( - 1, new Date().getTime(), ACCOUNT_OF_JON, "Jon Snow")); - - eventProcessor.process(new MoneyDepositEvent( - 2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal("100000"))); - - eventProcessor.process(new MoneyDepositEvent( - 3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal("100"))); - - eventProcessor.process(new MoneyTransferEvent( - 4, new Date().getTime(), new BigDecimal("10000"), ACCOUNT_OF_DAENERYS, - ACCOUNT_OF_JON)); - - Account accountOfDaenerysBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS); - Account accountOfJonBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON); - - AccountAggregate.resetState(); - - eventProcessor = new DomainEventProcessor(); - eventProcessor.recover(); - - Account accountOfDaenerysAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS); - Account accountOfJonAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON); - - Assert.assertEquals(accountOfDaenerysBeforeShotDown.getMoney(), - accountOfDaenerysAfterShotDown.getMoney()); - Assert - .assertEquals(accountOfJonBeforeShotDown.getMoney(), accountOfJonAfterShotDown.getMoney()); - } - -} \ No newline at end of file diff --git a/exclude-pmd.properties b/exclude-pmd.properties deleted file mode 100644 index 288ee9b2d318..000000000000 --- a/exclude-pmd.properties +++ /dev/null @@ -1,26 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -com.iluwatar.servicelayer.common.BaseEntity=UnusedPrivateField -com.iluwatar.doublechecked.locking.App=EmptyStatementNotInLoop,EmptyWhileStmt -com.iluwatar.doublechecked.locking.InventoryTest=EmptyStatementNotInLoop,EmptyWhileStmt diff --git a/execute-around/README.md b/execute-around/README.md deleted file mode 100644 index e0ae128b537f..000000000000 --- a/execute-around/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: pattern -title: Execute Around -folder: execute-around -permalink: /patterns/execute-around/ -pumlid: NSZ14G8n20NGLhI0XBlT865suoGa0n_NylNixSsxTvEHJTF7xGHsF8YShtfqdFdCK9TbK4ELDQcFl1ZizE8tbwRH3okR0NKBcXm_a7vK4bhOLreZXVnLJPzrvnnV -categories: Other -tags: - - Java - - Difficulty-Beginner - - Idiom ---- - -## Intent -Execute Around idiom frees the user from certain actions that -should always be executed before and after the business method. A good example -of this is resource allocation and deallocation leaving the user to specify -only what to do with the resource. - -![alt text](./etc/execute-around.png "Execute Around") - -## Applicability -Use the Execute Around idiom when - -* you use an API that requires methods to be called in pairs such as open/close or allocate/deallocate. - -## Credits -* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1) diff --git a/execute-around/etc/execute-around.png b/execute-around/etc/execute-around.png deleted file mode 100644 index fc048919d10e1c024c38dc2ad93d95cba20b9a59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4588 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 F{sUz; - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/execute-around/etc/execute-around.urm.puml b/execute-around/etc/execute-around.urm.puml deleted file mode 100644 index fd01a5fe1fe9..000000000000 --- a/execute-around/etc/execute-around.urm.puml +++ /dev/null @@ -1,14 +0,0 @@ -@startuml -package com.iluwatar.execute.around { - class App { - + App() - + main(args : String[]) {static} - } - interface FileWriterAction { - + writeFile(FileWriter) {abstract} - } - class SimpleFileWriter { - + SimpleFileWriter(filename : String, action : FileWriterAction) - } -} -@enduml \ No newline at end of file diff --git a/execute-around/pom.xml b/execute-around/pom.xml deleted file mode 100644 index 3da4dc440bcd..000000000000 --- a/execute-around/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - execute-around - - - junit - junit - test - - - diff --git a/execute-around/src/main/java/com/iluwatar/execute/around/App.java b/execute-around/src/main/java/com/iluwatar/execute/around/App.java deleted file mode 100644 index 11775462af18..000000000000 --- a/execute-around/src/main/java/com/iluwatar/execute/around/App.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.execute.around; - -import java.io.FileWriter; -import java.io.IOException; - -/** - * The Execute Around idiom specifies some code to be executed before and after a method. Typically - * the idiom is used when the API has methods to be executed in pairs, such as resource - * allocation/deallocation or lock acquisition/release. - *

    - * In this example, we have {@link SimpleFileWriter} class that opens and closes the file for the - * user. The user specifies only what to do with the file by providing the {@link FileWriterAction} - * implementation. - * - */ -public class App { - - /** - * Program entry point - */ - public static void main(String[] args) throws IOException { - - new SimpleFileWriter("testfile.txt", new FileWriterAction() { - - @Override - public void writeFile(FileWriter writer) throws IOException { - writer.write("Hello"); - writer.append(" "); - writer.append("there!"); - } - }); - } -} diff --git a/execute-around/src/main/java/com/iluwatar/execute/around/FileWriterAction.java b/execute-around/src/main/java/com/iluwatar/execute/around/FileWriterAction.java deleted file mode 100644 index 83670c361d38..000000000000 --- a/execute-around/src/main/java/com/iluwatar/execute/around/FileWriterAction.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.execute.around; - -import java.io.FileWriter; -import java.io.IOException; - -/** - * - * Interface for specifying what to do with the file resource. - * - */ -public interface FileWriterAction { - - void writeFile(FileWriter writer) throws IOException; - -} diff --git a/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java b/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java deleted file mode 100644 index 3c98597cb7da..000000000000 --- a/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.execute.around; - -import java.io.FileWriter; -import java.io.IOException; - -/** - * - * SimpleFileWriter handles opening and closing file for the user. The user only has to specify what - * to do with the file resource through {@link FileWriterAction} parameter. - * - */ -public class SimpleFileWriter { - - /** - * Constructor - */ - public SimpleFileWriter(String filename, FileWriterAction action) throws IOException { - FileWriter writer = new FileWriter(filename); - try { - action.writeFile(writer); - } finally { - writer.close(); - } - } -} diff --git a/execute-around/src/test/java/com/iluwatar/execute/around/AppTest.java b/execute-around/src/test/java/com/iluwatar/execute/around/AppTest.java deleted file mode 100644 index 7604db16d1b5..000000000000 --- a/execute-around/src/test/java/com/iluwatar/execute/around/AppTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.execute.around; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -/** - * - * Tests execute-around example. - * - */ -public class AppTest { - - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } - - @Before - @After - public void cleanup() { - File file = new File("testfile.txt"); - file.delete(); - } -} diff --git a/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java b/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java deleted file mode 100644 index fd13a92a90e7..000000000000 --- a/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.execute.around; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/12/15 - 3:21 PM - * - * @author Jeroen Meulemeester - */ -public class SimpleFileWriterTest { - - /** - * Create a temporary folder, used to generate files in during this test - */ - @Rule - public final TemporaryFolder testFolder = new TemporaryFolder(); - - /** - * Verify if the given writer is not 'null' - */ - @Test - public void testWriterNotNull() throws Exception { - final File temporaryFile = this.testFolder.newFile(); - new SimpleFileWriter(temporaryFile.getPath(), Assert::assertNotNull); - } - - /** - * Test if the {@link SimpleFileWriter} creates a file if it doesn't exist - */ - @Test - public void testNonExistentFile() throws Exception { - final File nonExistingFile = new File(this.testFolder.getRoot(), "non-existing-file"); - assertFalse(nonExistingFile.exists()); - - new SimpleFileWriter(nonExistingFile.getPath(), Assert::assertNotNull); - assertTrue(nonExistingFile.exists()); - } - - /** - * Test if the data written to the file writer actually gets in the file - */ - @Test - public void testActualWrite() throws Exception { - final String testMessage = "Test message"; - - final File temporaryFile = this.testFolder.newFile(); - assertTrue(temporaryFile.exists()); - - new SimpleFileWriter(temporaryFile.getPath(), writer -> writer.write(testMessage)); - assertTrue(Files.lines(temporaryFile.toPath()).allMatch(testMessage::equals)); - } - - /** - * Verify if an {@link IOException} during the write ripples through - */ - @Test(expected = IOException.class) - public void testIoException() throws Exception { - final File temporaryFile = this.testFolder.newFile(); - new SimpleFileWriter(temporaryFile.getPath(), writer -> { - throw new IOException(""); - }); - } - -} diff --git a/extension-objects/README.md b/extension-objects/README.md deleted file mode 100644 index 9b5c93a2200d..000000000000 --- a/extension-objects/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: pattern -title: Extension objects -folder: extension-objects -permalink: /patterns/extension-objects/ -categories: Behavioral -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Anticipate that an object’s interface needs to be extended in the future. Additional -interfaces are defined by extension objects. - -![Extension_objects](./etc/extension_obj.png "Extension objects") - -## Applicability -Use the Extension Objects pattern when: - -* you need to support the addition of new or unforeseen interfaces to existing classes and you don't want to impact clients that don't need this new interface. Extension Objects lets you keep related operations together by defining them in a separate class -* a class representing a key abstraction plays different roles for different clients. The number of roles the class can play should be open-ended. There is a need to preserve the key abstraction itself. For example, a customer object is still a customer object even if different subsystems view it differently. -* a class should be extensible with new behavior without subclassing from it. - -## Real world examples - -* [OpenDoc](https://en.wikipedia.org/wiki/OpenDoc) -* [Object Linking and Embedding](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding) diff --git a/extension-objects/etc/extension-objects.urm.puml b/extension-objects/etc/extension-objects.urm.puml deleted file mode 100644 index 02af47ddf261..000000000000 --- a/extension-objects/etc/extension-objects.urm.puml +++ /dev/null @@ -1,2 +0,0 @@ -@startuml -@enduml \ No newline at end of file diff --git a/extension-objects/etc/extension_obj.png b/extension-objects/etc/extension_obj.png deleted file mode 100644 index a2b750e9deddee833ccbea50b0d789390060e986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38018 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 T5LYt!3F3OX`njxgN@xNAEupb; diff --git a/extension-objects/etc/extension_obj.ucls b/extension-objects/etc/extension_obj.ucls deleted file mode 100644 index 9471caa83dad..000000000000 --- a/extension-objects/etc/extension_obj.ucls +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml deleted file mode 100644 index 2215834d79f1..000000000000 --- a/extension-objects/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - extension-objects - - - junit - junit - test - - - - diff --git a/extension-objects/src/main/java/App.java b/extension-objects/src/main/java/App.java deleted file mode 100644 index 0fcc548dc04c..000000000000 --- a/extension-objects/src/main/java/App.java +++ /dev/null @@ -1,84 +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. - */ -import abstractextensions.CommanderExtension; -import abstractextensions.SergeantExtension; -import abstractextensions.SoldierExtension; -import units.CommanderUnit; -import units.SergeantUnit; -import units.SoldierUnit; -import units.Unit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Anticipate that an object’s interface needs to be extended in the future. - * Additional interfaces are defined by extension objects. - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - //Create 3 different units - Unit soldierUnit = new SoldierUnit("SoldierUnit1"); - Unit sergeantUnit = new SergeantUnit("SergeantUnit1"); - Unit commanderUnit = new CommanderUnit("CommanderUnit1"); - - //check for each unit to have an extension - checkExtensionsForUnit(soldierUnit); - checkExtensionsForUnit(sergeantUnit); - checkExtensionsForUnit(commanderUnit); - - } - - private static void checkExtensionsForUnit(Unit unit) { - final Logger logger = LoggerFactory.getLogger(App.class); - - SoldierExtension soldierExtension = (SoldierExtension) unit.getUnitExtension("SoldierExtension"); - SergeantExtension sergeantExtension = (SergeantExtension) unit.getUnitExtension("SergeantExtension"); - CommanderExtension commanderExtension = (CommanderExtension) unit.getUnitExtension("CommanderExtension"); - - //if unit have extension call the method - if (soldierExtension != null) { - soldierExtension.soldierReady(); - } else { - logger.info(unit.getName() + " without SoldierExtension"); - } - - if (sergeantExtension != null) { - sergeantExtension.sergeantReady(); - } else { - logger.info(unit.getName() + " without SergeantExtension"); - } - - if (commanderExtension != null) { - commanderExtension.commanderReady(); - } else { - logger.info(unit.getName() + " without CommanderExtension"); - } - } -} diff --git a/extension-objects/src/main/java/abstractextensions/CommanderExtension.java b/extension-objects/src/main/java/abstractextensions/CommanderExtension.java deleted file mode 100644 index 66dd3a25e5b5..000000000000 --- a/extension-objects/src/main/java/abstractextensions/CommanderExtension.java +++ /dev/null @@ -1,31 +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 abstractextensions; - -/** - * Interface with their method - */ -public interface CommanderExtension extends UnitExtension { - - void commanderReady(); -} diff --git a/extension-objects/src/main/java/abstractextensions/SergeantExtension.java b/extension-objects/src/main/java/abstractextensions/SergeantExtension.java deleted file mode 100644 index 8df30c63e776..000000000000 --- a/extension-objects/src/main/java/abstractextensions/SergeantExtension.java +++ /dev/null @@ -1,31 +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 abstractextensions; - -/** - * Interface with their method - */ -public interface SergeantExtension extends UnitExtension { - - void sergeantReady(); -} diff --git a/extension-objects/src/main/java/abstractextensions/SoldierExtension.java b/extension-objects/src/main/java/abstractextensions/SoldierExtension.java deleted file mode 100644 index 9296b620474e..000000000000 --- a/extension-objects/src/main/java/abstractextensions/SoldierExtension.java +++ /dev/null @@ -1,30 +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 abstractextensions; - -/** - * Interface with their method - */ -public interface SoldierExtension extends UnitExtension { - void soldierReady(); -} diff --git a/extension-objects/src/main/java/abstractextensions/UnitExtension.java b/extension-objects/src/main/java/abstractextensions/UnitExtension.java deleted file mode 100644 index b3b3bf7fad1d..000000000000 --- a/extension-objects/src/main/java/abstractextensions/UnitExtension.java +++ /dev/null @@ -1,29 +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 abstractextensions; - -/** - * Other Extensions will extend this interface - */ -public interface UnitExtension { -} diff --git a/extension-objects/src/main/java/concreteextensions/Commander.java b/extension-objects/src/main/java/concreteextensions/Commander.java deleted file mode 100644 index 8094d2887ab9..000000000000 --- a/extension-objects/src/main/java/concreteextensions/Commander.java +++ /dev/null @@ -1,47 +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 concreteextensions; - -import abstractextensions.CommanderExtension; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import units.CommanderUnit; - -/** - * Class defining Commander - */ -public class Commander implements CommanderExtension { - - private CommanderUnit unit; - - public Commander(CommanderUnit commanderUnit) { - this.unit = commanderUnit; - } - - final Logger logger = LoggerFactory.getLogger(Commander.class); - - @Override - public void commanderReady() { - logger.info("[Commander] " + unit.getName() + " is ready!"); - } -} diff --git a/extension-objects/src/main/java/concreteextensions/Sergeant.java b/extension-objects/src/main/java/concreteextensions/Sergeant.java deleted file mode 100644 index 892a3d3728c5..000000000000 --- a/extension-objects/src/main/java/concreteextensions/Sergeant.java +++ /dev/null @@ -1,47 +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 concreteextensions; - -import abstractextensions.SergeantExtension; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import units.SergeantUnit; - -/** - * Class defining Sergeant - */ -public class Sergeant implements SergeantExtension { - - private SergeantUnit unit; - - public Sergeant(SergeantUnit sergeantUnit) { - this.unit = sergeantUnit; - } - - final Logger logger = LoggerFactory.getLogger(Sergeant.class); - - @Override - public void sergeantReady() { - logger.info("[Sergeant] " + unit.getName() + " is ready! "); - } -} diff --git a/extension-objects/src/main/java/concreteextensions/Soldier.java b/extension-objects/src/main/java/concreteextensions/Soldier.java deleted file mode 100644 index 79db74d6cf29..000000000000 --- a/extension-objects/src/main/java/concreteextensions/Soldier.java +++ /dev/null @@ -1,47 +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 concreteextensions; - -import abstractextensions.SoldierExtension; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import units.SoldierUnit; - -/** - * Class defining Soldier - */ -public class Soldier implements SoldierExtension { - - private SoldierUnit unit; - - public Soldier(SoldierUnit soldierUnit) { - this.unit = soldierUnit; - } - - final Logger logger = LoggerFactory.getLogger(Soldier.class); - - @Override - public void soldierReady() { - logger.info("[Solider] " + unit.getName() + " is ready!"); - } -} diff --git a/extension-objects/src/main/java/units/CommanderUnit.java b/extension-objects/src/main/java/units/CommanderUnit.java deleted file mode 100644 index 61b7a050d67f..000000000000 --- a/extension-objects/src/main/java/units/CommanderUnit.java +++ /dev/null @@ -1,49 +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 units; - -import abstractextensions.UnitExtension; -import concreteextensions.Commander; - -/** - * Class defining CommanderUnit - */ -public class CommanderUnit extends Unit { - - public CommanderUnit(String name) { - super(name); - } - - @Override - public UnitExtension getUnitExtension(String extensionName) { - - if (extensionName.equals("CommanderExtension")) { - if (unitExtension == null) { - unitExtension = new Commander(this); - } - return unitExtension; - } - - return super.getUnitExtension(extensionName); - } -} diff --git a/extension-objects/src/main/java/units/SergeantUnit.java b/extension-objects/src/main/java/units/SergeantUnit.java deleted file mode 100644 index a655abac4c52..000000000000 --- a/extension-objects/src/main/java/units/SergeantUnit.java +++ /dev/null @@ -1,49 +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 units; - -import abstractextensions.UnitExtension; -import concreteextensions.Sergeant; - -/** - * Class defining SergeantUnit - */ -public class SergeantUnit extends Unit { - - public SergeantUnit(String name) { - super(name); - } - - @Override - public UnitExtension getUnitExtension(String extensionName) { - - if (extensionName.equals("SergeantExtension")) { - if (unitExtension == null) { - unitExtension = new Sergeant(this); - } - return unitExtension; - } - - return super.getUnitExtension(extensionName); - } -} diff --git a/extension-objects/src/main/java/units/SoldierUnit.java b/extension-objects/src/main/java/units/SoldierUnit.java deleted file mode 100644 index 03617dd27586..000000000000 --- a/extension-objects/src/main/java/units/SoldierUnit.java +++ /dev/null @@ -1,49 +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 units; - -import abstractextensions.UnitExtension; -import concreteextensions.Soldier; - -/** - * Class defining SoldierUnit - */ -public class SoldierUnit extends Unit { - - public SoldierUnit(String name) { - super(name); - } - - @Override - public UnitExtension getUnitExtension(String extensionName) { - - if (extensionName.equals("SoldierExtension")) { - if (unitExtension == null) { - unitExtension = new Soldier(this); - } - - return unitExtension; - } - return super.getUnitExtension(extensionName); - } -} diff --git a/extension-objects/src/main/java/units/Unit.java b/extension-objects/src/main/java/units/Unit.java deleted file mode 100644 index 1bf251a8e7b5..000000000000 --- a/extension-objects/src/main/java/units/Unit.java +++ /dev/null @@ -1,50 +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 units; - -import abstractextensions.UnitExtension; - -/** - * Class defining Unit, other units will extend this class - */ -public class Unit { - - private String name; - protected UnitExtension unitExtension = null; - - public Unit(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public UnitExtension getUnitExtension(String extensionName) { - return null; - } -} diff --git a/extension-objects/src/test/java/AppTest.java b/extension-objects/src/test/java/AppTest.java deleted file mode 100644 index 4857881129f3..000000000000 --- a/extension-objects/src/test/java/AppTest.java +++ /dev/null @@ -1,36 +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. - */ -import org.junit.Test; - -/** - * Created by Srdjan on 03-May-17. - */ -public class AppTest { - @Test - public void main() throws Exception { - - String[] args = {}; - App.main(args); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/concreteextensions/CommanderTest.java b/extension-objects/src/test/java/concreteextensions/CommanderTest.java deleted file mode 100644 index 11f0cc60ec36..000000000000 --- a/extension-objects/src/test/java/concreteextensions/CommanderTest.java +++ /dev/null @@ -1,39 +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 concreteextensions; - -import org.junit.Test; -import units.CommanderUnit; - -/** - * Created by Srdjan on 03-May-17. - */ -public class CommanderTest { - @Test - public void commanderReady() throws Exception { - final Commander commander = new Commander(new CommanderUnit("CommanderUnitTest")); - - commander.commanderReady(); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/concreteextensions/SergeantTest.java b/extension-objects/src/test/java/concreteextensions/SergeantTest.java deleted file mode 100644 index 2deddca90d33..000000000000 --- a/extension-objects/src/test/java/concreteextensions/SergeantTest.java +++ /dev/null @@ -1,39 +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 concreteextensions; - -import org.junit.Test; -import units.SergeantUnit; - -/** - * Created by Srdjan on 03-May-17. - */ -public class SergeantTest { - @Test - public void sergeantReady() throws Exception { - final Sergeant sergeant = new Sergeant(new SergeantUnit("SergeantUnitTest")); - - sergeant.sergeantReady(); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/concreteextensions/SoldierTest.java b/extension-objects/src/test/java/concreteextensions/SoldierTest.java deleted file mode 100644 index affc6ee8bab4..000000000000 --- a/extension-objects/src/test/java/concreteextensions/SoldierTest.java +++ /dev/null @@ -1,39 +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 concreteextensions; - -import org.junit.Test; -import units.SoldierUnit; - -/** - * Created by Srdjan on 03-May-17. - */ -public class SoldierTest { - @Test - public void soldierReady() throws Exception { - final Soldier soldier = new Soldier(new SoldierUnit("SoldierUnitTest")); - - soldier.soldierReady(); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/units/CommanderUnitTest.java b/extension-objects/src/test/java/units/CommanderUnitTest.java deleted file mode 100644 index 8f4c1ca8d9fc..000000000000 --- a/extension-objects/src/test/java/units/CommanderUnitTest.java +++ /dev/null @@ -1,45 +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 units; - -import abstractextensions.CommanderExtension; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * Created by Srdjan on 03-May-17. - */ -public class CommanderUnitTest { - @Test - public void getUnitExtension() throws Exception { - - final Unit unit = new CommanderUnit("CommanderUnitName"); - - assertNull(unit.getUnitExtension("SoldierExtension")); - assertNull(unit.getUnitExtension("SergeantExtension")); - assertNotNull((CommanderExtension) unit.getUnitExtension("CommanderExtension")); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/units/SergeantUnitTest.java b/extension-objects/src/test/java/units/SergeantUnitTest.java deleted file mode 100644 index de773b59e839..000000000000 --- a/extension-objects/src/test/java/units/SergeantUnitTest.java +++ /dev/null @@ -1,45 +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 units; - -import abstractextensions.SergeantExtension; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * Created by Srdjan on 03-May-17. - */ -public class SergeantUnitTest { - @Test - public void getUnitExtension() throws Exception { - - final Unit unit = new SergeantUnit("SergeantUnitName"); - - assertNull(unit.getUnitExtension("SoldierExtension")); - assertNotNull((SergeantExtension) unit.getUnitExtension("SergeantExtension")); - assertNull(unit.getUnitExtension("CommanderExtension")); - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/units/SoldierUnitTest.java b/extension-objects/src/test/java/units/SoldierUnitTest.java deleted file mode 100644 index 06a1f7611d3c..000000000000 --- a/extension-objects/src/test/java/units/SoldierUnitTest.java +++ /dev/null @@ -1,47 +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 units; - -import abstractextensions.SoldierExtension; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * Created by Srdjan on 03-May-17. - */ -public class SoldierUnitTest { - @Test - public void getUnitExtension() throws Exception { - - final Unit unit = new SoldierUnit("SoldierUnitName"); - - assertNotNull((SoldierExtension) unit.getUnitExtension("SoldierExtension")); - assertNull(unit.getUnitExtension("SergeantExtension")); - assertNull(unit.getUnitExtension("CommanderExtension")); - - - } - -} \ No newline at end of file diff --git a/extension-objects/src/test/java/units/UnitTest.java b/extension-objects/src/test/java/units/UnitTest.java deleted file mode 100644 index a7d5300326cb..000000000000 --- a/extension-objects/src/test/java/units/UnitTest.java +++ /dev/null @@ -1,52 +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 units; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * Created by Srdjan on 03-May-17. - */ -public class UnitTest { - - @Test - public void testConstGetSet() throws Exception { - final String name = "testName"; - final Unit unit = new Unit(name); - assertEquals(name, unit.getName()); - - final String newName = "newName"; - unit.setName(newName); - assertEquals(newName, unit.getName()); - - - assertNull(unit.getUnitExtension("")); - assertNull(unit.getUnitExtension("SoldierExtension")); - assertNull(unit.getUnitExtension("SergeantExtension")); - assertNull(unit.getUnitExtension("CommanderExtension")); - } - -} \ No newline at end of file diff --git a/factory-kit/README.md b/factory-kit/README.md deleted file mode 100644 index b47cbff76ba4..000000000000 --- a/factory-kit/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Factory Kit -folder: factory-kit -permalink: /patterns/factory-kit/ -pumlid: JST15i8m20N0g-W14lRU1YcsQ4BooCS-RwzBTpDNSscvQKQx7C1SDwBWi-w68--vD6Gur55bTBAM9uE3dlpcikcotSjaGCCNTLu_q8C58pxbPI25_Bzcz3gpjoy0 -categories: Creational -tags: - - Java - - Difficulty-Beginner - - Functional ---- - -## Intent -Define a factory of immutable content with separated builder and factory interfaces. - -![alt text](./etc/factory-kit.png "Factory Kit") - -## Applicability -Use the Factory Kit pattern when - -* a class can't anticipate the class of objects it must create -* you just want a new instance of a custom builder instead of the global one -* you explicitly want to define types of objects, that factory can build -* you want a separated builder and creator interface - -## Credits - -* [Design Pattern Reloaded by Remi Forax: ](https://www.youtube.com/watch?v=-k2X7guaArU) diff --git a/factory-kit/etc/factory-kit.png b/factory-kit/etc/factory-kit.png deleted file mode 100644 index 7093193cb8d0256d1b6bad2434363135cb58710d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37570 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 a(XB - - - - - - - \ No newline at end of file diff --git a/factory-kit/etc/factory-kit.urm.puml b/factory-kit/etc/factory-kit.urm.puml deleted file mode 100644 index 23cf658f467e..000000000000 --- a/factory-kit/etc/factory-kit.urm.puml +++ /dev/null @@ -1,46 +0,0 @@ -@startuml -package com.iluwatar.factorykit { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Axe { - + Axe() - + toString() : String - } - class Bow { - + Bow() - + toString() : String - } - interface Builder { - + add(WeaponType, Supplier) {abstract} - } - class Spear { - + Spear() - + toString() : String - } - class Sword { - + Sword() - + toString() : String - } - interface Weapon { - } - interface WeaponFactory { - + create(WeaponType) : Weapon {abstract} - + factory(consumer : Consumer) : WeaponFactory {static} - } - enum WeaponType { - + AXE {static} - + BOW {static} - + SPEAR {static} - + SWORD {static} - + valueOf(name : String) : WeaponType {static} - + values() : WeaponType[] {static} - } -} -Axe ..|> Weapon -Bow ..|> Weapon -Spear ..|> Weapon -Sword ..|> Weapon -@enduml \ No newline at end of file diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml deleted file mode 100644 index eee0cd7348eb..000000000000 --- a/factory-kit/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - factory-kit - - - junit - junit - test - - - org.mockito - mockito-core - test - - - \ No newline at end of file diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java deleted file mode 100644 index 03a4ece83897..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * creating one of the objects specified directly in the factory-kit instance. - * - *

    - * In the given example {@link WeaponFactory} represents the factory-kit, that contains - * four {@link Builder}s for creating new objects of - * the classes implementing {@link Weapon} interface. - *
    Each of them can be called with {@link WeaponFactory#create(WeaponType)} method, with - * an input representing an instance of {@link WeaponType} that needs to - * 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. - * - * @param args @param args command line args - */ - public static void main(String[] args) { - WeaponFactory factory = WeaponFactory.factory(builder -> { - builder.add(WeaponType.SWORD, Sword::new); - builder.add(WeaponType.AXE, Axe::new); - builder.add(WeaponType.SPEAR, Spear::new); - builder.add(WeaponType.BOW, Bow::new); - }); - Weapon axe = factory.create(WeaponType.AXE); - LOGGER.info(axe.toString()); - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java deleted file mode 100644 index 429728cbc721..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -/** - * Class representing Axe - */ -public class Axe implements Weapon { - @Override - public String toString() { - return "Axe"; - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java deleted file mode 100644 index c655c3be851a..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -/** - * Class representing Bows - */ -public class Bow implements Weapon { - @Override - public String toString() { - return "Bow"; - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java deleted file mode 100644 index 8426c36a5a84..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -import java.util.function.Supplier; - -/** - * Functional interface that allows adding builder with name to the factory. - */ -public interface Builder { - void add(WeaponType name, Supplier supplier); -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java deleted file mode 100644 index 15ff8b246283..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; -/** - * Class representing Spear - */ -public class Spear implements Weapon { - @Override - public String toString() { - return "Spear"; - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java deleted file mode 100644 index 42ab5379992b..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; -/** - * Class representing Swords - */ -public class Sword implements Weapon { - @Override - public String toString() { - return "Sword"; - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java deleted file mode 100644 index cf6a140dcd55..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -/** - * Interface representing weapon. - */ -public interface Weapon { -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java deleted file mode 100644 index 8ee9c6c399f7..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * Functional interface, an example of the factory-kit design pattern. - *
    Instance created locally gives an opportunity to strictly define - * which objects types the instance of a factory will be able to create. - *
    Factory is a placeholder for {@link Builder}s - * with {@link WeaponFactory#create(WeaponType)} method to initialize new objects. - */ -public interface WeaponFactory { - - /** - * Creates an instance of the given type. - * @param name representing enum of an object type to be created. - * @return new instance of a requested class implementing {@link Weapon} interface. - */ - Weapon create(WeaponType name); - - /** - * Creates factory - placeholder for specified {@link Builder}s. - * @param consumer for the new builder to the factory. - * @return factory with specified {@link Builder}s - */ - static WeaponFactory factory(Consumer consumer) { - Map> map = new HashMap<>(); - consumer.accept(map::put); - return name -> map.get(name).get(); - } -} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java deleted file mode 100644 index 3f0520190115..000000000000 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit; - -/** - * Enumerates {@link Weapon} types - */ -public enum WeaponType { - SWORD, AXE, BOW, SPEAR -} diff --git a/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java b/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java deleted file mode 100644 index 4d8691ef043f..000000000000 --- a/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit.app; - -import com.iluwatar.factorykit.App; -import org.junit.Test; - -/** - * Application Test Entrypoint - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} - diff --git a/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java b/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java deleted file mode 100644 index 3f732546d54d..000000000000 --- a/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java +++ /dev/null @@ -1,88 +0,0 @@ - /** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factorykit.factorykit; - -import static org.junit.Assert.assertTrue; - -import com.iluwatar.factorykit.Axe; -import com.iluwatar.factorykit.Spear; -import com.iluwatar.factorykit.Sword; -import com.iluwatar.factorykit.Weapon; -import com.iluwatar.factorykit.WeaponFactory; -import com.iluwatar.factorykit.WeaponType; -import org.junit.Before; -import org.junit.Test; -/** - * Test Factory Kit Pattern - */ -public class FactoryKitTest { - - private WeaponFactory factory; - - @Before - public void init() { - factory = WeaponFactory.factory(builder -> { - builder.add(WeaponType.SPEAR, Spear::new); - builder.add(WeaponType.AXE, Axe::new); - builder.add(WeaponType.SWORD, Sword::new); - }); - } - - /** - * Testing {@link WeaponFactory} to produce a SPEAR asserting that the Weapon is an instance of {@link Spear} - */ - @Test - public void testSpearWeapon() { - Weapon weapon = factory.create(WeaponType.SPEAR); - verifyWeapon(weapon, Spear.class); - } - - /** - * Testing {@link WeaponFactory} to produce a AXE asserting that the Weapon is an instance of {@link Axe} - */ - @Test - public void testAxeWeapon() { - Weapon weapon = factory.create(WeaponType.AXE); - verifyWeapon(weapon, Axe.class); - } - - - /** - * Testing {@link WeaponFactory} to produce a SWORD asserting that the Weapon is an instance of {@link Sword} - */ - @Test - public void testWeapon() { - Weapon weapon = factory.create(WeaponType.SWORD); - verifyWeapon(weapon, Sword.class); - } - - /** - * This method asserts that the weapon object that is passed is an instance of the clazz - * - * @param weapon weapon object which is to be verified - * @param clazz expected class of the weapon - */ - private void verifyWeapon(Weapon weapon, Class clazz) { - assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon)); - } -} diff --git a/factory-method/.gitignore b/factory-method/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/factory-method/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/factory-method/README.md b/factory-method/README.md deleted file mode 100644 index 07c92d0e5db3..000000000000 --- a/factory-method/README.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -layout: pattern -title: Factory Method -folder: factory-method -permalink: /patterns/factory-method/ -pumlid: NSZB3G8n30N0Lg20n7UwCOxPP9MVx6TMT0zdRgEvjoazYeRrMmMsFuYChtmqr7Y6gycQq8aiQr3hSJ7OwEGtfwBUZfas0shJQR3_G2yMBFkaeQYha4B-AeUDl6FqBm00 -categories: Creational -tags: - - Java - - Difficulty-Beginner - - Gang Of Four ---- - -## Also known as -Virtual Constructor - -## Intent -Define an interface for creating an object, but let subclasses -decide which class to instantiate. Factory Method lets a class defer -instantiation to subclasses. - -## Explanation -Real world example - -> Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons. Depending on the customer at hand the right type of blacksmith is summoned. - -In plain words - -> It provides a way to delegate the instantiation logic to child classes. - -Wikipedia says - -> In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor. - - **Programmatic Example** - -Taking our blacksmith example above. First of all we have a blacksmith interface and some implementations for it - -``` -public interface Blacksmith { - Weapon manufactureWeapon(WeaponType weaponType); -} - -public class ElfBlacksmith implements Blacksmith { - public Weapon manufactureWeapon(WeaponType weaponType) { - return new ElfWeapon(weaponType); - } -} - -public class OrcBlacksmith implements Blacksmith { - public Weapon manufactureWeapon(WeaponType weaponType) { - return new OrcWeapon(weaponType); - } -} -``` - -Now as the customers come the correct type of blacksmith is summoned and requested weapons are manufactured - -``` -Blacksmith blacksmith = new ElfBlacksmith(); -blacksmith.manufactureWeapon(WeaponType.SPEAR); -blacksmith.manufactureWeapon(WeaponType.AXE); -// Elvish weapons are created -``` - -## Applicability -Use the Factory Method pattern when - -* a class can't anticipate the class of objects it must create -* a class wants its subclasses to specify the objects it creates -* classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate - -## Known uses - -* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--) -* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-) -* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--) -* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-) -* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-) -* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-) -* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/factory-method/pom.xml b/factory-method/pom.xml deleted file mode 100644 index 8c54f63a1a4f..000000000000 --- a/factory-method/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - factory-method - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 3fb1056821ea..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/App.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * problem of creating objects without specifying the exact class of object that will be created. - * This is done by creating objects via calling a factory method either specified in an interface - * and implemented by child classes, or implemented in a base class and optionally overridden by - * derived classes—rather than by calling a constructor. - *

    - * In this Factory Method example we have an interface ({@link Blacksmith}) with a method for - * creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses ( - * {@link OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce objects of - * their liking. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - private final Blacksmith blacksmith; - - /** - * Creates an instance of App which will use blacksmith to manufacture - * the weapons for war. - * App is unaware which concrete implementation of {@link Blacksmith} it is using. - * The decision of which blacksmith implementation to use may depend on configuration, or - * the type of rival in war. - * @param blacksmith a non-null implementation of blacksmith - */ - public App(Blacksmith blacksmith) { - this.blacksmith = blacksmith; - } - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - // Lets go to war with Orc weapons - App app = new App(new OrcBlacksmith()); - app.manufactureWeapons(); - - // Lets go to war with Elf weapons - app = new App(new ElfBlacksmith()); - app.manufactureWeapons(); - } - - private void manufactureWeapons() { - Weapon weapon; - weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); - LOGGER.info(weapon.toString()); - weapon = blacksmith.manufactureWeapon(WeaponType.AXE); - LOGGER.info(weapon.toString()); - } -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/Blacksmith.java b/factory-method/src/main/java/com/iluwatar/factory/method/Blacksmith.java deleted file mode 100644 index e856d467eb6e..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/Blacksmith.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * - * The interface containing method for producing objects. - * - */ -public interface Blacksmith { - - Weapon manufactureWeapon(WeaponType weaponType); - -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java b/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java deleted file mode 100644 index 66938bb1773b..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * - * Concrete subclass for creating new objects. - * - */ -public class ElfBlacksmith implements Blacksmith { - - public Weapon manufactureWeapon(WeaponType weaponType) { - return new ElfWeapon(weaponType); - } - -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java b/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java deleted file mode 100644 index 95771e248b9e..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * ElfWeapon. - */ -public class ElfWeapon implements Weapon { - - private WeaponType weaponType; - - public ElfWeapon(WeaponType weaponType) { - this.weaponType = weaponType; - } - - @Override - public String toString() { - return "Elven " + weaponType; - } - - @Override - public WeaponType getWeaponType() { - return weaponType; - } -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java b/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java deleted file mode 100644 index e2921a4b52cf..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * - * Concrete subclass for creating new objects. - * - */ -public class OrcBlacksmith implements Blacksmith { - - public Weapon manufactureWeapon(WeaponType weaponType) { - return new OrcWeapon(weaponType); - } -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java b/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java deleted file mode 100644 index 59ae0e7dc639..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * OrcWeapon. - */ -public class OrcWeapon implements Weapon { - - private WeaponType weaponType; - - public OrcWeapon(WeaponType weaponType) { - this.weaponType = weaponType; - } - - @Override - public String toString() { - return "Orcish " + weaponType; - } - - @Override - public WeaponType getWeaponType() { - return weaponType; - } -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/Weapon.java b/factory-method/src/main/java/com/iluwatar/factory/method/Weapon.java deleted file mode 100644 index c642622c3313..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/Weapon.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * Weapon interface. - */ -public interface Weapon { - - WeaponType getWeaponType(); - -} diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/WeaponType.java b/factory-method/src/main/java/com/iluwatar/factory/method/WeaponType.java deleted file mode 100644 index 9f5ce18764bb..000000000000 --- a/factory-method/src/main/java/com/iluwatar/factory/method/WeaponType.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -/** - * - * WeaponType enumeration - * - */ -public enum WeaponType { - - SHORT_SWORD("short sword"), SPEAR("spear"), AXE("axe"), UNDEFINED(""); - - private String title; - - WeaponType(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/factory-method/src/test/java/com/iluwatar/factory/method/AppTest.java b/factory-method/src/test/java/com/iluwatar/factory/method/AppTest.java deleted file mode 100644 index 88b40d4fe695..000000000000 --- a/factory-method/src/test/java/com/iluwatar/factory/method/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Factory Method example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java b/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java deleted file mode 100644 index 69736855ca8e..000000000000 --- a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.factory.method; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * The Factory Method is a creational design pattern which uses factory methods to deal with the - * problem of creating objects without specifying the exact class of object that will be created. - * This is done by creating objects via calling a factory method either specified in an interface - * and implemented by child classes, or implemented in a base class and optionally overridden by - * derived classes—rather than by calling a constructor. - * - *

    Factory produces the object of its liking. - * The weapon {@link Weapon} manufactured by the - * blacksmith depends on the kind of factory implementation it is referring to. - *

    - */ -public class FactoryMethodTest { - - /** - * Testing {@link OrcBlacksmith} to produce a SPEAR asserting that the Weapon is an instance - * of {@link OrcWeapon}. - */ - @Test - public void testOrcBlacksmithWithSpear() { - Blacksmith blacksmith = new OrcBlacksmith(); - Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); - verifyWeapon(weapon, WeaponType.SPEAR, OrcWeapon.class); - } - - /** - * Testing {@link OrcBlacksmith} to produce a AXE asserting that the Weapon is an instance - * of {@link OrcWeapon}. - */ - @Test - public void testOrcBlacksmithWithAxe() { - Blacksmith blacksmith = new OrcBlacksmith(); - Weapon weapon = blacksmith.manufactureWeapon(WeaponType.AXE); - verifyWeapon(weapon, WeaponType.AXE, OrcWeapon.class); - } - - /** - * Testing {@link ElfBlacksmith} to produce a SHORT_SWORD asserting that the Weapon is an - * instance of {@link ElfWeapon}. - */ - @Test - public void testElfBlacksmithWithShortSword() { - Blacksmith blacksmith = new ElfBlacksmith(); - Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD); - verifyWeapon(weapon, WeaponType.SHORT_SWORD, ElfWeapon.class); - } - - /** - * Testing {@link ElfBlacksmith} to produce a SPEAR asserting that the Weapon is an instance - * of {@link ElfWeapon}. - */ - @Test - public void testElfBlacksmithWithSpear() { - Blacksmith blacksmith = new ElfBlacksmith(); - Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); - verifyWeapon(weapon, WeaponType.SPEAR, ElfWeapon.class); - } - - /** - * This method asserts that the weapon object that is passed is an instance of the clazz and the - * weapon is of type expectedWeaponType. - * - * @param weapon weapon object which is to be verified - * @param expectedWeaponType expected WeaponType of the weapon - * @param clazz expected class of the weapon - */ - private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class clazz) { - assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon)); - assertEquals("Weapon must be of weaponType: " + expectedWeaponType, expectedWeaponType, - weapon.getWeaponType()); - } -} diff --git a/faq.md b/faq.md deleted file mode 100644 index 01a7e7b7235d..000000000000 --- a/faq.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -layout: page -title: FAQ -permalink: /faq/ -icon: fa-question -page-index: 5 ---- - -### Q1: What is the difference between State and Strategy patterns? {#Q1} - -While the implementation is similar they solve different problems. The State -pattern deals with what state an object is in - it encapsulates state-dependent -behavior. -The Strategy pattern deals with how an object performs a certain task - it -encapsulates an algorithm. - -### Q2: What is the difference between Strategy and Template Method patterns? {#Q2} - -In Template Method the algorithm is chosen at compile time via inheritance. -With Strategy pattern the algorithm is chosen at runtime via composition. - -### Q3: What is the difference between Proxy and Decorator patterns? {#Q3} - -The difference is the intent of the patterns. While Proxy controls access to -the object Decorator is used to add responsibilities to the object. - -### Q4: What is the difference between Chain of Responsibility and Intercepting Filter patterns? {#Q4} - -While the implementations look similar there are differences. The Chain of -Responsibility forms a chain of request processors and the processors are then -executed one by one until the correct processor is found. In Intercepting -Filter the chain is constructed from filters and the whole chain is always -executed. - -### Q5: What is the difference between Visitor and Double Dispatch patterns? {#Q5} - -The Visitor pattern is a means of adding a new operation to existing classes. -Double dispatch is a means of dispatching function calls with respect to two -polymorphic types, rather than a single polymorphic type, which is what -languages like C++ and Java _do not_ support directly. - -### Q6: What are the differences between Flyweight and Object Pool patterns? {#Q6} - -They differ in the way they are used. - -Pooled objects can simultaneously be used by a single "client" only. For that, -a pooled object must be checked out from the pool, then it can be used by a -client, and then the client must return the object back to the pool. Multiple -instances of identical objects may exist, up to the maximal capacity of the -pool. - -In contrast, a Flyweight object is singleton, and it can be used simultaneously -by multiple clients. - -As for concurrent access, pooled objects can be mutable and they usually don't -need to be thread safe, as typically, only one thread is going to use a -specific instance at the same time. Flyweight must either be immutable (the -best option), or implement thread safety. - -As for performance and scalability, pools can become bottlenecks, if all the -pooled objects are in use and more clients need them, threads will become -blocked waiting for available object from the pool. This is not the case with -Flyweight. - -### Q7: What are the differences between FluentInterface and Builder patterns? {#Q7} - -Fluent interfaces are sometimes confused with the Builder pattern, because they share method chaining and a fluent usage. However, fluent interfaces are not primarily used to create shared (mutable) objects, but to configure complex objects without having to respecify the target object on every property change. - -### Q8: What is the difference between java.io.Serialization and Memento pattern? {#Q8} - -Memento is typically used to implement rollback/save-point support. Example we might want to mark the state of an object at a point in time, do some work and then decide to rollback to the previous state. - -On the other hand serialization may be used as a tool to save the state of an object into byte[] and preserving the contents in memory or disk. When someone invokes the memento to revert object's previous state then we can deserialize the information stored and recreate previous state. - -So Memento is a pattern and serialization is a tool that can be used to implement this pattern. Other ways to implement the pattern can be to clone the contents of the object and keep track of those clones. diff --git a/feature-toggle/README.md b/feature-toggle/README.md deleted file mode 100644 index 06d95617807e..000000000000 --- a/feature-toggle/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: pattern -title: Feature Toggle -folder: feature-toggle -permalink: /patterns/feature-toggle/ -pumlid: NSZ14G8X30NGLhG0oDrk8XjPd12OvCTjNy_UthpxiAPvIBhUJc37WyZvgdtWp6U6U5i6CTIs9WtDYy5ER_vmEIH6jx8P4BUWoV43lOIHBWMhTnKIjB-gwRFkdFe5 -categories: Behavioral -tags: - - Java - - Difficulty-Beginner ---- - -## Also known as -Feature Flag - -## Intent -Used to switch code execution paths based on properties or groupings. Allowing new features to be released, tested -and rolled out. Allowing switching back to the older feature quickly if needed. It should be noted that this pattern, -can easily introduce code complexity. There is also cause for concern that the old feature that the toggle is eventually -going to phase out is never removed, causing redundant code smells and increased maintainability. - -![alt text](./etc/feature-toggle.png "Feature Toggle") - -## Applicability -Use the Feature Toggle pattern when - -* Giving different features to different users. -* Rolling out a new feature incrementally. -* Switching between development and production environments. - -## Credits - -* [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html) \ No newline at end of file diff --git a/feature-toggle/etc/feature-toggle.png b/feature-toggle/etc/feature-toggle.png deleted file mode 100644 index 5c118e57e44e86a22a426dcfa9aff8291dc246ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55425 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ⅈ_4h)^X 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 xw7`b``B#ay@U58d!Tbqz^ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/feature-toggle/etc/feature-toggle.urm.puml b/feature-toggle/etc/feature-toggle.urm.puml deleted file mode 100644 index 0febb26319d1..000000000000 --- a/feature-toggle/etc/feature-toggle.urm.puml +++ /dev/null @@ -1,48 +0,0 @@ -@startuml -package com.iluwatar.featuretoggle.pattern { - interface Service { - + getWelcomeMessage(User) : String {abstract} - + isEnhanced() : boolean {abstract} - } -} -package com.iluwatar.featuretoggle.user { - class User { - - name : String - + User(name : String) - + toString() : String - } - class UserGroup { - - freeGroup : List {static} - - paidGroup : List {static} - + UserGroup() - + addUserToFreeGroup(user : User) {static} - + addUserToPaidGroup(user : User) {static} - + isPaid(user : User) : boolean {static} - } -} -package com.iluwatar.featuretoggle.pattern.tieredversion { - class TieredFeatureToggleVersion { - + TieredFeatureToggleVersion() - + getWelcomeMessage(user : User) : String - + isEnhanced() : boolean - } -} -package com.iluwatar.featuretoggle.pattern.propertiesversion { - class PropertiesFeatureToggleVersion { - - isEnhanced : boolean - + PropertiesFeatureToggleVersion(properties : Properties) - + getWelcomeMessage(user : User) : String - + isEnhanced() : boolean - } -} -package com.iluwatar.featuretoggle { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -UserGroup --> "-freeGroup" User -PropertiesFeatureToggleVersion ..|> Service -TieredFeatureToggleVersion ..|> Service -@enduml \ No newline at end of file diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml deleted file mode 100644 index 6536710baf0d..000000000000 --- a/feature-toggle/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - feature-toggle - - - - - junit - junit - test - - - - \ No newline at end of file diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java deleted file mode 100644 index 97c184feccad..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.featuretoggle; - -import com.iluwatar.featuretoggle.pattern.Service; -import com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion; -import com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion; -import com.iluwatar.featuretoggle.user.User; -import com.iluwatar.featuretoggle.user.UserGroup; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Properties; - -/** - * The Feature Toggle pattern allows for complete code executions to be turned on or off with ease. This allows features - * to be controlled by either dynamic methods just as {@link User} information or by {@link Properties}. In the App - * below there are two examples. Firstly the {@link Properties} version of the feature toggle, where the enhanced - * version of the welcome message which is personalised is turned either on or off at instance creation. This method - * is not as dynamic as the {@link User} driven version where the feature of the personalised welcome message is - * dependant on the {@link UserGroup} the {@link User} is in. So if the user is a memeber of the - * {@link UserGroup#isPaid(User)} then they get an ehanced version of the welcome message. - * - * Note that this pattern can easily introduce code complexity, and if not kept in check can result in redundant - * unmaintained code within the codebase. - * - */ -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. - * - * Block 2 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature - * toggle to disabled. Notice the difference with the printed welcome message the username is not included. - * - * Block 3 shows the {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} being - * set up with two users on who is on the free level, while the other is on the paid level. When the - * {@link Service#getWelcomeMessage(User)} is called with the paid {@link User} note that the welcome message - * contains their username, while the same service call with the free tier user is more generic. No username is - * printed. - * - * @see User - * @see UserGroup - * @see Service - * @see PropertiesFeatureToggleVersion - * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion; - */ - public static void main(String[] args) { - - final Properties properties = new Properties(); - properties.put("enhancedWelcome", true); - Service service = new PropertiesFeatureToggleVersion(properties); - final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); - LOGGER.info(welcomeMessage); - - // --------------------------------------------- - - final Properties turnedOff = new Properties(); - turnedOff.put("enhancedWelcome", false); - Service turnedOffService = new PropertiesFeatureToggleVersion(turnedOff); - final String welcomeMessageturnedOff = turnedOffService.getWelcomeMessage(new User("Jamie No Code")); - LOGGER.info(welcomeMessageturnedOff); - - // -------------------------------------------- - - Service service2 = new TieredFeatureToggleVersion(); - - final User paidUser = new User("Jamie Coder"); - final User freeUser = new User("Alan Defect"); - - UserGroup.addUserToPaidGroup(paidUser); - UserGroup.addUserToFreeGroup(freeUser); - - final String welcomeMessagePaidUser = service2.getWelcomeMessage(paidUser); - final String welcomeMessageFreeUser = service2.getWelcomeMessage(freeUser); - LOGGER.info(welcomeMessageFreeUser); - LOGGER.info(welcomeMessagePaidUser); - } -} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java deleted file mode 100644 index 9650b9f67cc4..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.pattern; - -import com.iluwatar.featuretoggle.user.User; - -/** - * Simple interfaces to allow the calling of the method to generate the welcome message for a given user. While there is - * a helper method to gather the the status of the feature toggle. In some cases there is no need for the - * {@link Service#isEnhanced()} in {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} - * where the toggle is determined by the actual {@link User}. - * - * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion - * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion - * @see User - */ -public interface Service { - - /** - * Generates a welcome message for the passed user. - * - * @param user the {@link User} to be used if the message is to be personalised. - * @return Generated {@link String} welcome message - */ - String getWelcomeMessage(User user); - - /** - * Returns if the welcome message to be displayed will be the enhanced version. - * - * @return Boolean {@value true} if enhanced. - */ - boolean isEnhanced(); - -} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java deleted file mode 100644 index a474423db9c4..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.pattern.propertiesversion; - -import com.iluwatar.featuretoggle.pattern.Service; -import com.iluwatar.featuretoggle.user.User; - -import java.util.Properties; - -/** - * This example of the Feature Toogle pattern is less dynamic version than - * {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is turned on - * or off at the time of creation of the service. This example uses simple Java {@link Properties} however it could as - * easily be done with an external configuration file loaded by Spring and so on. A good example of when to use this - * version of the feature toggle is when new features are being developed. So you could have a configuration property - * boolean named development or some sort of system environment variable. - * - * @see Service - * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion - * @see User - */ -public class PropertiesFeatureToggleVersion implements Service { - - private boolean isEnhanced; - - /** - * Creates an instance of {@link PropertiesFeatureToggleVersion} using the passed {@link Properties} to determine, - * the status of the feature toggle {@link PropertiesFeatureToggleVersion#isEnhanced()}. There is also some defensive - * code to ensure the {@link Properties} passed are as expected. - * - * @param properties {@link Properties} used to configure the service and toggle features. - * @throws IllegalArgumentException when the passed {@link Properties} is not as expected - * @see Properties - */ - public PropertiesFeatureToggleVersion(final Properties properties) { - if (properties == null) { - throw new IllegalArgumentException("No Properties Provided."); - } else { - try { - isEnhanced = (boolean) properties.get("enhancedWelcome"); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid Enhancement Settings Provided."); - } - } - } - - /** - * Generate a welcome message based on the user being passed and the status of the feature toggle. If the enhanced - * version is enabled, then the message will be personalised with the name of the passed {@link User}. However if - * disabled then a generic version fo the message is returned. - * - * @param user the {@link User} to be displayed in the message if the enhanced version is enabled see - * {@link PropertiesFeatureToggleVersion#isEnhanced()}. If the enhanced version is enabled, then the - * message will be personalised with the name of the passed {@link User}. However if disabled then a - * generic version fo the message is returned. - * @return Resulting welcome message. - * @see User - */ - @Override - public String getWelcomeMessage(final User user) { - - if (isEnhanced()) { - return "Welcome " + user + ". You're using the enhanced welcome message."; - } - - return "Welcome to the application."; - } - - /** - * Method that checks if the welcome message to be returned is the enhanced venison or not. For this service it will - * see the value of the boolean that was set in the constructor - * {@link PropertiesFeatureToggleVersion#PropertiesFeatureToggleVersion(Properties)} - * - * @return Boolean value {@value true} if enhanced. - */ - @Override - public boolean isEnhanced() { - return isEnhanced; - } -} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java deleted file mode 100644 index 42b7412c00cd..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.pattern.tieredversion; - -import com.iluwatar.featuretoggle.pattern.Service; -import com.iluwatar.featuretoggle.user.User; -import com.iluwatar.featuretoggle.user.UserGroup; - -/** - * This example of the Feature Toogle pattern shows how it could be implemented based on a {@link User}. Therefore - * showing its use within a tiered application where the paying users get access to different content or - * better versions of features. So in this instance a {@link User} is passed in and if they are found to be - * on the {@link UserGroup#isPaid(User)} they are welcomed with a personalised message. While the other is more - * generic. However this pattern is limited to simple examples such as the one below. - * - * @see Service - * @see User - * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion - * @see UserGroup - */ -public class TieredFeatureToggleVersion implements Service { - - /** - * Generates a welcome message from the passed {@link User}. The resulting message depends on the group of the - * {@link User}. So if the {@link User} is in the {@link UserGroup#paidGroup} then the enhanced version of the - * welcome message will be returned where the username is displayed. - * - * @param user the {@link User} to generate the welcome message for, different messages are displayed if the user is - * in the {@link UserGroup#isPaid(User)} or {@link UserGroup#freeGroup} - * @return Resulting welcome message. - * @see User - * @see UserGroup - */ - @Override - public String getWelcomeMessage(User user) { - if (UserGroup.isPaid(user)) { - return "You're amazing " + user + ". Thanks for paying for this awesome software."; - } - - return "I suppose you can use this software."; - } - - /** - * Method that checks if the welcome message to be returned is the enhanced version. For this instance as the logic - * is driven by the user group. This method is a little redundant. However can be used to show that there is an - * enhanced version available. - * - * @return Boolean value {@value true} if enhanced. - */ - @Override - public boolean isEnhanced() { - return true; - } - -} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java deleted file mode 100644 index baf25aa8b7d6..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.user; - -/** - * Used to demonstrate the purpose of the feature toggle. This class actually has nothing to do with the pattern. - */ -public class User { - - private String name; - - /** - * Default Constructor setting the username. - * - * @param name {@link String} to represent the name of the user. - */ - public User(String name) { - this.name = name; - } - - /** - * {@inheritDoc} - * @return The {@link String} representation of the User, in this case just return the name of the user. - */ - @Override - public String toString() { - return name; - } -} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java deleted file mode 100644 index cb84ec533274..000000000000 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.user; - -import java.util.ArrayList; -import java.util.List; - -/** - * Contains the lists of users of different groups paid and free. Used to demonstrate the tiered example of feature - * toggle. Allowing certain features to be available to only certain groups of users. - * - * @see User - */ -public class UserGroup { - - private static List freeGroup = new ArrayList<>(); - private static List paidGroup = new ArrayList<>(); - - - /** - * Add the passed {@link User} to the free user group list. - * - * @param user {@link User} to be added to the free group - * @throws IllegalArgumentException when user is already added to the paid group - * @see User - */ - public static void addUserToFreeGroup(final User user) throws IllegalArgumentException { - if (paidGroup.contains(user)) { - throw new IllegalArgumentException("User all ready member of paid group."); - } else { - if (!freeGroup.contains(user)) { - freeGroup.add(user); - } - } - } - - /** - * Add the passed {@link User} to the paid user group list. - * - * @param user {@link User} to be added to the paid group - * @throws IllegalArgumentException when the user is already added to the free group - * @see User - */ - public static void addUserToPaidGroup(final User user) throws IllegalArgumentException { - if (freeGroup.contains(user)) { - throw new IllegalArgumentException("User all ready member of free group."); - } else { - if (!paidGroup.contains(user)) { - paidGroup.add(user); - } - } - } - - /** - * Method to take a {@link User} to determine if the user is in the {@link UserGroup#paidGroup}. - * - * @param user {@link User} to check if they are in the {@link UserGroup#paidGroup} - * - * @return true if the {@link User} is in {@link UserGroup#paidGroup} - */ - public static boolean isPaid(User user) { - return paidGroup.contains(user); - } -} diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java deleted file mode 100644 index 846b46bcf807..000000000000 --- a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.featuretoggle.pattern.propertiesversion; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import com.iluwatar.featuretoggle.pattern.Service; -import com.iluwatar.featuretoggle.user.User; -import java.util.Properties; -import org.junit.Test; - -/** - * Test Properties Toggle - */ -public class PropertiesFeatureToggleVersionTest { - - @Test(expected = IllegalArgumentException.class) - public void testNullPropertiesPassed() throws Exception { - new PropertiesFeatureToggleVersion(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testNonBooleanProperty() throws Exception { - final Properties properties = new Properties(); - properties.setProperty("enhancedWelcome", "Something"); - new PropertiesFeatureToggleVersion(properties); - } - - @Test - public void testFeatureTurnedOn() throws Exception { - final Properties properties = new Properties(); - properties.put("enhancedWelcome", true); - Service service = new PropertiesFeatureToggleVersion(properties); - assertTrue(service.isEnhanced()); - final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); - assertEquals("Welcome Jamie No Code. You're using the enhanced welcome message.", welcomeMessage); - } - - @Test - public void testFeatureTurnedOff() throws Exception { - final Properties properties = new Properties(); - properties.put("enhancedWelcome", false); - Service service = new PropertiesFeatureToggleVersion(properties); - assertFalse(service.isEnhanced()); - final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); - assertEquals("Welcome to the application.", welcomeMessage); - } -} diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java deleted file mode 100644 index 3966032d5eac..000000000000 --- a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.pattern.tieredversion; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import com.iluwatar.featuretoggle.pattern.Service; -import com.iluwatar.featuretoggle.user.User; -import com.iluwatar.featuretoggle.user.UserGroup; -import org.junit.Before; -import org.junit.Test; - -/** - * Test Tiered Feature Toggle - */ -public class TieredFeatureToggleVersionTest { - - final User paidUser = new User("Jamie Coder"); - final User freeUser = new User("Alan Defect"); - final Service service = new TieredFeatureToggleVersion(); - - @Before - public void setUp() throws Exception { - UserGroup.addUserToPaidGroup(paidUser); - UserGroup.addUserToFreeGroup(freeUser); - } - - @Test - public void testGetWelcomeMessageForPaidUser() throws Exception { - final String welcomeMessage = service.getWelcomeMessage(paidUser); - final String expected = "You're amazing Jamie Coder. Thanks for paying for this awesome software."; - assertEquals(expected, welcomeMessage); - } - - @Test - public void testGetWelcomeMessageForFreeUser() throws Exception { - final String welcomeMessage = service.getWelcomeMessage(freeUser); - final String expected = "I suppose you can use this software."; - assertEquals(expected, welcomeMessage); - } - - @Test - public void testIsEnhancedAlwaysTrueAsTiered() throws Exception { - assertTrue(service.isEnhanced()); - } -} diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java deleted file mode 100644 index b2c6e5859d4c..000000000000 --- a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.featuretoggle.user; - -import static junit.framework.TestCase.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Test User Group specific feature - */ -public class UserGroupTest { - - @Test - public void testAddUserToFreeGroup() throws Exception { - User user = new User("Free User"); - UserGroup.addUserToFreeGroup(user); - assertFalse(UserGroup.isPaid(user)); - } - - @Test - public void testAddUserToPaidGroup() throws Exception { - User user = new User("Paid User"); - UserGroup.addUserToPaidGroup(user); - assertTrue(UserGroup.isPaid(user)); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddUserToPaidWhenOnFree() throws Exception { - User user = new User("Paid User"); - UserGroup.addUserToFreeGroup(user); - UserGroup.addUserToPaidGroup(user); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddUserToFreeWhenOnPaid() throws Exception { - User user = new User("Free User"); - UserGroup.addUserToPaidGroup(user); - UserGroup.addUserToFreeGroup(user); - } -} diff --git a/fluentinterface/README.md b/fluentinterface/README.md deleted file mode 100644 index 8bf43d97433b..000000000000 --- a/fluentinterface/README.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -layout: pattern -title: Fluent Interface -folder: fluentinterface -permalink: /patterns/fluentinterface/ -pumlid: NOj93eCm302_KXv0VEzlN6F0bMCYB_3zvjpRQ3IpY97MnkNwEZD7l04SdtP8dlMfOAVBaYqRNHr4wy54Xo_Uk6uSSjWwC9FT0Zh61DYrPY_pyXs9WPF-NIllRLJN7m00 -categories: Other -tags: - - Java - - Difficulty-Intermediate - - Functional ---- - -## Intent -A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific language. Using this pattern results in code that can be read nearly as human language. - -## Implementation - -A fluent interface can be implemented using any of - - * Method Chaining - calling a method returns some object on which further methods can be called. - * Static Factory Methods and Imports - * Named parameters - can be simulated in Java using static factory methods. - -![Fluent Interface](./etc/fluentinterface.png "Fluent Interface") - -## Applicability -Use the Fluent Interface pattern when - -* you provide an API that would benefit from a DSL-like usage -* you have objects that are difficult to configure or use - -## Real world examples - -* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html) -* [Google Guava FluentInterable](https://github.com/google/guava/wiki/FunctionalExplained) -* [JOOQ](http://www.jooq.org/doc/3.0/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/) -* [Mockito](http://mockito.org/) -* [Java Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial) - -## Credits - -* [Fluent Interface - Martin Fowler](http://www.martinfowler.com/bliki/FluentInterface.html) -* [Evolutionary architecture and emergent design: Fluent interfaces - Neal Ford](http://www.ibm.com/developerworks/library/j-eaed14/) -* [Internal DSL](http://www.infoq.com/articles/internal-dsls-java) diff --git a/fluentinterface/etc/fluentinterface.png b/fluentinterface/etc/fluentinterface.png deleted file mode 100644 index 611fec7c6e7daa4aab70f1d61c621822333eb7b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83424 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%0AXA48uE6Wo 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

    7U;(81 zmhb8hZ5F<(zsxsvJ2UHV_+V->)mQS7=2CBnK0{^k2f9N8WM;7F#(e#ctVf#nuKuU) zm8AAtkyPg>5J3L7xF9%1t2sNZ`T`LVC;FmfZ9o>QT++qj4jIR0` zdl92a+GC}hP@KKNER|ZIS*m4Pfh(!>K58{(J}#d0rbBpc%>?EWwEA4nHlNbOkaU=| zT7CVKND280bnpYhw9}d39whJCM3qyaCdqiAF$*7H2$>Q+wx)gG^3;v213p!|o_#3c zzVY*OTTX}H<9=eJ`Elw!iL8c{#uL;d$YYoAD$43!JL(u`p*^zxn)i_RhO)w^U?FcW zEN1}_x&o+N5N^nL4vM*n3+KxN-ROxk(8hs*@dKnTMPF=G`vAfgq&OKKSj%n|k`3)w zFvmG+IPO}gNHsQAEe5_uCv|AM7-%nLPpwJRMd$#!=Z(hEDxYJgiDfY|9onKMTD z1F1AnHY%X%lDsJrm3RU@YUj7~6Z@5O?WiZp2Efn)S?eNg{6NvnUQjLhq}JKlQ<8a5 z3IX$*6NGrGA5Z&U*VDbSEVE5=QF0ns)aA2+V{i0F7P)&jd@;oXX%Zzb-N|cQ9PW{U zf}3*yHQhmP%7n|*{)nj)xCrJB*4e6|8wiuxtX$kck(BS*DWlzHnv#H@e7^zxun`lr zk5eQ8J&?{V15b>?`siT1Mp;sS7{mo2QYj>WC$ef!bb2WNiw)}HPLG`>duZCij7L&EoIo_XrPre3vpuH9o*-0aX|EdIG^YM+|@w< zeE``8?A{20aiLEN4-F#AWh%beXOdltn3qAi>`c2x2^%-%CC$T2)wqqKRk@B$N@ zVg()>SKE-Z+ZXMkG4*3L0LYb5Xo6!1fup>c{fRbT^0|%Ka=TEQwBhQ>UJ2XH;H{F4 ze7>aB`$F7eT$&^Sy;3f80a9Zg$dK%jO%TMW^|kKaKoN)mGXr`d za08wVP~SjtSq18Kv%38u43%cUz+bd8I)OMgtaKmy+Fuw^yMUL8e$(k=_vTWn3WOkm z?nH*SNWdWDQ;+B~q0&!n2f^k~BPxLo4bZQ-IN>y@S2$cIenwNH9yw9iNu{J6VYNAl zEEE^f2e)jWnmeFDa5eXr`X@y|w#*c1v!>b?JcPtCxFedarVpH;aISdQHX4_`)nSca zofgxbT_e$qqmMsfKrORPl0|t?NAgwaac*%d-0S)Cr^tvWH}6fy6B(k%Yz+oEd;@g{ zhaSlEEbf9kuz0ZREWXz&GroTdXR7Xq?6OT#P;JTK!wtke?O8HlBo7t&zo}O^GGtcj=J$<*S>>L(wer9jAtNzwKq;M}ejtkT*HX~ln zrrv8Sx8v^FEEi*zo5DAjG4A*E1_`VK3(bLta`KlTtPBW)MHeEUXx_`rrblY(ZW7XY zo279eZg!%1o-B))ftGwFGgPlXsK!yNEjS0{>EV1tML(Q2(MDf@7STaSq%}dX@Jl&{ zUBG!XNQP05T7DyWTsp3N|7az*TOoZg#;3fX&35jFZg*8IU@CIW2ydUlwJ2P}K)xK;uXjZ@m)s6(Jr>)^Lpi8-&1Nl%&?lToyu6S^xEJSAEbhF-9phikn zm73`CY*En6!XiTMbthby;fRzo^Pl~ePj};o4v6uUz&ZwpkxbXZc>2qmy(gZP9+d?9 zs2%?s;Wj>Kh%vayN}P&C$GijRxsJ)v%QMSEkT(Q2WTd-aTz^jWQROaLu~}*Mjvbk- zio_irUg!%iRRNV)@HaAr5q&;7?cqSl6(Eo

    sKQS4 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 Rc^U%{c)I$ztaD0e0s!dz!;t_0 diff --git a/fluentinterface/etc/fluentinterface.ucls b/fluentinterface/etc/fluentinterface.ucls deleted file mode 100644 index e30c45bb2432..000000000000 --- a/fluentinterface/etc/fluentinterface.ucls +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/fluentinterface/etc/fluentinterface.urm.puml b/fluentinterface/etc/fluentinterface.urm.puml deleted file mode 100644 index ef71a0f4bace..000000000000 --- a/fluentinterface/etc/fluentinterface.urm.puml +++ /dev/null @@ -1,72 +0,0 @@ -@startuml -package com.iluwatar.fluentinterface.fluentiterable.simple { - class SimpleFluentIterable { - - iterable : Iterable - # SimpleFluentIterable(iterable : Iterable) - + asList() : List - + filter(predicate : Predicate) : FluentIterable - + first() : Optional - + first(count : int) : FluentIterable - + forEach(action : Consumer) - + from(iterable : Iterable) : FluentIterable {static} - + fromCopyOf(iterable : Iterable) : FluentIterable {static} - + getRemainingElementsCount() : int - + iterator() : Iterator - + last() : Optional - + last(count : int) : FluentIterable - + map(function : Function) : FluentIterable - + spliterator() : Spliterator - + toList(iterator : Iterator) : List {static} - } -} -package com.iluwatar.fluentinterface.app { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - - negatives() : Predicate {static} - - positives() : Predicate {static} - - prettyPrint(delimiter : String, prefix : String, iterable : Iterable) {static} - - prettyPrint(prefix : String, iterable : Iterable) {static} - - transformToString() : Function {static} - } -} -package com.iluwatar.fluentinterface.fluentiterable.lazy { - abstract class DecoratingIterator { - # fromIterator : Iterator - - next : E - + DecoratingIterator(fromIterator : Iterator) - + computeNext() : E {abstract} - + hasNext() : boolean - + next() : E - } - class LazyFluentIterable { - - iterable : Iterable - # LazyFluentIterable() - # LazyFluentIterable(iterable : Iterable) - + asList() : List - + filter(predicate : Predicate) : FluentIterable - + first() : Optional - + first(count : int) : FluentIterable - + from(iterable : Iterable) : FluentIterable {static} - + iterator() : Iterator - + last() : Optional - + last(count : int) : FluentIterable - + map(function : Function) : FluentIterable - } -} -package com.iluwatar.fluentinterface.fluentiterable { - interface FluentIterable { - + asList() : List {abstract} - + copyToList(iterable : Iterable) : List {static} - + filter(Predicate) : FluentIterable {abstract} - + first() : Optional {abstract} - + first(int) : FluentIterable {abstract} - + last() : Optional {abstract} - + last(int) : FluentIterable {abstract} - + map(Function) : FluentIterable {abstract} - } -} -LazyFluentIterable ..|> FluentIterable -SimpleFluentIterable ..|> FluentIterable -@enduml \ No newline at end of file diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml deleted file mode 100644 index 11318e295914..000000000000 --- a/fluentinterface/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - fluentinterface - - - junit - junit - test - - - org.mockito - mockito-core - test - - - \ No newline at end of file diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java deleted file mode 100644 index fd6fc66dd7e9..000000000000 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.app; - -import static java.lang.String.valueOf; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.StringJoiner; -import java.util.function.Function; -import java.util.function.Predicate; - -import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; -import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable; -import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. - * Those interfaces tend to mimic domain specific languages, so they can nearly be read as human - * languages. - *

    - * In this example two implementations of a {@link FluentIterable} interface are given. The - * {@link SimpleFluentIterable} evaluates eagerly and would be too costly for real world - * applications. The {@link LazyFluentIterable} is evaluated on termination. Their usage is - * demonstrated with a simple number list that is filtered, transformed and collected. The result is - * printed afterwards. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - - List integerList = new ArrayList<>(); - integerList.addAll(Arrays.asList(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, - -68, 45)); - - prettyPrint("The initial list contains: ", integerList); - - List firstFiveNegatives = - SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).first(3).asList(); - prettyPrint("The first three negative values are: ", firstFiveNegatives); - - - List lastTwoPositives = - SimpleFluentIterable.fromCopyOf(integerList).filter(positives()).last(2).asList(); - prettyPrint("The last two positive values are: ", lastTwoPositives); - - SimpleFluentIterable - .fromCopyOf(integerList) - .filter(number -> number % 2 == 0) - .first() - .ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber)); - - - List transformedList = - SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).map(transformToString()) - .asList(); - prettyPrint("A string-mapped list of negative numbers contains: ", transformedList); - - - List lastTwoOfFirstFourStringMapped = - LazyFluentIterable.from(integerList).filter(positives()).first(4).last(2) - .map(number -> "String[" + valueOf(number) + "]").asList(); - prettyPrint( - "The lazy list contains the last two of the first four positive numbers mapped to Strings: ", - lastTwoOfFirstFourStringMapped); - - LazyFluentIterable - .from(integerList) - .filter(negatives()) - .first(2) - .last() - .ifPresent(lastOfFirstTwo -> LOGGER.info("The last of the first two negatives is: {}", lastOfFirstTwo)); - } - - private static Function transformToString() { - return integer -> "String[" + valueOf(integer) + "]"; - } - - private static Predicate negatives() { - return integer -> integer < 0; - } - - private static Predicate positives() { - return integer -> integer > 0; - } - - private static void prettyPrint(String prefix, Iterable iterable) { - prettyPrint(", ", prefix, iterable); - } - - private static void prettyPrint(String delimiter, String prefix, - Iterable iterable) { - StringJoiner joiner = new StringJoiner(delimiter, prefix, "."); - Iterator iterator = iterable.iterator(); - while (iterator.hasNext()) { - joiner.add(iterator.next().toString()); - } - - LOGGER.info(joiner.toString()); - } -} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java deleted file mode 100644 index 693585962173..000000000000 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * The FluentIterable is a more convenient implementation of the common iterable interface based on - * the fluent interface design pattern. This interface defines common operations, but doesn't aim to - * be complete. It was inspired by Guava's com.google.common.collect.FluentIterable. - * - * @param is the class of objects the iterable contains - */ -public interface FluentIterable extends Iterable { - - /** - * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy - * the predicate. - * - * @param predicate the condition to test with for the filtering. If the test is negative, the - * tested object is removed by the iterator. - * @return a filtered FluentIterable - */ - FluentIterable filter(Predicate predicate); - - /** - * Returns an Optional containing the first element of this iterable if present, else returns - * Optional.empty(). - * - * @return the first element after the iteration is evaluated - */ - Optional first(); - - /** - * Evaluates the iteration and leaves only the count first elements. - * - * @return the first count elements as an Iterable - */ - FluentIterable first(int count); - - /** - * Evaluates the iteration and returns the last element. This is a terminating operation. - * - * @return the last element after the iteration is evaluated - */ - Optional last(); - - /** - * Evaluates the iteration and leaves only the count last elements. - * - * @return the last counts elements as an Iterable - */ - FluentIterable last(int count); - - /** - * Transforms this FluentIterable into a new one containing objects of the type T. - * - * @param function a function that transforms an instance of E into an instance of T - * @param the target type of the transformation - * @return a new FluentIterable of the new type - */ - FluentIterable map(Function function); - - /** - * Returns the contents of this Iterable as a List. - * - * @return a List representation of this Iterable - */ - List asList(); - - /** - * Utility method that iterates over iterable and adds the contents to a list. - * - * @param iterable the iterable to collect - * @param the type of the objects to iterate - * @return a list with all objects of the given iterator - */ - static List copyToList(Iterable iterable) { - List copy = new ArrayList<>(); - Iterator iterator = iterable.iterator(); - while (iterator.hasNext()) { - copy.add(iterator.next()); - } - return copy; - } -} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java deleted file mode 100644 index 389904bffc84..000000000000 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable.lazy; - -import java.util.Iterator; - -/** - * This class is used to realize LazyFluentIterables. It decorates a given iterator. Does not - * support consecutive hasNext() calls. - * @param Iterable Collection of Elements of Type E - */ -public abstract class DecoratingIterator implements Iterator { - - protected final Iterator fromIterator; - - private E next; - - /** - * Creates an iterator that decorates the given iterator. - */ - public DecoratingIterator(Iterator fromIterator) { - this.fromIterator = fromIterator; - } - - /** - * Precomputes and saves the next element of the Iterable. null is considered as end of data. - * - * @return true if a next element is available - */ - @Override - public final boolean hasNext() { - next = computeNext(); - return next != null; - } - - /** - * Returns the next element of the Iterable. - * - * @return the next element of the Iterable, or null if not present. - */ - @Override - public final E next() { - if (next == null) { - return fromIterator.next(); - } else { - final E result = next; - next = null; - return result; - } - } - - /** - * Computes the next object of the Iterable. Can be implemented to realize custom behaviour for an - * iteration process. null is considered as end of data. - * - * @return the next element of the Iterable. - */ - public abstract E computeNext(); -} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java deleted file mode 100644 index 1a4c88ed7c48..000000000000 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java +++ /dev/null @@ -1,249 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable.lazy; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; - -import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; - -/** - * This is a lazy implementation of the FluentIterable interface. It evaluates all chained - * operations when a terminating operation is applied. - * - * @param the type of the objects the iteration is about - */ -public class LazyFluentIterable implements FluentIterable { - - private final Iterable iterable; - - /** - * This constructor creates a new LazyFluentIterable. It wraps the given iterable. - * - * @param iterable the iterable this FluentIterable works on. - */ - protected LazyFluentIterable(Iterable iterable) { - this.iterable = iterable; - } - - /** - * This constructor can be used to implement anonymous subclasses of the LazyFluentIterable. - */ - protected LazyFluentIterable() { - iterable = this; - } - - /** - * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy - * the predicate. - * - * @param predicate the condition to test with for the filtering. If the test is negative, the - * tested object is removed by the iterator. - * @return a new FluentIterable object that decorates the source iterable - */ - @Override - public FluentIterable filter(Predicate predicate) { - return new LazyFluentIterable() { - @Override - public Iterator iterator() { - return new DecoratingIterator(iterable.iterator()) { - @Override - public E computeNext() { - while (fromIterator.hasNext()) { - E candidate = fromIterator.next(); - if (predicate.test(candidate)) { - return candidate; - } - } - - return null; - } - }; - } - }; - } - - /** - * Can be used to collect objects from the iteration. Is a terminating operation. - * - * @return an Optional containing the first object of this Iterable - */ - @Override - public Optional first() { - Iterator resultIterator = first(1).iterator(); - return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); - } - - /** - * Can be used to collect objects from the iteration. - * - * @param count defines the number of objects to return - * @return the same FluentIterable with a collection decimated to a maximum of 'count' first - * objects. - */ - @Override - public FluentIterable first(int count) { - return new LazyFluentIterable() { - @Override - public Iterator iterator() { - return new DecoratingIterator(iterable.iterator()) { - int currentIndex; - - @Override - public E computeNext() { - if (currentIndex < count && fromIterator.hasNext()) { - E candidate = fromIterator.next(); - currentIndex++; - return candidate; - } - return null; - } - }; - } - }; - } - - /** - * Can be used to collect objects from the iteration. Is a terminating operation. - * - * @return an Optional containing the last object of this Iterable - */ - @Override - public Optional last() { - Iterator resultIterator = last(1).iterator(); - return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); - } - - /** - * Can be used to collect objects from the Iterable. Is a terminating operation. This operation is - * memory intensive, because the contents of this Iterable are collected into a List, when the - * next object is requested. - * - * @param count defines the number of objects to return - * @return the same FluentIterable with a collection decimated to a maximum of 'count' last - * objects - */ - @Override - public FluentIterable last(int count) { - return new LazyFluentIterable() { - @Override - public Iterator iterator() { - return new DecoratingIterator(iterable.iterator()) { - private int stopIndex; - private int totalElementsCount; - private List list; - private int currentIndex; - - @Override - public E computeNext() { - initialize(); - - E candidate = null; - while (currentIndex < stopIndex && fromIterator.hasNext()) { - currentIndex++; - fromIterator.next(); - } - if (currentIndex >= stopIndex && fromIterator.hasNext()) { - candidate = fromIterator.next(); - } - return candidate; - } - - private void initialize() { - if (list == null) { - list = new ArrayList<>(); - Iterator newIterator = iterable.iterator(); - while (newIterator.hasNext()) { - list.add(newIterator.next()); - } - - totalElementsCount = list.size(); - stopIndex = totalElementsCount - count; - } - } - }; - } - }; - } - - /** - * Transforms this FluentIterable into a new one containing objects of the type T. - * - * @param function a function that transforms an instance of E into an instance of T - * @param the target type of the transformation - * @return a new FluentIterable of the new type - */ - @Override - public FluentIterable map(Function function) { - return new LazyFluentIterable() { - @Override - public Iterator iterator() { - return new DecoratingIterator(null) { - Iterator oldTypeIterator = iterable.iterator(); - - @Override - public T computeNext() { - if (oldTypeIterator.hasNext()) { - E candidate = oldTypeIterator.next(); - return function.apply(candidate); - } else { - return null; - } - } - }; - } - }; - } - - /** - * Collects all remaining objects of this iteration into a list. - * - * @return a list with all remaining objects of this iteration - */ - @Override - public List asList() { - return FluentIterable.copyToList(iterable); - } - - @Override - public Iterator iterator() { - return new DecoratingIterator(iterable.iterator()) { - @Override - public E computeNext() { - return fromIterator.hasNext() ? fromIterator.next() : null; - } - }; - } - - /** - * @return a FluentIterable from a given iterable. Calls the LazyFluentIterable constructor. - */ - public static final FluentIterable from(Iterable iterable) { - return new LazyFluentIterable<>(iterable); - } - -} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java deleted file mode 100644 index fde259f9b03c..000000000000 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable.simple; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Spliterator; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; - -import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; - -/** - * This is a simple implementation of the FluentIterable interface. It evaluates all chained - * operations eagerly. This implementation would be costly to be utilized in real applications. - * - * @param the type of the objects the iteration is about - */ -public class SimpleFluentIterable implements FluentIterable { - - private final Iterable iterable; - - /** - * This constructor creates a copy of a given iterable's contents. - * - * @param iterable the iterable this interface copies to work on. - */ - protected SimpleFluentIterable(Iterable iterable) { - this.iterable = iterable; - } - - /** - * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy - * the predicate. - * - * @param predicate the condition to test with for the filtering. If the test is negative, the - * tested object is removed by the iterator. - * @return the same FluentIterable with a filtered collection - */ - @Override - public final FluentIterable filter(Predicate predicate) { - Iterator iterator = iterator(); - while (iterator.hasNext()) { - E nextElement = iterator.next(); - if (!predicate.test(nextElement)) { - iterator.remove(); - } - } - return this; - } - - /** - * Can be used to collect objects from the Iterable. Is a terminating operation. - * - * @return an option of the first object of the Iterable - */ - @Override - public final Optional first() { - Iterator resultIterator = first(1).iterator(); - return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); - } - - /** - * Can be used to collect objects from the Iterable. Is a terminating operation. - * - * @param count defines the number of objects to return - * @return the same FluentIterable with a collection decimated to a maximum of 'count' first - * objects. - */ - @Override - public final FluentIterable first(int count) { - Iterator iterator = iterator(); - int currentCount = 0; - while (iterator.hasNext()) { - iterator.next(); - if (currentCount >= count) { - iterator.remove(); - } - currentCount++; - } - return this; - } - - /** - * Can be used to collect objects from the Iterable. Is a terminating operation. - * - * @return an option of the last object of the Iterable - */ - @Override - public final Optional last() { - List list = last(1).asList(); - if (list.isEmpty()) { - return Optional.empty(); - } - return Optional.of(list.get(0)); - } - - /** - * Can be used to collect objects from the Iterable. Is a terminating operation. - * - * @param count defines the number of objects to return - * @return the same FluentIterable with a collection decimated to a maximum of 'count' last - * objects - */ - @Override - public final FluentIterable last(int count) { - int remainingElementsCount = getRemainingElementsCount(); - Iterator iterator = iterator(); - int currentIndex = 0; - while (iterator.hasNext()) { - iterator.next(); - if (currentIndex < remainingElementsCount - count) { - iterator.remove(); - } - currentIndex++; - } - - return this; - } - - /** - * Transforms this FluentIterable into a new one containing objects of the type T. - * - * @param function a function that transforms an instance of E into an instance of T - * @param the target type of the transformation - * @return a new FluentIterable of the new type - */ - @Override - public final FluentIterable map(Function function) { - List temporaryList = new ArrayList<>(); - Iterator iterator = iterator(); - while (iterator.hasNext()) { - temporaryList.add(function.apply(iterator.next())); - } - return from(temporaryList); - } - - /** - * Collects all remaining objects of this Iterable into a list. - * - * @return a list with all remaining objects of this Iterable - */ - @Override - public List asList() { - return toList(iterable.iterator()); - } - - /** - * @return a FluentIterable from a given iterable. Calls the SimpleFluentIterable constructor. - */ - public static final FluentIterable from(Iterable iterable) { - return new SimpleFluentIterable<>(iterable); - } - - public static final FluentIterable fromCopyOf(Iterable iterable) { - List copy = FluentIterable.copyToList(iterable); - return new SimpleFluentIterable<>(copy); - } - - @Override - public Iterator iterator() { - return iterable.iterator(); - } - - @Override - public void forEach(Consumer action) { - iterable.forEach(action); - } - - - @Override - public Spliterator spliterator() { - return iterable.spliterator(); - } - - /** - * @return the count of remaining objects of the current Iterable - */ - public final int getRemainingElementsCount() { - int counter = 0; - Iterator iterator = iterator(); - while (iterator.hasNext()) { - iterator.next(); - counter++; - } - return counter; - } - - /** - * Collects the remaining objects of the given iterator into a List. - * - * @return a new List with the remaining objects. - */ - public static List toList(Iterator iterator) { - List copy = new ArrayList<>(); - while (iterator.hasNext()) { - copy.add(iterator.next()); - } - return copy; - } -} diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/app/AppTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/app/AppTest.java deleted file mode 100644 index 11740bf1af46..000000000000 --- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/app/AppTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.app; - -import org.junit.Test; -/** - * Application Test Entry - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java deleted file mode 100644 index 4cc2b1a7a7b8..000000000000 --- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable; - -import org.junit.Test; - -import java.util.*; -import java.util.function.Consumer; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -/** - * Date: 12/12/15 - 7:00 PM - * - * @author Jeroen Meulemeester - */ -public abstract class FluentIterableTest { - - /** - * Create a new {@link FluentIterable} from the given integers - * - * @param integers The integers - * @return The new iterable, use for testing - */ - protected abstract FluentIterable createFluentIterable(final Iterable integers); - - @Test - public void testFirst() throws Exception { - final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); - final Optional first = createFluentIterable(integers).first(); - assertNotNull(first); - assertTrue(first.isPresent()); - assertEquals(integers.get(0), first.get()); - } - - @Test - public void testFirstEmptyCollection() throws Exception { - final List integers = Collections.emptyList(); - final Optional first = createFluentIterable(integers).first(); - assertNotNull(first); - assertFalse(first.isPresent()); - } - - @Test - public void testFirstCount() throws Exception { - final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); - final List first4 = createFluentIterable(integers) - .first(4) - .asList(); - - assertNotNull(first4); - assertEquals(4, first4.size()); - - assertEquals(integers.get(0), first4.get(0)); - assertEquals(integers.get(1), first4.get(1)); - assertEquals(integers.get(2), first4.get(2)); - assertEquals(integers.get(3), first4.get(3)); - } - - @Test - public void testFirstCountLessItems() throws Exception { - final List integers = Arrays.asList(1, 2, 3); - final List first4 = createFluentIterable(integers) - .first(4) - .asList(); - - assertNotNull(first4); - assertEquals(3, first4.size()); - - assertEquals(integers.get(0), first4.get(0)); - assertEquals(integers.get(1), first4.get(1)); - assertEquals(integers.get(2), first4.get(2)); - } - - @Test - public void testLast() throws Exception { - final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); - final Optional last = createFluentIterable(integers).last(); - assertNotNull(last); - assertTrue(last.isPresent()); - assertEquals(integers.get(integers.size() - 1), last.get()); - } - - @Test - public void testLastEmptyCollection() throws Exception { - final List integers = Collections.emptyList(); - final Optional last = createFluentIterable(integers).last(); - assertNotNull(last); - assertFalse(last.isPresent()); - } - - @Test - public void testLastCount() throws Exception { - final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); - final List last4 = createFluentIterable(integers) - .last(4) - .asList(); - - assertNotNull(last4); - assertEquals(4, last4.size()); - assertEquals(Integer.valueOf(3), last4.get(0)); - assertEquals(Integer.valueOf(10), last4.get(1)); - assertEquals(Integer.valueOf(9), last4.get(2)); - assertEquals(Integer.valueOf(8), last4.get(3)); - } - - @Test - public void testLastCountLessItems() throws Exception { - final List integers = Arrays.asList(1, 2, 3); - final List last4 = createFluentIterable(integers) - .last(4) - .asList(); - - assertNotNull(last4); - assertEquals(3, last4.size()); - - assertEquals(Integer.valueOf(1), last4.get(0)); - assertEquals(Integer.valueOf(2), last4.get(1)); - assertEquals(Integer.valueOf(3), last4.get(2)); - } - - @Test - public void testFilter() throws Exception { - final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); - final List evenItems = createFluentIterable(integers) - .filter(i -> i % 2 == 0) - .asList(); - - assertNotNull(evenItems); - assertEquals(3, evenItems.size()); - assertEquals(Integer.valueOf(2), evenItems.get(0)); - assertEquals(Integer.valueOf(10), evenItems.get(1)); - assertEquals(Integer.valueOf(8), evenItems.get(2)); - } - - @Test - public void testMap() throws Exception { - final List integers = Arrays.asList(1, 2, 3); - final List longs = createFluentIterable(integers) - .map(Integer::longValue) - .asList(); - - assertNotNull(longs); - assertEquals(integers.size(), longs.size()); - assertEquals(Long.valueOf(1), longs.get(0)); - assertEquals(Long.valueOf(2), longs.get(1)); - assertEquals(Long.valueOf(3), longs.get(2)); - } - - @Test - public void testForEach() throws Exception { - final List integers = Arrays.asList(1, 2, 3); - - final Consumer consumer = mock(Consumer.class); - createFluentIterable(integers).forEach(consumer); - - verify(consumer, times(1)).accept(Integer.valueOf(1)); - verify(consumer, times(1)).accept(Integer.valueOf(2)); - verify(consumer, times(1)).accept(Integer.valueOf(3)); - verifyNoMoreInteractions(consumer); - - } - - @Test - public void testSpliterator() throws Exception { - final List integers = Arrays.asList(1, 2, 3); - final Spliterator split = createFluentIterable(integers).spliterator(); - assertNotNull(split); - } - -} \ No newline at end of file diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java deleted file mode 100644 index 4f4a118634c6..000000000000 --- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable.lazy; - -import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; -import com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest; - -/** - * Date: 12/12/15 - 7:56 PM - * - * @author Jeroen Meulemeester - */ -public class LazyFluentIterableTest extends FluentIterableTest { - - @Override - protected FluentIterable createFluentIterable(Iterable integers) { - return LazyFluentIterable.from(integers); - } - -} diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java deleted file mode 100644 index 23b93b0a09ff..000000000000 --- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.fluentinterface.fluentiterable.simple; - -import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; -import com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest; - -/** - * Date: 12/12/15 - 7:56 PM - * - * @author Jeroen Meulemeester - */ -public class SimpleFluentIterableTest extends FluentIterableTest { - - @Override - protected FluentIterable createFluentIterable(Iterable integers) { - return SimpleFluentIterable.fromCopyOf(integers); - } - -} diff --git a/flux/README.md b/flux/README.md deleted file mode 100644 index e36b73900e9d..000000000000 --- a/flux/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: pattern -title: Flux -folder: flux -permalink: /patterns/flux/ -pumlid: 7SP14eCm20NGg-W13FlU1YFLE0GpyAazVZk-rPkRLSrDqdKwW14l8kUxx0r7hXdYzJA8eTIhKzEy6UnqyeUNJQBjjWm6n2seS_n3Ryql2UgJajxBoAu_ -categories: Presentation Tier -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Flux eschews MVC in favor of a unidirectional data flow. When a -user interacts with a view, the view propagates an action through a central -dispatcher, to the various stores that hold the application's data and business -logic, which updates all of the views that are affected. - -![alt text](./etc/flux.png "Flux") - -## Applicability -Use the Flux pattern when - -* you want to focus on creating explicit and understandable update paths for your application's data, which makes tracing changes during development simpler and makes bugs easier to track down and fix. - -## Credits - -* [Flux - Application architecture for building user interfaces](http://facebook.github.io/flux/) diff --git a/flux/etc/flux.png b/flux/etc/flux.png deleted file mode 100644 index 9cb596eaf03d0a97523b8efe50495f407f3bab38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62348 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%0ADKlO=7zK=?WZ6o=By;0+ozLGT-uIlRPo_yFzP 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

    nDi@2?%Cy6*Q98iYqFx4O(t;E{y-U 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/flux/etc/flux.urm.puml b/flux/etc/flux.urm.puml deleted file mode 100644 index 11ac26d60f9f..000000000000 --- a/flux/etc/flux.urm.puml +++ /dev/null @@ -1,117 +0,0 @@ -@startuml -package com.iluwatar.flux.view { - class ContentView { - - LOGGER : Logger {static} - - content : Content - + ContentView() - + render() - + storeChanged(store : Store) - } - class MenuView { - - LOGGER : Logger {static} - - selected : MenuItem - + MenuView() - + itemClicked(item : MenuItem) - + render() - + storeChanged(store : Store) - } - interface View { - + render() {abstract} - + storeChanged(Store) {abstract} - } -} -package com.iluwatar.flux.action { - abstract class Action { - - type : ActionType - + Action(type : ActionType) - + getType() : ActionType - } - enum ActionType { - + CONTENT_CHANGED {static} - + MENU_ITEM_SELECTED {static} - + valueOf(name : String) : ActionType {static} - + values() : ActionType[] {static} - } - enum Content { - + COMPANY {static} - + PRODUCTS {static} - - title : String - + toString() : String - + valueOf(name : String) : Content {static} - + values() : Content[] {static} - } - class ContentAction { - - content : Content - + ContentAction(content : Content) - + getContent() : Content - } - class MenuAction { - - menuItem : MenuItem - + MenuAction(menuItem : MenuItem) - + getMenuItem() : MenuItem - } - enum MenuItem { - + COMPANY {static} - + HOME {static} - + PRODUCTS {static} - - title : String - + toString() : String - + valueOf(name : String) : MenuItem {static} - + values() : MenuItem[] {static} - } -} -package com.iluwatar.flux.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.flux.store { - class ContentStore { - - content : Content - + ContentStore() - + getContent() : Content - + onAction(action : Action) - } - class MenuStore { - - selected : MenuItem - + MenuStore() - + getSelected() : MenuItem - + onAction(action : Action) - } - abstract class Store { - - views : List - + Store() - # notifyChange() - + onAction(Action) {abstract} - + registerView(view : View) - } -} -package com.iluwatar.flux.dispatcher { - class Dispatcher { - - instance : Dispatcher {static} - - stores : List - - Dispatcher() - - dispatchAction(action : Action) - + getInstance() : Dispatcher {static} - + menuItemSelected(menuItem : MenuItem) - + registerStore(store : Store) - } -} -MenuAction --> "-menuItem" MenuItem -Action --> "-type" ActionType -Dispatcher --> "-instance" Dispatcher -MenuStore --> "-selected" MenuItem -ContentView --> "-content" Content -Dispatcher --> "-stores" Store -MenuView --> "-selected" MenuItem -Store --> "-views" View -ContentAction --> "-content" Content -ContentStore --> "-content" Content -ContentAction --|> Action -MenuAction --|> Action -ContentStore --|> Store -MenuStore --|> Store -ContentView ..|> View -MenuView ..|> View -@enduml \ No newline at end of file diff --git a/flux/pom.xml b/flux/pom.xml deleted file mode 100644 index 779bd3e974dc..000000000000 --- a/flux/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - flux - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/flux/src/main/java/com/iluwatar/flux/action/Action.java b/flux/src/main/java/com/iluwatar/flux/action/Action.java deleted file mode 100644 index 31765177a53c..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/Action.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -/** - * - * Action is the data payload dispatched to the stores when something happens. - * - */ -public abstract class Action { - - private ActionType type; - - public Action(ActionType type) { - this.type = type; - } - - public ActionType getType() { - return type; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/action/ActionType.java b/flux/src/main/java/com/iluwatar/flux/action/ActionType.java deleted file mode 100644 index f5b5a2f810bb..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/ActionType.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -/** - * - * Types of actions. - * - */ -public enum ActionType { - - MENU_ITEM_SELECTED, CONTENT_CHANGED; - -} diff --git a/flux/src/main/java/com/iluwatar/flux/action/Content.java b/flux/src/main/java/com/iluwatar/flux/action/Content.java deleted file mode 100644 index 596b466db414..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/Content.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -/** - * - * Content items. - * - */ -public enum Content { - - PRODUCTS("Products - This page lists the company's products."), COMPANY( - "Company - This page displays information about the company."); - - private String title; - - private Content(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/action/ContentAction.java b/flux/src/main/java/com/iluwatar/flux/action/ContentAction.java deleted file mode 100644 index f6005b8d77ad..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/ContentAction.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -/** - * - * ContentAction is a concrete action. - * - */ -public class ContentAction extends Action { - - private Content content; - - public ContentAction(Content content) { - super(ActionType.CONTENT_CHANGED); - this.content = content; - } - - public Content getContent() { - return content; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/action/MenuAction.java b/flux/src/main/java/com/iluwatar/flux/action/MenuAction.java deleted file mode 100644 index 6dc95f5bc164..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/MenuAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - - -/** - * - * MenuAction is a concrete action. - * - */ -public class MenuAction extends Action { - - private MenuItem menuItem; - - public MenuAction(MenuItem menuItem) { - super(ActionType.MENU_ITEM_SELECTED); - this.menuItem = menuItem; - } - - public MenuItem getMenuItem() { - return menuItem; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/action/MenuItem.java b/flux/src/main/java/com/iluwatar/flux/action/MenuItem.java deleted file mode 100644 index 5e0f0d6f1f8f..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/action/MenuItem.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -/** - * - * Menu items. - * - */ -public enum MenuItem { - - HOME("Home"), PRODUCTS("Products"), COMPANY("Company"); - - private String title; - - MenuItem(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/app/App.java b/flux/src/main/java/com/iluwatar/flux/app/App.java deleted file mode 100644 index c758652c7fb0..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/app/App.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.app; - -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.dispatcher.Dispatcher; -import com.iluwatar.flux.store.ContentStore; -import com.iluwatar.flux.store.MenuStore; -import com.iluwatar.flux.view.ContentView; -import com.iluwatar.flux.view.MenuView; - -/** - * - * Flux is the application architecture that Facebook uses for building client-side web - * applications. Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with - * a React view, the view propagates an action through a central dispatcher, to the various stores - * that hold the application's data and business logic, which updates all of the views that are - * affected. - *

    - * This example has two views: menu and content. They represent typical main menu and content area - * of a web page. When menu item is clicked it triggers events through the dispatcher. The events - * are received and handled by the stores updating their data as needed. The stores then notify the - * views that they should rerender themselves. - *

    - * http://facebook.github.io/flux/docs/overview.html - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - // initialize and wire the system - MenuStore menuStore = new MenuStore(); - Dispatcher.getInstance().registerStore(menuStore); - ContentStore contentStore = new ContentStore(); - Dispatcher.getInstance().registerStore(contentStore); - MenuView menuView = new MenuView(); - menuStore.registerView(menuView); - ContentView contentView = new ContentView(); - contentStore.registerView(contentView); - - // render initial view - menuView.render(); - contentView.render(); - - // user clicks another menu item - // this triggers action dispatching and eventually causes views to render with new content - menuView.itemClicked(MenuItem.COMPANY); - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java b/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java deleted file mode 100644 index 3be55dc46144..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.dispatcher; - -import java.util.LinkedList; -import java.util.List; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.action.ContentAction; -import com.iluwatar.flux.action.MenuAction; -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.store.Store; - -/** - * - * Dispatcher sends Actions to registered Stores. - * - */ -public final class Dispatcher { - - private static Dispatcher instance = new Dispatcher(); - - private List stores = new LinkedList<>(); - - private Dispatcher() {} - - public static Dispatcher getInstance() { - return instance; - } - - public void registerStore(Store store) { - stores.add(store); - } - - /** - * Menu item selected handler - */ - public void menuItemSelected(MenuItem menuItem) { - dispatchAction(new MenuAction(menuItem)); - switch (menuItem) { - case HOME: - case PRODUCTS: - default: - dispatchAction(new ContentAction(Content.PRODUCTS)); - break; - case COMPANY: - dispatchAction(new ContentAction(Content.COMPANY)); - break; - } - } - - private void dispatchAction(Action action) { - stores.stream().forEach(store -> store.onAction(action)); - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/store/ContentStore.java b/flux/src/main/java/com/iluwatar/flux/store/ContentStore.java deleted file mode 100644 index b457dccbb254..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/store/ContentStore.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.store; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.action.ActionType; -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.action.ContentAction; - -/** - * - * ContentStore is a concrete store. - * - */ -public class ContentStore extends Store { - - private Content content = Content.PRODUCTS; - - @Override - public void onAction(Action action) { - if (action.getType().equals(ActionType.CONTENT_CHANGED)) { - ContentAction contentAction = (ContentAction) action; - content = contentAction.getContent(); - notifyChange(); - } - } - - public Content getContent() { - return content; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/store/MenuStore.java b/flux/src/main/java/com/iluwatar/flux/store/MenuStore.java deleted file mode 100644 index 124e027bdac2..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/store/MenuStore.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.store; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.action.ActionType; -import com.iluwatar.flux.action.MenuAction; -import com.iluwatar.flux.action.MenuItem; - -/** - * - * MenuStore is a concrete store. - * - */ -public class MenuStore extends Store { - - private MenuItem selected = MenuItem.HOME; - - @Override - public void onAction(Action action) { - if (action.getType().equals(ActionType.MENU_ITEM_SELECTED)) { - MenuAction menuAction = (MenuAction) action; - selected = menuAction.getMenuItem(); - notifyChange(); - } - } - - public MenuItem getSelected() { - return selected; - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/store/Store.java b/flux/src/main/java/com/iluwatar/flux/store/Store.java deleted file mode 100644 index 42a546c10982..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/store/Store.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.store; - -import java.util.LinkedList; -import java.util.List; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.view.View; - -/** - * - * Store is a data model. - * - */ -public abstract class Store { - - private List views = new LinkedList<>(); - - public abstract void onAction(Action action); - - public void registerView(View view) { - views.add(view); - } - - protected void notifyChange() { - views.stream().forEach(view -> view.storeChanged(this)); - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/view/ContentView.java b/flux/src/main/java/com/iluwatar/flux/view/ContentView.java deleted file mode 100644 index a501485c53df..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/view/ContentView.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.view; - -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.store.ContentStore; -import com.iluwatar.flux.store.Store; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * ContentView is a concrete view. - * - */ -public class ContentView implements View { - - private static final Logger LOGGER = LoggerFactory.getLogger(ContentView.class); - - private Content content = Content.PRODUCTS; - - @Override - public void storeChanged(Store store) { - ContentStore contentStore = (ContentStore) store; - content = contentStore.getContent(); - render(); - } - - @Override - public void render() { - 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 deleted file mode 100644 index 0744adce6091..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/view/MenuView.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.view; - -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.dispatcher.Dispatcher; -import com.iluwatar.flux.store.MenuStore; -import com.iluwatar.flux.store.Store; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * MenuView is a concrete view. - * - */ -public class MenuView implements View { - - private static final Logger LOGGER = LoggerFactory.getLogger(MenuView.class); - - private MenuItem selected = MenuItem.HOME; - - @Override - public void storeChanged(Store store) { - MenuStore menuStore = (MenuStore) store; - selected = menuStore.getSelected(); - render(); - } - - @Override - public void render() { - for (MenuItem item : MenuItem.values()) { - if (selected.equals(item)) { - LOGGER.info("* {}", item); - } else { - LOGGER.info(item.toString()); - } - } - } - - public void itemClicked(MenuItem item) { - Dispatcher.getInstance().menuItemSelected(item); - } -} diff --git a/flux/src/main/java/com/iluwatar/flux/view/View.java b/flux/src/main/java/com/iluwatar/flux/view/View.java deleted file mode 100644 index c7cc6036aa66..000000000000 --- a/flux/src/main/java/com/iluwatar/flux/view/View.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.view; - -import com.iluwatar.flux.store.Store; - -/** - * - * Views define the representation of data. - * - */ -public interface View { - - void storeChanged(Store store); - - void render(); -} diff --git a/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java b/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java deleted file mode 100644 index 3ddf7805c95e..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/12/15 - 10:11 PM - * - * @author Jeroen Meulemeester - */ -public class ContentTest { - - @Test - public void testToString() throws Exception { - for (final Content content : Content.values()) { - final String toString = content.toString(); - assertNotNull(toString); - assertFalse(toString.trim().isEmpty()); - } - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java b/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java deleted file mode 100644 index e40133586ea5..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.action; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/12/15 - 10:15 PM - * - * @author Jeroen Meulemeester - */ -public class MenuItemTest { - - @Test - public void testToString() throws Exception { - for (final MenuItem menuItem : MenuItem.values()) { - final String toString = menuItem.toString(); - assertNotNull(toString); - assertFalse(toString.trim().isEmpty()); - } - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/app/AppTest.java b/flux/src/test/java/com/iluwatar/flux/app/AppTest.java deleted file mode 100644 index 7e6475ee730a..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/app/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.app; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java b/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java deleted file mode 100644 index b245de6ac0a0..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.dispatcher; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.action.ActionType; -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.action.ContentAction; -import com.iluwatar.flux.action.MenuAction; -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.store.Store; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.List; -import java.util.stream.Collectors; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -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/12/15 - 8:22 PM - * - * @author Jeroen Meulemeester - */ -public class DispatcherTest { - - /** - * Dispatcher is a singleton with no way to reset it's internal state back to the beginning. - * Replace the instance with a fresh one before each test to make sure test cases have no - * influence on each other. - */ - @Before - public void setUp() throws Exception { - final Constructor constructor; - constructor = Dispatcher.class.getDeclaredConstructor(); - constructor.setAccessible(true); - - final Field field = Dispatcher.class.getDeclaredField("instance"); - field.setAccessible(true); - field.set(Dispatcher.getInstance(), constructor.newInstance()); - } - - @Test - public void testGetInstance() throws Exception { - assertNotNull(Dispatcher.getInstance()); - assertSame(Dispatcher.getInstance(), Dispatcher.getInstance()); - } - - @Test - public void testMenuItemSelected() throws Exception { - final Dispatcher dispatcher = Dispatcher.getInstance(); - - final Store store = mock(Store.class); - dispatcher.registerStore(store); - dispatcher.menuItemSelected(MenuItem.HOME); - dispatcher.menuItemSelected(MenuItem.COMPANY); - - // We expect 4 events, 2 menu selections and 2 content change actions - final ArgumentCaptor actionCaptor = ArgumentCaptor.forClass(Action.class); - verify(store, times(4)).onAction(actionCaptor.capture()); - verifyNoMoreInteractions(store); - - final List actions = actionCaptor.getAllValues(); - final List menuActions = actions.stream() - .filter(a -> a.getType().equals(ActionType.MENU_ITEM_SELECTED)) - .map(a -> (MenuAction) a) - .collect(Collectors.toList()); - - final List contentActions = actions.stream() - .filter(a -> a.getType().equals(ActionType.CONTENT_CHANGED)) - .map(a -> (ContentAction) a) - .collect(Collectors.toList()); - - assertEquals(2, menuActions.size()); - assertEquals(1, menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.HOME::equals).count()); - assertEquals(1, menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.COMPANY::equals).count()); - - assertEquals(2, contentActions.size()); - assertEquals(1, contentActions.stream().map(ContentAction::getContent).filter(Content.PRODUCTS::equals).count()); - assertEquals(1, contentActions.stream().map(ContentAction::getContent).filter(Content.COMPANY::equals).count()); - - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java b/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java deleted file mode 100644 index 85c0e46f4f2a..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.store; - -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.action.ContentAction; -import com.iluwatar.flux.action.MenuAction; -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.view.View; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -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; - -/** - * Date: 12/12/15 - 10:18 PM - * - * @author Jeroen Meulemeester - */ -public class ContentStoreTest { - - @Test - public void testOnAction() throws Exception { - final ContentStore contentStore = new ContentStore(); - - final View view = mock(View.class); - contentStore.registerView(view); - - verifyZeroInteractions(view); - - // Content should not react on menu action ... - contentStore.onAction(new MenuAction(MenuItem.PRODUCTS)); - verifyZeroInteractions(view); - - // ... but it should react on a content action - contentStore.onAction(new ContentAction(Content.COMPANY)); - verify(view, times(1)).storeChanged(eq(contentStore)); - verifyNoMoreInteractions(view); - assertEquals(Content.COMPANY, contentStore.getContent()); - - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java b/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java deleted file mode 100644 index 63d1dfdfb914..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.store; - -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.action.ContentAction; -import com.iluwatar.flux.action.MenuAction; -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.view.View; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -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; - -/** - * Date: 12/12/15 - 10:18 PM - * - * @author Jeroen Meulemeester - */ -public class MenuStoreTest { - - @Test - public void testOnAction() throws Exception { - final MenuStore menuStore = new MenuStore(); - - final View view = mock(View.class); - menuStore.registerView(view); - - verifyZeroInteractions(view); - - // Menu should not react on content action ... - menuStore.onAction(new ContentAction(Content.COMPANY)); - verifyZeroInteractions(view); - - // ... but it should react on a menu action - menuStore.onAction(new MenuAction(MenuItem.PRODUCTS)); - verify(view, times(1)).storeChanged(eq(menuStore)); - verifyNoMoreInteractions(view); - assertEquals(MenuItem.PRODUCTS, menuStore.getSelected()); - - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java b/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java deleted file mode 100644 index b97d751bf798..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.view; - -import com.iluwatar.flux.action.Content; -import com.iluwatar.flux.store.ContentStore; -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -/** - * Date: 12/12/15 - 10:31 PM - * - * @author Jeroen Meulemeester - */ -public class ContentViewTest { - - @Test - public void testStoreChanged() throws Exception { - final ContentStore store = mock(ContentStore.class); - when(store.getContent()).thenReturn(Content.PRODUCTS); - - final ContentView view = new ContentView(); - view.storeChanged(store); - - verify(store, times(1)).getContent(); - verifyNoMoreInteractions(store); - } - -} diff --git a/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java b/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java deleted file mode 100644 index 528549e9ca5a..000000000000 --- a/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flux.view; - -import com.iluwatar.flux.action.Action; -import com.iluwatar.flux.action.MenuItem; -import com.iluwatar.flux.dispatcher.Dispatcher; -import com.iluwatar.flux.store.MenuStore; -import com.iluwatar.flux.store.Store; -import org.junit.Test; - -import static org.mockito.Matchers.any; -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.mockito.Mockito.when; - -/** - * Date: 12/12/15 - 10:31 PM - * - * @author Jeroen Meulemeester - */ -public class MenuViewTest { - - @Test - public void testStoreChanged() throws Exception { - final MenuStore store = mock(MenuStore.class); - when(store.getSelected()).thenReturn(MenuItem.HOME); - - final MenuView view = new MenuView(); - view.storeChanged(store); - - verify(store, times(1)).getSelected(); - verifyNoMoreInteractions(store); - } - - @Test - public void testItemClicked() throws Exception { - final Store store = mock(Store.class); - Dispatcher.getInstance().registerStore(store); - - final MenuView view = new MenuView(); - view.itemClicked(MenuItem.PRODUCTS); - - // We should receive a menu click action and a content changed action - verify(store, times(2)).onAction(any(Action.class)); - - } - -} diff --git a/flyweight/README.md b/flyweight/README.md deleted file mode 100644 index 9a0e13e199e0..000000000000 --- a/flyweight/README.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -layout: pattern -title: Flyweight -folder: flyweight -permalink: /patterns/flyweight/ -pumlid: HSV94S8m3030Lg20M7-w4OvYAoCh7Xtnq3ty-Eq-MQlaJcdow17JNm26gpIEdkzqidffa4Qfrm2MN1XeSEADsqxEJRU94MJgCD1_W4C-YxZr08hwNqaRPUQGBm00 -categories: Structural -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate - - Performance ---- - -## Intent -Use sharing to support large numbers of fine-grained objects -efficiently. - -## Explanation -Real world example - -> Alchemist's shop has shelves full of magic potions. Many of the potions are the same so there is no need to create new object for each of them. Instead one object instance can represent multiple shelf items so memory footprint remains small. - -In plain words - -> It is used to minimize memory usage or computational expenses by sharing as much as possible with similar objects. - -Wikipedia says - -> In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. - -**Programmatic example** - -Translating our alchemist shop example from above. First of all we have different potion types - -``` -public interface Potion { - void drink(); -} - -public class HealingPotion implements Potion { - private static final Logger LOGGER = LoggerFactory.getLogger(HealingPotion.class); - @Override - public void drink() { - LOGGER.info("You feel healed. (Potion={})", System.identityHashCode(this)); - } -} - -public class HolyWaterPotion implements Potion { - private static final Logger LOGGER = LoggerFactory.getLogger(HolyWaterPotion.class); - @Override - public void drink() { - LOGGER.info("You feel blessed. (Potion={})", System.identityHashCode(this)); - } -} - -public class InvisibilityPotion implements Potion { - private static final Logger LOGGER = LoggerFactory.getLogger(InvisibilityPotion.class); - @Override - public void drink() { - LOGGER.info("You become invisible. (Potion={})", System.identityHashCode(this)); - } -} -``` - -Then the actual Flyweight object which is the factory for creating potions - -``` -public class PotionFactory { - - private final Map potions; - - public PotionFactory() { - potions = new EnumMap<>(PotionType.class); - } - - Potion createPotion(PotionType type) { - Potion potion = potions.get(type); - if (potion == null) { - switch (type) { - case HEALING: - potion = new HealingPotion(); - potions.put(type, potion); - break; - case HOLY_WATER: - potion = new HolyWaterPotion(); - potions.put(type, potion); - break; - case INVISIBILITY: - potion = new InvisibilityPotion(); - potions.put(type, potion); - break; - default: - break; - } - } - return potion; - } -} -``` - -And it can be used as below - -``` -PotionFactory factory = new PotionFactory(); -factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) -factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) -factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) -factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) -factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) -factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) -``` - -## Applicability -The Flyweight pattern's effectiveness depends heavily on how -and where it's used. Apply the Flyweight pattern when all of the following are -true - -* an application uses a large number of objects -* storage costs are high because of the sheer quantity of objects -* most object state can be made extrinsic -* many groups of objects may be replaced by relatively few shared objects once extrinsic state is removed -* the application doesn't depend on object identity. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects. - -## Real world examples - -* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) and similarly for Byte, Character and other wrapped types. - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/flyweight/pom.xml b/flyweight/pom.xml deleted file mode 100644 index 9814dc2df2ad..000000000000 --- a/flyweight/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - flyweight - - - junit - junit - test - - - diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java deleted file mode 100644 index 01320e082961..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * - * AlchemistShop holds potions on its shelves. It uses PotionFactory to provide the potions. - * - */ -public class AlchemistShop { - - private static final Logger LOGGER = LoggerFactory.getLogger(AlchemistShop.class); - - private List topShelf; - private List bottomShelf; - - /** - * Constructor - */ - public AlchemistShop() { - topShelf = new ArrayList<>(); - bottomShelf = new ArrayList<>(); - fillShelves(); - } - - private void fillShelves() { - - PotionFactory factory = new PotionFactory(); - - topShelf.add(factory.createPotion(PotionType.INVISIBILITY)); - topShelf.add(factory.createPotion(PotionType.INVISIBILITY)); - topShelf.add(factory.createPotion(PotionType.STRENGTH)); - topShelf.add(factory.createPotion(PotionType.HEALING)); - topShelf.add(factory.createPotion(PotionType.INVISIBILITY)); - topShelf.add(factory.createPotion(PotionType.STRENGTH)); - topShelf.add(factory.createPotion(PotionType.HEALING)); - topShelf.add(factory.createPotion(PotionType.HEALING)); - - bottomShelf.add(factory.createPotion(PotionType.POISON)); - bottomShelf.add(factory.createPotion(PotionType.POISON)); - bottomShelf.add(factory.createPotion(PotionType.POISON)); - bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER)); - bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER)); - } - - /** - * Get a read-only list of all the items on the top shelf - * - * @return The top shelf potions - */ - public final List getTopShelf() { - return Collections.unmodifiableList(this.topShelf); - } - - /** - * Get a read-only list of all the items on the bottom shelf - * - * @return The bottom shelf potions - */ - public final List getBottomShelf() { - return Collections.unmodifiableList(this.bottomShelf); - } - - /** - * Enumerate potions - */ - public void enumerate() { - - LOGGER.info("Enumerating top shelf potions\n"); - - for (Potion p : topShelf) { - p.drink(); - } - - LOGGER.info("Enumerating bottom shelf potions\n"); - - for (Potion p : bottomShelf) { - p.drink(); - } - } -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/App.java b/flyweight/src/main/java/com/iluwatar/flyweight/App.java deleted file mode 100644 index 043321b5f84a..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/App.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -/** - * - * Flyweight pattern is useful when the program needs a huge amount of objects. It provides means to - * decrease resource usage by sharing object instances. - *

    - * In this example {@link AlchemistShop} has great amount of potions on its shelves. To fill the - * shelves {@link AlchemistShop} uses {@link PotionFactory} (which represents the Flyweight in this - * example). Internally {@link PotionFactory} holds a map of the potions and lazily creates new ones - * when requested. - *

    - * To enable safe sharing, between clients and threads, Flyweight objects must be immutable. - * Flyweight objects are by definition value objects. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - AlchemistShop alchemistShop = new AlchemistShop(); - alchemistShop.enumerate(); - } -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java deleted file mode 100644 index 060aaea4ab05..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * HealingPotion - * - */ -public class HealingPotion implements Potion { - - private static final Logger LOGGER = LoggerFactory.getLogger(HealingPotion.class); - - @Override - public void drink() { - 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 deleted file mode 100644 index 1b14f56be7d1..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * HolyWaterPotion - * - */ -public class HolyWaterPotion implements Potion { - - private static final Logger LOGGER = LoggerFactory.getLogger(HolyWaterPotion.class); - - @Override - public void drink() { - 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 deleted file mode 100644 index 8baec7c13c4e..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * InvisibilityPotion - * - */ -public class InvisibilityPotion implements Potion { - - private static final Logger LOGGER = LoggerFactory.getLogger(InvisibilityPotion.class); - - @Override - public void drink() { - 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 deleted file mode 100644 index 8f6bc113f72b..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * PoisonPotion - * - */ -public class PoisonPotion implements Potion { - - private static final Logger LOGGER = LoggerFactory.getLogger(PoisonPotion.class); - - @Override - public void drink() { - LOGGER.info("Urgh! This is poisonous. (Potion={})", System.identityHashCode(this)); - } -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/Potion.java b/flyweight/src/main/java/com/iluwatar/flyweight/Potion.java deleted file mode 100644 index c6ce38760a5d..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/Potion.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -/** - * - * Interface for Potions. - * - */ -public interface Potion { - - void drink(); -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/PotionFactory.java b/flyweight/src/main/java/com/iluwatar/flyweight/PotionFactory.java deleted file mode 100644 index c93707000547..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/PotionFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import java.util.EnumMap; -import java.util.Map; - -/** - * - * PotionFactory is the Flyweight in this example. It minimizes memory use by sharing object - * instances. It holds a map of potion instances and new potions are created only when none of the - * type already exists. - * - */ -public class PotionFactory { - - private final Map potions; - - public PotionFactory() { - potions = new EnumMap<>(PotionType.class); - } - - Potion createPotion(PotionType type) { - Potion potion = potions.get(type); - if (potion == null) { - switch (type) { - case HEALING: - potion = new HealingPotion(); - potions.put(type, potion); - break; - case HOLY_WATER: - potion = new HolyWaterPotion(); - potions.put(type, potion); - break; - case INVISIBILITY: - potion = new InvisibilityPotion(); - potions.put(type, potion); - break; - case POISON: - potion = new PoisonPotion(); - potions.put(type, potion); - break; - case STRENGTH: - potion = new StrengthPotion(); - potions.put(type, potion); - break; - default: - break; - } - } - return potion; - } -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/PotionType.java b/flyweight/src/main/java/com/iluwatar/flyweight/PotionType.java deleted file mode 100644 index 3ee938838b06..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/PotionType.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -/** - * - * Enumeration for potion types. - * - */ -public enum PotionType { - - HEALING, INVISIBILITY, STRENGTH, HOLY_WATER, POISON -} diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java deleted file mode 100644 index 787e717fce62..000000000000 --- a/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * StrengthPotion - * - */ -public class StrengthPotion implements Potion { - - private static final Logger LOGGER = LoggerFactory.getLogger(StrengthPotion.class); - - @Override - public void drink() { - LOGGER.info("You feel strong. (Potion={})", System.identityHashCode(this)); - } -} diff --git a/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java b/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java deleted file mode 100644 index 96cc455a7807..000000000000 --- a/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/12/15 - 10:54 PM - * - * @author Jeroen Meulemeester - */ -public class AlchemistShopTest { - - @Test - public void testShop() throws Exception { - final AlchemistShop shop = new AlchemistShop(); - - final List bottomShelf = shop.getBottomShelf(); - assertNotNull(bottomShelf); - assertEquals(5, bottomShelf.size()); - - final List topShelf = shop.getTopShelf(); - assertNotNull(topShelf); - assertEquals(8, topShelf.size()); - - final List allPotions = new ArrayList<>(); - allPotions.addAll(topShelf); - allPotions.addAll(bottomShelf); - - // There are 13 potion instances, but only 5 unique instance types - assertEquals(13, allPotions.size()); - assertEquals(5, allPotions.stream().map(System::identityHashCode).distinct().count()); - - } - -} diff --git a/flyweight/src/test/java/com/iluwatar/flyweight/AppTest.java b/flyweight/src/test/java/com/iluwatar/flyweight/AppTest.java deleted file mode 100644 index 5d2d6815f19b..000000000000 --- a/flyweight/src/test/java/com/iluwatar/flyweight/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.flyweight; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/front-controller/README.md b/front-controller/README.md deleted file mode 100644 index c832674dc13b..000000000000 --- a/front-controller/README.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: pattern -title: Front Controller -folder: front-controller -permalink: /patterns/front-controller/ -pumlid: PSlB3OGm303HLfO24j-t6nCC13bEvC_IFk6yjz6JPgbIE3OAvS_fFkmBe7Zde_ePQnXfwU8adajlK3bkT5Iuy8Tf8wk7f87kf6BGq6R0hlD8xwQTUG9v-SCSslA8nWy0 -categories: Presentation Tier -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Introduce a common handler for all requests for a web site. This -way we can encapsulate common functionality such as security, -internationalization, routing and logging in a single place. - -![alt text](./etc/front-controller.png "Front Controller") - -## Applicability -Use the Front Controller pattern when - -* you want to encapsulate common request handling functionality in single place -* you want to implements dynamic request handling i.e. change routing without modifying code -* make web server configuration portable, you only need to register the handler web server specific way - -## Real world examples - -* [Apache Struts](https://struts.apache.org/) - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) -* [Presentation Tier Patterns](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns) -* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420) diff --git a/front-controller/etc/front-controller.png b/front-controller/etc/front-controller.png deleted file mode 100644 index 77c14ef019cc2864c159a9600095e7117c479916..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27672 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/front-controller/etc/front-controller.urm.puml b/front-controller/etc/front-controller.urm.puml deleted file mode 100644 index 246e7657c4c5..000000000000 --- a/front-controller/etc/front-controller.urm.puml +++ /dev/null @@ -1,53 +0,0 @@ -@startuml -package com.iluwatar.front.controller { - class App { - + App() - + main(args : String[]) {static} - } - class ArcherCommand { - + ArcherCommand() - + process() - } - class ArcherView { - - LOGGER : Logger {static} - + ArcherView() - + display() - } - class CatapultCommand { - + CatapultCommand() - + process() - } - class CatapultView { - - LOGGER : Logger {static} - + CatapultView() - + display() - } - interface Command { - + process() {abstract} - } - class ErrorView { - - LOGGER : Logger {static} - + ErrorView() - + display() - } - class FrontController { - + FrontController() - - getCommand(request : String) : Command - - getCommandClass(request : String) : Class {static} - + handleRequest(request : String) - } - class UnknownCommand { - + UnknownCommand() - + process() - } - interface View { - + display() {abstract} - } -} -ArcherCommand ..|> Command -ArcherView ..|> View -CatapultCommand ..|> Command -CatapultView ..|> View -ErrorView ..|> View -UnknownCommand ..|> Command -@enduml \ No newline at end of file diff --git a/front-controller/pom.xml b/front-controller/pom.xml deleted file mode 100644 index b9080bda7839..000000000000 --- a/front-controller/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - front-controller - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/App.java b/front-controller/src/main/java/com/iluwatar/front/controller/App.java deleted file mode 100644 index 92f43e363d9c..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/App.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * The Front Controller is a presentation tier pattern. Essentially it defines a controller that - * handles all requests for a web site. - *

    - * The Front Controller pattern consolidates request handling through a single handler object ( - * {@link FrontController}). This object can carry out the common the behavior such as - * authorization, request logging and routing requests to corresponding views. - *

    - * Typically the requests are mapped to command objects ({@link Command}) which then display the - * correct view ({@link View}). - *

    - * In this example we have implemented two views: {@link ArcherView} and {@link CatapultView}. These - * are displayed by sending correct request to the {@link FrontController} object. For example, the - * {@link ArcherView} gets displayed when {@link FrontController} receives request "Archer". When - * the request is unknown, we display the error view ({@link ErrorView}). - * - */ -public class App { - - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - FrontController controller = new FrontController(); - controller.handleRequest("Archer"); - controller.handleRequest("Catapult"); - controller.handleRequest("foobar"); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java b/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java deleted file mode 100644 index 882784bbfe4f..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Custom exception type - * - */ -public class ApplicationException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public ApplicationException(Throwable cause) { - super(cause); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java deleted file mode 100644 index b1bb77d3cd4b..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Command for archers. - * - */ -public class ArcherCommand implements Command { - - @Override - public void process() { - new ArcherView().display(); - } -} 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 deleted file mode 100644 index af6c72d0d962..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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() { - LOGGER.info("Displaying archers"); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java deleted file mode 100644 index e5cc47043819..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Command for catapults. - * - */ -public class CatapultCommand implements Command { - - @Override - public void process() { - new CatapultView().display(); - } -} 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 deleted file mode 100644 index 2191fcaa6d03..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * View for catapults. - * - */ -public class CatapultView implements View { - - private static final Logger LOGGER = LoggerFactory.getLogger(CatapultView.class); - - @Override - public void display() { - LOGGER.info("Displaying catapults"); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/Command.java b/front-controller/src/main/java/com/iluwatar/front/controller/Command.java deleted file mode 100644 index 998d7dea87f7..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/Command.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Commands are the intermediary between requests and views. - * - */ -public interface Command { - - void process(); -} 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 deleted file mode 100644 index 22961ef7b880..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * View for errors. - * - */ -public class ErrorView implements View { - - private static final Logger LOGGER = LoggerFactory.getLogger(ErrorView.class); - - @Override - public void display() { - LOGGER.error("Error 500"); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java deleted file mode 100644 index 19f4a39f1812..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * FrontController is the handler class that takes in all the requests and renders the correct - * response. - * - */ -public class FrontController { - - public void handleRequest(String request) { - Command command = getCommand(request); - command.process(); - } - - private Command getCommand(String request) { - Class commandClass = getCommandClass(request); - try { - return (Command) commandClass.newInstance(); - } catch (Exception e) { - throw new ApplicationException(e); - } - } - - private static Class getCommandClass(String request) { - Class result; - try { - result = Class.forName("com.iluwatar.front.controller." + request + "Command"); - } catch (ClassNotFoundException e) { - result = UnknownCommand.class; - } - return result; - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java deleted file mode 100644 index ad888bf9ebc6..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Default command in case the mapping is not successful. - * - */ -public class UnknownCommand implements Command { - - @Override - public void process() { - new ErrorView().display(); - } -} diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/View.java b/front-controller/src/main/java/com/iluwatar/front/controller/View.java deleted file mode 100644 index ad43d0b026f0..000000000000 --- a/front-controller/src/main/java/com/iluwatar/front/controller/View.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -/** - * - * Views are the representations rendered for the user. - * - */ -public interface View { - - void display(); -} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java deleted file mode 100644 index dd15be495ebc..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java deleted file mode 100644 index c68a4ebf6b35..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.front.controller; - -import static org.junit.Assert.assertSame; - -import org.junit.Test; - -/** - * Date: 12/13/15 - 1:35 PM - * - * @author Jeroen Meulemeester - */ -public class ApplicationExceptionTest { - - @Test - public void testCause() throws Exception { - final Exception cause = new Exception(); - assertSame(cause, new ApplicationException(cause).getCause()); - } - -} \ No newline at end of file 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 deleted file mode 100644 index edb5032ed1d7..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import org.junit.runners.Parameterized.Parameters; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/13/15 - 1:39 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class CommandTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - @Parameters - public static List data() { - final List parameters = new ArrayList<>(); - parameters.add(new Object[]{"Archer", "Displaying archers"}); - parameters.add(new Object[]{"Catapult", "Displaying catapults"}); - parameters.add(new Object[]{"NonExistentCommand", "Error 500"}); - return parameters; - } - - /** - * The view that's been tested - */ - private final String request; - - /** - * The expected display message - */ - private final String displayMessage; - - /** - * Create a new instance of the {@link CommandTest} with the given view and expected message - * - * @param request The request that's been tested - * @param displayMessage The expected display message - */ - public CommandTest(final String request, final String displayMessage) { - this.displayMessage = displayMessage; - this.request = request; - } - - @Test - public void testDisplay() { - final FrontController frontController = new FrontController(); - assertEquals(0, appender.getLogSize()); - frontController.handleRequest(request); - 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 deleted file mode 100644 index 5367403f97dc..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import org.junit.runners.Parameterized.Parameters; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/13/15 - 1:39 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class FrontControllerTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - @Parameters - public static List data() { - final List parameters = new ArrayList<>(); - parameters.add(new Object[]{new ArcherCommand(), "Displaying archers"}); - parameters.add(new Object[]{new CatapultCommand(), "Displaying catapults"}); - parameters.add(new Object[]{new UnknownCommand(), "Error 500"}); - return parameters; - } - - /** - * The view that's been tested - */ - private final Command command; - - /** - * The expected display message - */ - private final String displayMessage; - - /** - * Create a new instance of the {@link FrontControllerTest} with the given view and expected message - * - * @param command The command that's been tested - * @param displayMessage The expected display message - */ - public FrontControllerTest(final Command command, final String displayMessage) { - this.displayMessage = displayMessage; - this.command = command; - } - - @Test - public void testDisplay() { - assertEquals(0, appender.getLogSize()); - this.command.process(); - assertEquals(displayMessage, appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - -} 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 deleted file mode 100644 index a5786b97ebc4..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import org.junit.runners.Parameterized.Parameters; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/13/15 - 1:39 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class ViewTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - @Parameters - public static List data() { - final List parameters = new ArrayList<>(); - parameters.add(new Object[]{new ArcherView(), "Displaying archers"}); - parameters.add(new Object[]{new CatapultView(), "Displaying catapults"}); - parameters.add(new Object[]{new ErrorView(), "Error 500"}); - return parameters; - } - - /** - * The view that's been tested - */ - private final View view; - - /** - * The expected display message - */ - private final String displayMessage; - - /** - * Create a new instance of the {@link ViewTest} with the given view and expected message - * - * @param view The view that's been tested - * @param displayMessage The expected display message - */ - public ViewTest(final View view, final String displayMessage) { - this.displayMessage = displayMessage; - this.view = view; - } - - @Test - public void testDisplay() { - assertEquals(0, appender.getLogSize()); - this.view.display(); - assertEquals(displayMessage, appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - -} 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 deleted file mode 100644 index 2e6f26c0c668..000000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * InMemory Log Appender Util. - */ -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/guarded-suspension/README.md b/guarded-suspension/README.md deleted file mode 100644 index 3e00539a231e..000000000000 --- a/guarded-suspension/README.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: pattern -title: Guarded Suspension -folder: guarded-suspension -permalink: /patterns/guarded-suspension/ -pumlid: ROux3W8n30LxJW47IDnJxLLCOcMD4YVoXxq-eQTwev56UeSvgiVejmTBwL4fjDzFzsLF0CKhD_OpNc6aPOgJU2vp0FUuSAVmnW-cIiPDqa9tKZ4OQ1kW1MgbcYniaHXF0VBoH-VGaTVlnK5Iztu1 -categories: Concurrency -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Use Guarded suspension pattern to handle a situation when you want to execute a method on object which is not in a proper state. - -![Guarded Suspension diagram](./etc/guarded-suspension.png) - -## Applicability -Use Guarded Suspension pattern when the developer knows that the method execution will be blocked for a finite period of time - -## Related patterns -* Balking diff --git a/guarded-suspension/etc/guarded-suspension.png b/guarded-suspension/etc/guarded-suspension.png deleted file mode 100644 index bd3fa5661fab47538fb3df095fecd6bbfba7217b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10318 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 diff --git a/guarded-suspension/etc/guarded-suspension.ucls b/guarded-suspension/etc/guarded-suspension.ucls deleted file mode 100644 index 2e46325e44c4..000000000000 --- a/guarded-suspension/etc/guarded-suspension.ucls +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/guarded-suspension/etc/guarded-suspension.urm.puml b/guarded-suspension/etc/guarded-suspension.urm.puml deleted file mode 100644 index 45a7d37904cb..000000000000 --- a/guarded-suspension/etc/guarded-suspension.urm.puml +++ /dev/null @@ -1,15 +0,0 @@ -@startuml -package com.iluwatar.guarded.suspension { - class App { - + App() - + main(args : String[]) {static} - } - class GuardedQueue { - - LOGGER : Logger {static} - - sourceList : Queue - + GuardedQueue() - + get() : Integer - + put(e : Integer) - } -} -@enduml \ No newline at end of file diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml deleted file mode 100644 index bcc9ead0639f..000000000000 --- a/guarded-suspension/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - jar - guarded-suspension - - - junit - junit - test - - - \ No newline at end of file diff --git a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/App.java b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/App.java deleted file mode 100644 index 8747c84e5809..000000000000 --- a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/App.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. - */ -/** - * Guarded-suspension is a concurrent design pattern for handling situation when to execute some action we need - * condition to be satisfied. - *

    - * Implementation is based on GuardedQueue, which has two methods: get and put, - * the condition is that we cannot get from empty queue so when thread attempt - * to break the condition we invoke Object's wait method on him and when other thread put an element - * to the queue he notify the waiting one that now he can get from queue. - */ -package com.iluwatar.guarded.suspension; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * Created by robertt240 on 1/26/17. - */ -public class App { - /** - * Example pattern execution - * - * @param args - command line args - */ - public static void main(String[] args) { - GuardedQueue guardedQueue = new GuardedQueue(); - ExecutorService executorService = Executors.newFixedThreadPool(3); - - //here we create first thread which is supposed to get from guardedQueue - executorService.execute(() -> { - guardedQueue.get(); - } - ); - - //here we wait two seconds to show that the thread which is trying to get from guardedQueue will be waiting - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //now we execute second thread which will put number to guardedQueue and notify first thread that it could get - executorService.execute(() -> { - guardedQueue.put(20); - } - ); - executorService.shutdown(); - try { - executorService.awaitTermination(30, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - -} diff --git a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java deleted file mode 100644 index bf6142dd966e..000000000000 --- a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java +++ /dev/null @@ -1,70 +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.guarded.suspension; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.Queue; - -/** - * Guarded Queue is an implementation for Guarded Suspension Pattern - * Guarded suspension pattern is used to handle a situation when you want to execute a method - * on an object which is not in a proper state. - * @see http://java-design-patterns.com/patterns/guarded-suspension/ - */ -public class GuardedQueue { - private static final Logger LOGGER = LoggerFactory.getLogger(GuardedQueue.class); - private final Queue sourceList; - - public GuardedQueue() { - this.sourceList = new LinkedList<>(); - } - - /** - * @return last element of a queue if queue is not empty - */ - public synchronized Integer get() { - while (sourceList.isEmpty()) { - try { - LOGGER.info("waiting"); - wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - LOGGER.info("getting"); - return sourceList.peek(); - } - - /** - * @param e number which we want to put to our queue - */ - public synchronized void put(Integer e) { - LOGGER.info("putting"); - sourceList.add(e); - LOGGER.info("notifying"); - notify(); - } -} diff --git a/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java b/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java deleted file mode 100644 index 5a741d399bf9..000000000000 --- a/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java +++ /dev/null @@ -1,61 +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. - *

    - * PROBLEM
    - * A concurrent system have a mixture of short duration, mid duration and long duration tasks. Mid - * or long duration tasks should be performed asynchronously to meet quality of service - * requirements. - * - *

    - * INTENT
    - * The intent of this pattern is to separate the the synchronous and asynchronous processing in the - * concurrent application by introducing two intercommunicating layers - one for sync and one for - * async. This simplifies the programming without unduly affecting the performance. - * - *

    - * APPLICABILITY
    - * UNIX network subsystems - In operating systems network operations are carried out - * asynchronously with help of hardware level interrupts.
    - * CORBA - At the asynchronous layer one thread is associated with each socket that is connected - * to the client. Thread blocks waiting for CORBA requests from the client. On receiving request it - * is inserted in the queuing layer which is then picked up by synchronous layer which processes the - * request and sends response back to the client.
    - * Android AsyncTask framework - Framework provides a way to execute long running blocking - * calls, such as downloading a file, in background threads so that the UI thread remains free to - * respond to user inputs.
    - * - *

    - * IMPLEMENTATION
    - * The main method creates an asynchronous service which does not block the main thread while the - * task is being performed. The main thread continues its work which is similar to Async Method - * Invocation pattern. The difference between them is that there is a queuing layer between - * Asynchronous layer and synchronous layer, which allows for different communication patterns - * between both layers. Such as Priority Queue can be used as queuing layer to prioritize the way - * tasks are executed. Our implementation is just one simple way of implementing this pattern, there - * are many variants possible as described in its applications. - * - */ -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) { - AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); - /* - * A new task to calculate sum is received but as this is main thread, it should not block. So - * it passes it to the asynchronous task layer to compute and proceeds with handling other - * incoming requests. This is particularly useful when main thread is waiting on Socket to - * receive new incoming requests and does not wait for particular request to be completed before - * responding to new request. - */ - service.execute(new ArithmeticSumTask(1000)); - - /* - * New task received, lets pass that to async layer for computation. So both requests will be - * executed in parallel. - */ - service.execute(new ArithmeticSumTask(500)); - service.execute(new ArithmeticSumTask(2000)); - service.execute(new ArithmeticSumTask(1)); - } - - /** - * - * ArithmeticSumTask - * - */ - static class ArithmeticSumTask implements AsyncTask { - private long n; - - public ArithmeticSumTask(long n) { - this.n = n; - } - - /* - * This is the long running task that is performed in background. In our example the long - * running task is calculating arithmetic sum with artificial delay. - */ - @Override - public Long call() throws Exception { - return ap(n); - } - - /* - * This will be called in context of the main thread where some validations can be done - * regarding the inputs. Such as it must be greater than 0. It's a small computation which can - * be performed in main thread. If we did validated the input in background thread then we pay - * the cost of context switching which is much more than validating it in main thread. - */ - @Override - public void onPreCall() { - if (n < 0) { - throw new IllegalArgumentException("n is less than 0"); - } - } - - @Override - public void onPostCall(Long result) { - // Handle the result of computation - LOGGER.info(result.toString()); - } - - @Override - public void onError(Throwable throwable) { - throw new IllegalStateException("Should not occur"); - } - } - - private static long ap(long i) { - try { - Thread.sleep(i); - } catch (InterruptedException e) { - LOGGER.error("Exception caught.", e); - } - return i * (i + 1) / 2; - } -} diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java deleted file mode 100644 index 2751b98709e4..000000000000 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.halfsynchalfasync; - -import java.util.concurrent.Callable; - -/** - * Represents some computation that is performed asynchronously and its result. The computation is - * typically done is background threads and the result is posted back in form of callback. The - * callback does not implement {@code isComplete}, {@code cancel} as it is out of scope of this - * pattern. - * - * @param type of result - */ -public interface AsyncTask extends Callable { - /** - * Is called in context of caller thread before call to {@link #call()}. Large tasks should not be - * performed in this method as it will block the caller thread. Small tasks such as validations - * can be performed here so that the performance penalty of context switching is not incurred in - * case of invalid requests. - */ - void onPreCall(); - - /** - * A callback called after the result is successfully computed by {@link #call()}. In our - * implementation this method is called in context of background thread but in some variants, such - * as Android where only UI thread can change the state of UI widgets, this method is called in - * context of UI thread. - */ - void onPostCall(O result); - - /** - * A callback called if computing the task resulted in some exception. This method is called when - * either of {@link #call()} or {@link #onPreCall()} throw any exception. - * - * @param throwable error cause - */ - void onError(Throwable throwable); - - /** - * This is where the computation of task should reside. This method is called in context of - * background thread. - */ - @Override - O call() throws Exception; -} diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java deleted file mode 100644 index 4e2f9c23a6cd..000000000000 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.halfsynchalfasync; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.FutureTask; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * This is the asynchronous layer which does not block when a new request arrives. It just passes - * the request to the synchronous layer which consists of a queue i.e. a {@link BlockingQueue} and a - * pool of threads i.e. {@link ThreadPoolExecutor}. Out of this pool of worker threads one of the - * thread picks up the task and executes it synchronously in background and the result is posted - * back to the caller via callback. - */ -public class AsynchronousService { - - /* - * This represents the queuing layer as well as synchronous layer of the pattern. The thread pool - * contains worker threads which execute the tasks in blocking/synchronous manner. Long running - * tasks should be performed in the background which does not affect the performance of main - * thread. - */ - private ExecutorService service; - - /** - * Creates an asynchronous service using {@code workQueue} as communication channel between - * asynchronous layer and synchronous layer. Different types of queues such as Priority queue, can - * be used to control the pattern of communication between the layers. - */ - public AsynchronousService(BlockingQueue workQueue) { - service = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, workQueue); - } - - - /** - * A non-blocking method which performs the task provided in background and returns immediately. - *

    - * On successful completion of task the result is posted back using callback method - * {@link AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally due to - * some exception then the reason for error is posted back using callback method - * {@link AsyncTask#onError(Throwable)}. - *

    - * NOTE: The results are posted back in the context of background thread in this implementation. - */ - public void execute(final AsyncTask task) { - try { - // some small tasks such as validation can be performed here. - task.onPreCall(); - } catch (Exception e) { - task.onError(e); - return; - } - - service.submit(new FutureTask(task) { - @Override - protected void done() { - super.done(); - try { - /* - * called in context of background thread. There is other variant possible where result is - * posted back and sits in the queue of caller thread which then picks it up for - * processing. An example of such a system is Android OS, where the UI elements can only - * be updated using UI thread. So result must be posted back in UI thread. - */ - task.onPostCall(get()); - } catch (InterruptedException e) { - // should not occur - } catch (ExecutionException e) { - task.onError(e.getCause()); - } - } - }); - } -} diff --git a/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AppTest.java b/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AppTest.java deleted file mode 100644 index 2dfc2bf5cbd3..000000000000 --- a/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.halfsynchalfasync; - -import java.util.concurrent.ExecutionException; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws InterruptedException, ExecutionException { - App.main(null); - } -} diff --git a/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java b/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java deleted file mode 100644 index c6d00b1ac454..000000000000 --- a/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.halfsynchalfasync; - -import org.junit.Test; -import org.mockito.InOrder; - -import java.io.IOException; -import java.util.concurrent.LinkedBlockingQueue; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; - -/** - * Date: 12/12/15 - 11:15 PM - * - * @author Jeroen Meulemeester - */ -public class AsynchronousServiceTest { - - @Test - public void testPerfectExecution() throws Exception { - final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); - final AsyncTask task = mock(AsyncTask.class); - final Object result = new Object(); - when(task.call()).thenReturn(result); - service.execute(task); - - verify(task, timeout(2000)).onPostCall(eq(result)); - - final InOrder inOrder = inOrder(task); - inOrder.verify(task, times(1)).onPreCall(); - inOrder.verify(task, times(1)).call(); - inOrder.verify(task, times(1)).onPostCall(eq(result)); - - verifyNoMoreInteractions(task); - } - - @Test - public void testCallException() throws Exception { - final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); - final AsyncTask task = mock(AsyncTask.class); - final IOException exception = new IOException(); - when(task.call()).thenThrow(exception); - service.execute(task); - - verify(task, timeout(2000)).onError(eq(exception)); - - final InOrder inOrder = inOrder(task); - inOrder.verify(task, times(1)).onPreCall(); - inOrder.verify(task, times(1)).call(); - inOrder.verify(task, times(1)).onError(exception); - - verifyNoMoreInteractions(task); - } - - @Test - public void testPreCallException() throws Exception { - final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); - final AsyncTask task = mock(AsyncTask.class); - final IllegalStateException exception = new IllegalStateException(); - doThrow(exception).when(task).onPreCall(); - service.execute(task); - - verify(task, timeout(2000)).onError(eq(exception)); - - final InOrder inOrder = inOrder(task); - inOrder.verify(task, times(1)).onPreCall(); - inOrder.verify(task, times(1)).onError(exception); - - verifyNoMoreInteractions(task); - } - -} \ No newline at end of file diff --git a/hexagonal/README.md b/hexagonal/README.md deleted file mode 100644 index dc1566625d9a..000000000000 --- a/hexagonal/README.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -layout: pattern -title: Hexagonal Architecture -folder: hexagonal -permalink: /patterns/hexagonal/ -pumlid: HSTB4W8X30N0g-W1XkozpPD90LO8L3wEnzUTk-xxq2fvSfhSUiJs1v7XAcr4psSwMrqQh57gcZGaBmICNdZZEDb7qsCZWasT9lm7wln1MmeXZlfVIPjbvvGl -pumlformat: svg -categories: Architectural -tags: - - Java - - Difficulty-Expert ---- - -## Also known as -* Ports and Adapters -* Clean Architecture -* Onion Architecture - -## Intent -Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases. - -![Hexagonal Architecture class diagram](./etc/hexagonal.png) - -## Applicability -Use Hexagonal Architecture pattern when - -* When the application needs to be independent of any frameworks -* When it is important that the application highly maintainable and fully testable - -## Tutorials -* [Build Maintainable Systems With Hexagonal Architecture](http://java-design-patterns.com/blog/build-maintainable-systems-with-hexagonal-architecture/) - -## Presentations -* [Hexagonal Architecture](https://github.com/iluwatar/java-design-patterns/tree/master/hexagonal/etc/presentation.html) - -## Real world examples - -* [Apache Isis](https://isis.apache.org/) builds generic UI and REST API directly from the underlying domain objects - -## Credits - -* [Alistair Cockburn - Hexagonal Architecture](http://alistair.cockburn.us/Hexagonal+architecture) diff --git a/hexagonal/etc/hexagonal.png b/hexagonal/etc/hexagonal.png deleted file mode 100644 index 1ad077fd4fd0e9874c2f85f3f488ead2e3fe7ffc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148602 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�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 A!2kdN diff --git a/hexagonal/etc/hexagonal.ucls b/hexagonal/etc/hexagonal.ucls deleted file mode 100644 index d3b46b23d08e..000000000000 --- a/hexagonal/etc/hexagonal.ucls +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hexagonal/etc/hexagonal.urm.puml b/hexagonal/etc/hexagonal.urm.puml deleted file mode 100644 index 9ca6e6f9f788..000000000000 --- a/hexagonal/etc/hexagonal.urm.puml +++ /dev/null @@ -1,279 +0,0 @@ -@startuml -package com.iluwatar.hexagonal.sampledata { - class SampleData { - - PLAYERS : List {static} - + SampleData() - - getRandomPlayerDetails() : PlayerDetails {static} - + submitTickets(lotteryService : LotteryService, numTickets : int) {static} - } -} -package com.iluwatar.hexagonal.service { - class ConsoleLottery { - - LOGGER : Logger {static} - + ConsoleLottery() - - addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner) {static} - - checkTicket(service : LotteryService, scanner : Scanner) {static} - + main(args : String[]) {static} - - printMainMenu() {static} - - queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner) {static} - - readString(scanner : Scanner) : String {static} - - submitTicket(service : LotteryService, scanner : Scanner) {static} - } -} -package com.iluwatar.hexagonal.mongo { - class MongoConnectionPropertiesLoader { - - DEFAULT_HOST : String {static} - - DEFAULT_PORT : int {static} - + MongoConnectionPropertiesLoader() - + load() {static} - } -} -package com.iluwatar.hexagonal.domain { - class LotteryAdministration { - - notifications : LotteryEventLog - - repository : LotteryTicketRepository - - wireTransfers : WireTransfers - + LotteryAdministration(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) - + getAllSubmittedTickets() : Map - + performLottery() : LotteryNumbers - + resetLottery() - } - class LotteryConstants { - + PLAYER_MAX_SALDO : int {static} - + PRIZE_AMOUNT : int {static} - + SERVICE_BANK_ACCOUNT : String {static} - + SERVICE_BANK_ACCOUNT_SALDO : int {static} - + TICKET_PRIZE : int {static} - - LotteryConstants() - } - class LotteryNumbers { - + MAX_NUMBER : int {static} - + MIN_NUMBER : int {static} - + NUM_NUMBERS : int {static} - - numbers : Set - - LotteryNumbers() - - LotteryNumbers(givenNumbers : Set) - + create(givenNumbers : Set) : LotteryNumbers {static} - + createRandom() : LotteryNumbers {static} - + equals(obj : Object) : boolean - - generateRandomNumbers() - + getNumbers() : Set - + getNumbersAsString() : String - + hashCode() : int - + toString() : String - } - -class RandomNumberGenerator { - - randomIterator : OfInt - + RandomNumberGenerator(min : int, max : int) - + nextInt() : int - } - class LotteryService { - - notifications : LotteryEventLog - - repository : LotteryTicketRepository - - wireTransfers : WireTransfers - + LotteryService(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) - + checkTicketForPrize(id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult - + submitTicket(ticket : LotteryTicket) : Optional - } - class LotteryTicket { - - id : LotteryTicketId - - lotteryNumbers : LotteryNumbers - - playerDetails : PlayerDetails - + LotteryTicket(id : LotteryTicketId, details : PlayerDetails, numbers : LotteryNumbers) - + equals(obj : Object) : boolean - + getId() : LotteryTicketId - + getNumbers() : LotteryNumbers - + getPlayerDetails() : PlayerDetails - + hashCode() : int - + setId(id : LotteryTicketId) - + toString() : String - } - class LotteryTicketCheckResult { - - checkResult : CheckResult - - prizeAmount : int - + LotteryTicketCheckResult(result : CheckResult) - + LotteryTicketCheckResult(result : CheckResult, amount : int) - + equals(obj : Object) : boolean - + getPrizeAmount() : int - + getResult() : CheckResult - + hashCode() : int - } - enum CheckResult { - + NO_PRIZE {static} - + TICKET_NOT_SUBMITTED {static} - + WIN_PRIZE {static} - + valueOf(name : String) : CheckResult {static} - + values() : CheckResult[] {static} - } - class LotteryTicketId { - - id : int - - numAllocated : int {static} - + LotteryTicketId() - + LotteryTicketId(id : int) - + equals(o : Object) : boolean - + getId() : int - + hashCode() : int - + toString() : String - } - class LotteryUtils { - - LotteryUtils() - + checkTicketForPrize(repository : LotteryTicketRepository, id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult {static} - } - class PlayerDetails { - - bankAccountNumber : String - - emailAddress : String - - phoneNumber : String - + PlayerDetails(email : String, bankAccount : String, phone : String) - + equals(obj : Object) : boolean - + getBankAccount() : String - + getEmail() : String - + getPhoneNumber() : String - + hashCode() : int - + toString() : String - } -} -package com.iluwatar.hexagonal.banking { - class InMemoryBank { - - accounts : Map {static} - + InMemoryBank() - + getFunds(bankAccount : String) : int - + setFunds(bankAccount : String, amount : int) - + transferFunds(amount : int, sourceBackAccount : String, destinationBankAccount : String) : boolean - } - class MongoBank { - - DEFAULT_ACCOUNTS_COLLECTION : String {static} - - DEFAULT_DB : String {static} - - accountsCollection : MongoCollection - - database : MongoDatabase - - mongoClient : MongoClient - + MongoBank() - + MongoBank(dbName : String, accountsCollectionName : String) - + connect() - + connect(dbName : String, accountsCollectionName : String) - + getAccountsCollection() : MongoCollection - + getFunds(bankAccount : String) : int - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + setFunds(bankAccount : String, amount : int) - + transferFunds(amount : int, sourceBackAccount : String, destinationBankAccount : String) : boolean - } - interface WireTransfers { - + getFunds(String) : int {abstract} - + setFunds(String, int) {abstract} - + transferFunds(int, String, String) : boolean {abstract} - } -} -package com.iluwatar.hexagonal.database { - class InMemoryTicketRepository { - - tickets : Map {static} - + InMemoryTicketRepository() - + deleteAll() - + findAll() : Map - + findById(id : LotteryTicketId) : Optional - + save(ticket : LotteryTicket) : Optional - } - interface LotteryTicketRepository { - + deleteAll() {abstract} - + findAll() : Map {abstract} - + findById(LotteryTicketId) : Optional {abstract} - + save(LotteryTicket) : Optional {abstract} - } - class MongoTicketRepository { - - DEFAULT_COUNTERS_COLLECTION : String {static} - - DEFAULT_DB : String {static} - - DEFAULT_TICKETS_COLLECTION : String {static} - - countersCollection : MongoCollection - - database : MongoDatabase - - mongoClient : MongoClient - - ticketsCollection : MongoCollection - + MongoTicketRepository() - + MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String) - + connect() - + connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String) - + deleteAll() - - docToTicket(doc : Document) : LotteryTicket - + findAll() : Map - + findById(id : LotteryTicketId) : Optional - + getCountersCollection() : MongoCollection - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + getNextId() : int - + getTicketsCollection() : MongoCollection - - initCounters() - + save(ticket : LotteryTicket) : Optional - } -} -package com.iluwatar.hexagonal { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.hexagonal.administration { - class ConsoleAdministration { - - LOGGER : Logger {static} - + ConsoleAdministration() - + main(args : String[]) {static} - - printMainMenu() {static} - - readString(scanner : Scanner) : String {static} - } -} -package com.iluwatar.hexagonal.eventlog { - interface LotteryEventLog { - + prizeError(PlayerDetails, int) {abstract} - + ticketDidNotWin(PlayerDetails) {abstract} - + ticketSubmitError(PlayerDetails) {abstract} - + ticketSubmitted(PlayerDetails) {abstract} - + ticketWon(PlayerDetails, int) {abstract} - } - class MongoEventLog { - - DEFAULT_DB : String {static} - - DEFAULT_EVENTS_COLLECTION : String {static} - - database : MongoDatabase - - eventsCollection : MongoCollection - - mongoClient : MongoClient - - stdOutEventLog : StdOutEventLog - + MongoEventLog() - + MongoEventLog(dbName : String, eventsCollectionName : String) - + connect() - + connect(dbName : String, eventsCollectionName : String) - + getEventsCollection() : MongoCollection - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + prizeError(details : PlayerDetails, prizeAmount : int) - + ticketDidNotWin(details : PlayerDetails) - + ticketSubmitError(details : PlayerDetails) - + ticketSubmitted(details : PlayerDetails) - + ticketWon(details : PlayerDetails, prizeAmount : int) - } - class StdOutEventLog { - - LOGGER : Logger {static} - + StdOutEventLog() - + prizeError(details : PlayerDetails, prizeAmount : int) - + ticketDidNotWin(details : PlayerDetails) - + ticketSubmitError(details : PlayerDetails) - + ticketSubmitted(details : PlayerDetails) - + ticketWon(details : PlayerDetails, prizeAmount : int) - } -} -LotteryTicket --> "-playerDetails" PlayerDetails -MongoEventLog --> "-stdOutEventLog" StdOutEventLog -LotteryService --> "-wireTransfers" WireTransfers -LotteryAdministration --> "-notifications" LotteryEventLog -LotteryAdministration --> "-wireTransfers" WireTransfers -LotteryService --> "-notifications" LotteryEventLog -LotteryTicket --> "-id" LotteryTicketId -LotteryAdministration --> "-repository" LotteryTicketRepository -LotteryTicket --> "-lotteryNumbers" LotteryNumbers -SampleData --> "-PLAYERS" PlayerDetails -RandomNumberGenerator ..+ LotteryNumbers -LotteryService --> "-repository" LotteryTicketRepository -CheckResult ..+ LotteryTicketCheckResult -LotteryTicketCheckResult --> "-checkResult" CheckResult -InMemoryBank ..|> WireTransfers -MongoBank ..|> WireTransfers -InMemoryTicketRepository ..|> LotteryTicketRepository -MongoTicketRepository ..|> LotteryTicketRepository -MongoEventLog ..|> LotteryEventLog -StdOutEventLog ..|> LotteryEventLog -@enduml \ No newline at end of file diff --git a/hexagonal/etc/layers.png b/hexagonal/etc/layers.png deleted file mode 100644 index cb5a9c90bbe953ff87197bfb1834c34fac450f3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15887 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 Kh}Vc32LC_vUU`lH diff --git a/hexagonal/etc/ports_and_adapters.png b/hexagonal/etc/ports_and_adapters.png deleted file mode 100644 index d285045dea68721c586bbfae5d303265f738eea0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34860 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 diff --git a/hexagonal/etc/ports_and_adapters.xml b/hexagonal/etc/ports_and_adapters.xml deleted file mode 100644 index 9df3173d902e..000000000000 --- a/hexagonal/etc/ports_and_adapters.xml +++ /dev/null @@ -1,25 +0,0 @@ - -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 deleted file mode 100644 index 5c6d1d0a5c6a..000000000000 --- a/hexagonal/etc/presentation.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - Title - - - - - - - - - - diff --git a/hexagonal/pom.xml b/hexagonal/pom.xml deleted file mode 100644 index 940a7fc61210..000000000000 --- a/hexagonal/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - hexagonal - - - junit - junit - test - - - com.google.inject - guice - - - org.mongodb - mongo-java-driver - - - diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java deleted file mode 100644 index 6514986075fb..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.iluwatar.hexagonal.domain.LotteryAdministration; -import com.iluwatar.hexagonal.domain.LotteryService; -import com.iluwatar.hexagonal.module.LotteryTestingModule; -import com.iluwatar.hexagonal.sampledata.SampleData; - -/** - * - * Hexagonal Architecture pattern decouples the application core from the - * services it uses. This allows the services to be plugged in and the - * application will run with or without the services.

    - * - * The core logic, or business logic, of an application consists of the - * algorithms that are essential to its purpose. They implement the use - * cases that are the heart of the application. When you change them, you - * change the essence of the application.

    - * - * The services are not essential. They can be replaced without changing - * the purpose of the application. Examples: database access and other - * types of storage, user interface components, e-mail and other - * communication components, hardware devices.

    - * - * This example demonstrates Hexagonal Architecture with a lottery system. - * The application core is separate from the services that drive it and - * from the services it uses.

    - * - * The primary ports for the application are console interfaces - * {@link ConsoleAdministration} through which the lottery round is - * initiated and run and {@link ConsoleLottery} that allows players to - * submit lottery tickets for the draw.

    - * - * The secondary ports that application core uses are {@link WireTransfers} - * which is a banking service, {@link LotteryEventLog} that delivers - * eventlog as lottery events occur and {@link LotteryTicketRepository} - * that is the storage for the lottery tickets. - * - */ -public class App { - - /** - * Program entry point - */ - public static void main(String[] args) { - - Injector injector = Guice.createInjector(new LotteryTestingModule()); - - // start new lottery round - LotteryAdministration administartion = injector.getInstance(LotteryAdministration.class); - administartion.resetLottery(); - - // submit some lottery tickets - LotteryService service = injector.getInstance(LotteryService.class); - SampleData.submitTickets(service, 20); - - // perform lottery - administartion.performLottery(); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java deleted file mode 100644 index 9dc20f87c63e..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.administration; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.iluwatar.hexagonal.domain.LotteryAdministration; -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryService; -import com.iluwatar.hexagonal.module.LotteryModule; -import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; -import com.iluwatar.hexagonal.sampledata.SampleData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Scanner; - -/** - * Console interface for lottery administration - */ -public class ConsoleAdministration { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleAdministration.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - MongoConnectionPropertiesLoader.load(); - Injector injector = Guice.createInjector(new LotteryModule()); - LotteryAdministration administartion = injector.getInstance(LotteryAdministration.class); - LotteryService service = injector.getInstance(LotteryService.class); - SampleData.submitTickets(service, 20); - try (Scanner scanner = new Scanner(System.in)) { - boolean exit = false; - while (!exit) { - printMainMenu(); - String cmd = readString(scanner); - if ("1".equals(cmd)) { - administartion.getAllSubmittedTickets().forEach((k, v) -> LOGGER.info("Key: {}, Value: {}", k, v)); - } else if ("2".equals(cmd)) { - LotteryNumbers numbers = administartion.performLottery(); - LOGGER.info("The winning numbers: {}", numbers.getNumbersAsString()); - LOGGER.info("Time to reset the database for next round, eh?"); - } else if ("3".equals(cmd)) { - administartion.resetLottery(); - LOGGER.info("The lottery ticket database was cleared."); - } else if ("4".equals(cmd)) { - exit = true; - } else { - LOGGER.info("Unknown command: {}", cmd); - } - } - } - } - - private static void printMainMenu() { - 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) { - System.out.print("> "); - return scanner.next(); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java deleted file mode 100644 index a8eb7817c046..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.banking; - -import java.util.HashMap; -import java.util.Map; - -import com.iluwatar.hexagonal.domain.LotteryConstants; - -/** - * - * Banking implementation - * - */ -public class InMemoryBank implements WireTransfers { - - private static Map accounts = new HashMap<>(); - - static { - accounts.put(LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_SALDO); - } - - @Override - public void setFunds(String bankAccount, int amount) { - accounts.put(bankAccount, amount); - } - - @Override - public int getFunds(String bankAccount) { - return accounts.getOrDefault(bankAccount, 0); - } - - @Override - public boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount) { - if (accounts.getOrDefault(sourceBackAccount, 0) >= amount) { - accounts.put(sourceBackAccount, accounts.get(sourceBackAccount) - amount); - accounts.put(destinationBankAccount, accounts.get(destinationBankAccount) + amount); - return true; - } else { - return false; - } - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java deleted file mode 100644 index 7ccc829eda98..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.banking; - -import com.mongodb.MongoClient; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.UpdateOptions; -import org.bson.Document; - -import java.util.ArrayList; -import java.util.List; - -/** - * Mongo based banking adapter - */ -public class MongoBank implements WireTransfers { - - private static final String DEFAULT_DB = "lotteryDB"; - private static final String DEFAULT_ACCOUNTS_COLLECTION = "accounts"; - - private MongoClient mongoClient; - private MongoDatabase database; - private MongoCollection accountsCollection; - - /** - * Constructor - */ - public MongoBank() { - connect(); - } - - /** - * Constructor accepting parameters - */ - public MongoBank(String dbName, String accountsCollectionName) { - connect(dbName, accountsCollectionName); - } - - /** - * Connect to database with default parameters - */ - public void connect() { - connect(DEFAULT_DB, DEFAULT_ACCOUNTS_COLLECTION); - } - - /** - * Connect to database with given parameters - */ - public void connect(String dbName, String accountsCollectionName) { - if (mongoClient != null) { - mongoClient.close(); - } - mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - database = mongoClient.getDatabase(dbName); - accountsCollection = database.getCollection(accountsCollectionName); - } - - /** - * @return mongo client - */ - public MongoClient getMongoClient() { - return mongoClient; - } - - /** - * - * @return mongo database - */ - public MongoDatabase getMongoDatabase() { - return database; - } - - /** - * - * @return accounts collection - */ - public MongoCollection getAccountsCollection() { - return accountsCollection; - } - - - @Override - public void setFunds(String bankAccount, int amount) { - Document search = new Document("_id", bankAccount); - Document update = new Document("_id", bankAccount).append("funds", amount); - accountsCollection.updateOne(search, new Document("$set", update), new UpdateOptions().upsert(true)); - } - - @Override - public int getFunds(String bankAccount) { - Document search = new Document("_id", bankAccount); - List results = accountsCollection.find(search).limit(1).into(new ArrayList()); - if (results.size() > 0) { - return results.get(0).getInteger("funds"); - } else { - return 0; - } - } - - @Override - public boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount) { - int sourceFunds = getFunds(sourceBackAccount); - if (sourceFunds < amount) { - return false; - } else { - int destFunds = getFunds(destinationBankAccount); - setFunds(sourceBackAccount, sourceFunds - amount); - setFunds(destinationBankAccount, destFunds + amount); - return true; - } - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java deleted file mode 100644 index 670824cb898e..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.banking; - -/** - * - * Interface to bank accounts. - * - */ -public interface WireTransfers { - - /** - * Set amount of funds for bank account - */ - void setFunds(String bankAccount, int amount); - - /** - * Get amount of funds for bank account - */ - int getFunds(String bankAccount); - - /** - * Transfer funds from one bank account to another - */ - boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount); - -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java deleted file mode 100644 index f2f4c7db2053..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.database; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; - -/** - * - * Mock database for lottery tickets. - * - */ -public class InMemoryTicketRepository implements LotteryTicketRepository { - - private static Map tickets = new HashMap<>(); - - @Override - public Optional findById(LotteryTicketId id) { - LotteryTicket ticket = tickets.get(id); - if (ticket == null) { - return Optional.empty(); - } else { - return Optional.of(ticket); - } - } - - @Override - public Optional save(LotteryTicket ticket) { - LotteryTicketId id = new LotteryTicketId(); - tickets.put(id, ticket); - return Optional.of(id); - } - - @Override - public Map findAll() { - return tickets; - } - - @Override - public void deleteAll() { - tickets.clear(); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java deleted file mode 100644 index 5daf3af9c20c..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.database; - -import java.util.Map; -import java.util.Optional; - -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; - -/** - * - * Interface for accessing lottery tickets in database. - * - */ -public interface LotteryTicketRepository { - - /** - * Find lottery ticket by id - */ - Optional findById(LotteryTicketId id); - - /** - * Save lottery ticket - */ - Optional save(LotteryTicket ticket); - - /** - * Get all lottery tickets - */ - Map findAll(); - - /** - * Delete all lottery tickets - */ - void deleteAll(); - -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java deleted file mode 100644 index ac747d4eaf4e..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java +++ /dev/null @@ -1,195 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.database; - -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.domain.PlayerDetails; -import com.mongodb.MongoClient; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; -import org.bson.Document; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -/** - * Mongo lottery ticket database - */ -public class MongoTicketRepository implements LotteryTicketRepository { - - private static final String DEFAULT_DB = "lotteryDB"; - private static final String DEFAULT_TICKETS_COLLECTION = "lotteryTickets"; - private static final String DEFAULT_COUNTERS_COLLECTION = "counters"; - - private MongoClient mongoClient; - private MongoDatabase database; - private MongoCollection ticketsCollection; - private MongoCollection countersCollection; - - /** - * Constructor - */ - public MongoTicketRepository() { - connect(); - } - - /** - * Constructor accepting parameters - */ - public MongoTicketRepository(String dbName, String ticketsCollectionName, - String countersCollectionName) { - connect(dbName, ticketsCollectionName, countersCollectionName); - } - - /** - * Connect to database with default parameters - */ - public void connect() { - connect(DEFAULT_DB, DEFAULT_TICKETS_COLLECTION, DEFAULT_COUNTERS_COLLECTION); - } - - /** - * Connect to database with given parameters - */ - public void connect(String dbName, String ticketsCollectionName, - String countersCollectionName) { - if (mongoClient != null) { - mongoClient.close(); - } - mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - database = mongoClient.getDatabase(dbName); - ticketsCollection = database.getCollection(ticketsCollectionName); - countersCollection = database.getCollection(countersCollectionName); - if (countersCollection.count() <= 0) { - initCounters(); - } - } - - private void initCounters() { - Document doc = new Document("_id", "ticketId").append("seq", 1); - countersCollection.insertOne(doc); - } - - /** - * @return next ticket id - */ - public int getNextId() { - Document find = new Document("_id", "ticketId"); - Document increase = new Document("seq", 1); - Document update = new Document("$inc", increase); - Document result = countersCollection.findOneAndUpdate(find, update); - return result.getInteger("seq"); - } - - /** - * @return mongo client - */ - public MongoClient getMongoClient() { - return mongoClient; - } - - /** - * - * @return mongo database - */ - public MongoDatabase getMongoDatabase() { - return database; - } - - /** - * - * @return tickets collection - */ - public MongoCollection getTicketsCollection() { - return ticketsCollection; - } - - /** - * - * @return counters collection - */ - public MongoCollection getCountersCollection() { - return countersCollection; - } - - @Override - public Optional findById(LotteryTicketId id) { - Document find = new Document("ticketId", id.getId()); - List results = ticketsCollection.find(find).limit(1).into(new ArrayList()); - if (results.size() > 0) { - LotteryTicket lotteryTicket = docToTicket(results.get(0)); - return Optional.of(lotteryTicket); - } else { - return Optional.empty(); - } - } - - @Override - public Optional save(LotteryTicket ticket) { - int ticketId = getNextId(); - Document doc = new Document("ticketId", ticketId); - doc.put("email", ticket.getPlayerDetails().getEmail()); - doc.put("bank", ticket.getPlayerDetails().getBankAccount()); - doc.put("phone", ticket.getPlayerDetails().getPhoneNumber()); - doc.put("numbers", ticket.getNumbers().getNumbersAsString()); - ticketsCollection.insertOne(doc); - return Optional.of(new LotteryTicketId(ticketId)); - } - - @Override - public Map findAll() { - Map map = new HashMap<>(); - List docs = ticketsCollection.find(new Document()).into(new ArrayList()); - for (Document doc: docs) { - LotteryTicket lotteryTicket = docToTicket(doc); - map.put(lotteryTicket.getId(), lotteryTicket); - } - return map; - } - - @Override - public void deleteAll() { - ticketsCollection.deleteMany(new Document()); - } - - private LotteryTicket docToTicket(Document doc) { - PlayerDetails playerDetails = new PlayerDetails(doc.getString("email"), doc.getString("bank"), - doc.getString("phone")); - int[] numArray = Arrays.asList(doc.getString("numbers").split(",")).stream().mapToInt(Integer::parseInt).toArray(); - Set numbers = new HashSet<>(); - for (int num: numArray) { - numbers.add(num); - } - LotteryNumbers lotteryNumbers = LotteryNumbers.create(numbers); - return new LotteryTicket(new LotteryTicketId(doc.getInteger("ticketId")), playerDetails, lotteryNumbers); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java deleted file mode 100644 index b8681b57ecde..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import com.google.inject.Inject; -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.database.LotteryTicketRepository; -import com.iluwatar.hexagonal.eventlog.LotteryEventLog; - -import java.util.Map; - -/** - * - * Lottery administration implementation - * - */ -public class LotteryAdministration { - - private final LotteryTicketRepository repository; - private final LotteryEventLog notifications; - private final WireTransfers wireTransfers; - - /** - * Constructor - */ - @Inject - public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications, - WireTransfers wireTransfers) { - this.repository = repository; - this.notifications = notifications; - this.wireTransfers = wireTransfers; - } - - /** - * Get all the lottery tickets submitted for lottery - */ - public Map getAllSubmittedTickets() { - return repository.findAll(); - } - - /** - * Draw lottery numbers - */ - public LotteryNumbers performLottery() { - LotteryNumbers numbers = LotteryNumbers.createRandom(); - Map tickets = getAllSubmittedTickets(); - for (LotteryTicketId id : tickets.keySet()) { - LotteryTicketCheckResult result = LotteryUtils.checkTicketForPrize(repository, id, numbers); - if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) { - boolean transferred = wireTransfers.transferFunds(LotteryConstants.PRIZE_AMOUNT, - LotteryConstants.SERVICE_BANK_ACCOUNT, tickets.get(id).getPlayerDetails().getBankAccount()); - if (transferred) { - notifications.ticketWon(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT); - } else { - notifications.prizeError(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT); - } - } else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) { - notifications.ticketDidNotWin(tickets.get(id).getPlayerDetails()); - } - } - return numbers; - } - - /** - * Begin new lottery round - */ - public void resetLottery() { - repository.deleteAll(); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java deleted file mode 100644 index 9ecbb74b9f82..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -/** - * - * Lottery domain constants - * - */ -public class LotteryConstants { - - private LotteryConstants() { - } - - public static final int PRIZE_AMOUNT = 100000; - public static final String SERVICE_BANK_ACCOUNT = "123-123"; - public static final int TICKET_PRIZE = 3; - public static final int SERVICE_BANK_ACCOUNT_SALDO = 150000; - public static final int PLAYER_MAX_SALDO = 100; - -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java deleted file mode 100644 index a688647fad22..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.PrimitiveIterator; -import java.util.Random; -import java.util.Set; - -/** - * - * Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must be unique and - * between 1 and 20. - * - */ -public class LotteryNumbers { - - private final Set numbers; - - public static final int MIN_NUMBER = 1; - public static final int MAX_NUMBER = 20; - public static final int NUM_NUMBERS = 4; - - /** - * Constructor. Creates random lottery numbers. - */ - private LotteryNumbers() { - numbers = new HashSet<>(); - generateRandomNumbers(); - } - - /** - * Constructor. Uses given numbers. - */ - private LotteryNumbers(Set givenNumbers) { - numbers = new HashSet<>(); - numbers.addAll(givenNumbers); - } - - /** - * @return random LotteryNumbers - */ - public static LotteryNumbers createRandom() { - return new LotteryNumbers(); - } - - /** - * @return given LotteryNumbers - */ - public static LotteryNumbers create(Set givenNumbers) { - return new LotteryNumbers(givenNumbers); - } - - /** - * @return lottery numbers - */ - public Set getNumbers() { - return Collections.unmodifiableSet(numbers); - } - - /** - * @return numbers as comma separated string - */ - public String getNumbersAsString() { - List list = new ArrayList<>(); - list.addAll(numbers); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < NUM_NUMBERS; i++) { - builder.append(list.get(i)); - if (i < NUM_NUMBERS - 1) { - builder.append(","); - } - } - return builder.toString(); - } - - /** - * Generates 4 unique random numbers between 1-20 into numbers set. - */ - private void generateRandomNumbers() { - numbers.clear(); - RandomNumberGenerator generator = new RandomNumberGenerator(MIN_NUMBER, MAX_NUMBER); - while (numbers.size() < NUM_NUMBERS) { - int num = generator.nextInt(); - if (!numbers.contains(num)) { - numbers.add(num); - } - } - } - - @Override - public String toString() { - return "LotteryNumbers{" + "numbers=" + numbers + '}'; - } - - /** - * - * Helper class for generating random numbers. - * - */ - private static class RandomNumberGenerator { - - private PrimitiveIterator.OfInt randomIterator; - - /** - * Initialize a new random number generator that generates random numbers in the range [min, max] - * - * @param min the min value (inclusive) - * @param max the max value (inclusive) - */ - public RandomNumberGenerator(int min, int max) { - randomIterator = new Random().ints(min, max + 1).iterator(); - } - - /** - * @return a random number in the range (min, max) - */ - public int nextInt() { - return randomIterator.nextInt(); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((numbers == null) ? 0 : numbers.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - LotteryNumbers other = (LotteryNumbers) obj; - if (numbers == null) { - if (other.numbers != null) { - return false; - } - } else if (!numbers.equals(other.numbers)) { - return false; - } - return true; - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java deleted file mode 100644 index 7afa76503b4b..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import com.google.inject.Inject; -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.database.LotteryTicketRepository; -import com.iluwatar.hexagonal.eventlog.LotteryEventLog; - -import java.util.Optional; - -/** - * - * Implementation for lottery service - * - */ -public class LotteryService { - - private final LotteryTicketRepository repository; - private final LotteryEventLog notifications; - private final WireTransfers wireTransfers; - - /** - * Constructor - */ - @Inject - public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications, - WireTransfers wireTransfers) { - this.repository = repository; - this.notifications = notifications; - this.wireTransfers = wireTransfers; - } - - /** - * Submit lottery ticket to participate in the lottery - */ - public Optional submitTicket(LotteryTicket ticket) { - boolean result = wireTransfers.transferFunds(LotteryConstants.TICKET_PRIZE, - ticket.getPlayerDetails().getBankAccount(), LotteryConstants.SERVICE_BANK_ACCOUNT); - if (!result) { - notifications.ticketSubmitError(ticket.getPlayerDetails()); - return Optional.empty(); - } - Optional optional = repository.save(ticket); - if (optional.isPresent()) { - notifications.ticketSubmitted(ticket.getPlayerDetails()); - } - return optional; - } - - /** - * Check if lottery ticket has won - */ - public LotteryTicketCheckResult checkTicketForPrize(LotteryTicketId id, LotteryNumbers winningNumbers) { - return LotteryUtils.checkTicketForPrize(repository, id, winningNumbers); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java deleted file mode 100644 index 2c5340b63b2c..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -/** - * - * Immutable value object representing lottery ticket. - * - */ -public class LotteryTicket { - - private LotteryTicketId id; - private final PlayerDetails playerDetails; - private final LotteryNumbers lotteryNumbers; - - /** - * Constructor. - */ - public LotteryTicket(LotteryTicketId id, PlayerDetails details, LotteryNumbers numbers) { - this.id = id; - playerDetails = details; - lotteryNumbers = numbers; - } - - /** - * @return player details - */ - public PlayerDetails getPlayerDetails() { - return playerDetails; - } - - /** - * @return lottery numbers - */ - public LotteryNumbers getNumbers() { - return lotteryNumbers; - } - - /** - * @return id - */ - public LotteryTicketId getId() { - return id; - } - - /** - * set id - */ - public void setId(LotteryTicketId id) { - this.id = id; - } - - @Override - public String toString() { - return playerDetails.toString() + " " + lotteryNumbers.toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((lotteryNumbers == null) ? 0 : lotteryNumbers.hashCode()); - result = prime * result + ((playerDetails == null) ? 0 : playerDetails.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - LotteryTicket other = (LotteryTicket) obj; - if (lotteryNumbers == null) { - if (other.lotteryNumbers != null) { - return false; - } - } else if (!lotteryNumbers.equals(other.lotteryNumbers)) { - return false; - } - if (playerDetails == null) { - if (other.playerDetails != null) { - return false; - } - } else if (!playerDetails.equals(other.playerDetails)) { - return false; - } - return true; - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java deleted file mode 100644 index a5b455354370..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -/** - * - * Represents lottery ticket check result. - * - */ -public class LotteryTicketCheckResult { - - /** - * Enumeration of Type of Outcomes of a Lottery - */ - public enum CheckResult { WIN_PRIZE, NO_PRIZE, TICKET_NOT_SUBMITTED } - - private final CheckResult checkResult; - private final int prizeAmount; - - /** - * Constructor. - */ - public LotteryTicketCheckResult(CheckResult result) { - checkResult = result; - prizeAmount = 0; - } - - /** - * Constructor. - */ - public LotteryTicketCheckResult(CheckResult result, int amount) { - checkResult = result; - prizeAmount = amount; - } - - /** - * @return check result - */ - public CheckResult getResult() { - return checkResult; - } - - /** - * @return prize amount - */ - public int getPrizeAmount() { - return prizeAmount; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((checkResult == null) ? 0 : checkResult.hashCode()); - result = prime * result + prizeAmount; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - LotteryTicketCheckResult other = (LotteryTicketCheckResult) obj; - return checkResult == other.checkResult && prizeAmount == other.prizeAmount; - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java deleted file mode 100644 index 838fdb32b843..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -/** - * Lottery ticked id - */ -public class LotteryTicketId { - - private static volatile int numAllocated; - private final int id; - - public LotteryTicketId() { - this.id = numAllocated + 1; - numAllocated++; - } - - public LotteryTicketId(int id) { - this.id = id; - } - - public int getId() { - return id; - } - - @Override - public String toString() { - return String.format("%d", id); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - LotteryTicketId that = (LotteryTicketId) o; - - return id == that.id; - - } - - @Override - public int hashCode() { - return id; - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java deleted file mode 100644 index 2f3c3be222a0..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import com.iluwatar.hexagonal.database.LotteryTicketRepository; - -import java.util.Optional; - -/** - * Lottery utilities - */ -public class LotteryUtils { - - private LotteryUtils() { - } - - /** - * Checks if lottery ticket has won - */ - public static LotteryTicketCheckResult checkTicketForPrize(LotteryTicketRepository repository, LotteryTicketId id, - LotteryNumbers winningNumbers) { - Optional optional = repository.findById(id); - if (optional.isPresent()) { - if (optional.get().getNumbers().equals(winningNumbers)) { - return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.WIN_PRIZE, 1000); - } else { - return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.NO_PRIZE); - } - } else { - return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.TICKET_NOT_SUBMITTED); - } - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java deleted file mode 100644 index 6f47d6cf5a0d..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -/** - * - * Immutable value object containing lottery player details. - * - */ -public class PlayerDetails { - - private final String emailAddress; - private final String bankAccountNumber; - private final String phoneNumber; - - /** - * Constructor. - */ - public PlayerDetails(String email, String bankAccount, String phone) { - emailAddress = email; - bankAccountNumber = bankAccount; - phoneNumber = phone; - } - - /** - * @return email - */ - public String getEmail() { - return emailAddress; - } - - /** - * @return bank account number - */ - public String getBankAccount() { - return bankAccountNumber; - } - - /** - * @return phone number - */ - public String getPhoneNumber() { - return phoneNumber; - } - - @Override - public String toString() { - return "PlayerDetails{" + "emailAddress='" + emailAddress + '\'' - + ", bankAccountNumber='" + bankAccountNumber + '\'' - + ", phoneNumber='" + phoneNumber + '\'' + '}'; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((bankAccountNumber == null) ? 0 : bankAccountNumber.hashCode()); - result = prime * result + ((emailAddress == null) ? 0 : emailAddress.hashCode()); - result = prime * result + ((phoneNumber == null) ? 0 : phoneNumber.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - PlayerDetails other = (PlayerDetails) obj; - if (bankAccountNumber == null) { - if (other.bankAccountNumber != null) { - return false; - } - } else if (!bankAccountNumber.equals(other.bankAccountNumber)) { - return false; - } - if (emailAddress == null) { - if (other.emailAddress != null) { - return false; - } - } else if (!emailAddress.equals(other.emailAddress)) { - return false; - } - if (phoneNumber == null) { - if (other.phoneNumber != null) { - return false; - } - } else if (!phoneNumber.equals(other.phoneNumber)) { - return false; - } - return true; - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/LotteryEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/LotteryEventLog.java deleted file mode 100644 index fd6bfebdf9f1..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/LotteryEventLog.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.eventlog; - -import com.iluwatar.hexagonal.domain.PlayerDetails; - -/** - * - * Event log for lottery events - * - */ -public interface LotteryEventLog { - - /** - * lottery ticket submitted - */ - void ticketSubmitted(PlayerDetails details); - - /** - * error submitting lottery ticket - */ - void ticketSubmitError(PlayerDetails details); - - /** - * lottery ticket did not win - */ - void ticketDidNotWin(PlayerDetails details); - - /** - * lottery ticket won - */ - void ticketWon(PlayerDetails details, int prizeAmount); - - /** - * error paying the prize - */ - void prizeError(PlayerDetails details, int prizeAmount); - -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java deleted file mode 100644 index fdc907305161..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.eventlog; - -import com.iluwatar.hexagonal.domain.PlayerDetails; -import com.mongodb.MongoClient; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; -import org.bson.Document; - -/** - * Mongo based event log - */ -public class MongoEventLog implements LotteryEventLog { - - private static final String DEFAULT_DB = "lotteryDB"; - private static final String DEFAULT_EVENTS_COLLECTION = "events"; - - private MongoClient mongoClient; - private MongoDatabase database; - private MongoCollection eventsCollection; - - private StdOutEventLog stdOutEventLog = new StdOutEventLog(); - - /** - * Constructor - */ - public MongoEventLog() { - connect(); - } - - /** - * Constructor accepting parameters - */ - public MongoEventLog(String dbName, String eventsCollectionName) { - connect(dbName, eventsCollectionName); - } - - /** - * Connect to database with default parameters - */ - public void connect() { - connect(DEFAULT_DB, DEFAULT_EVENTS_COLLECTION); - } - - /** - * Connect to database with given parameters - */ - public void connect(String dbName, String eventsCollectionName) { - if (mongoClient != null) { - mongoClient.close(); - } - mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - database = mongoClient.getDatabase(dbName); - eventsCollection = database.getCollection(eventsCollectionName); - } - - /** - * @return mongo client - */ - public MongoClient getMongoClient() { - return mongoClient; - } - - /** - * - * @return mongo database - */ - public MongoDatabase getMongoDatabase() { - return database; - } - - /** - * - * @return accounts collection - */ - public MongoCollection getEventsCollection() { - return eventsCollection; - } - - - @Override - public void ticketSubmitted(PlayerDetails details) { - Document document = new Document("email", details.getEmail()); - document.put("phone", details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); - document.put("message", "Lottery ticket was submitted and bank account was charged for 3 credits."); - eventsCollection.insertOne(document); - stdOutEventLog.ticketSubmitted(details); - } - - @Override - public void ticketSubmitError(PlayerDetails details) { - Document document = new Document("email", details.getEmail()); - document.put("phone", details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); - document.put("message", "Lottery ticket could not be submitted because lack of funds."); - eventsCollection.insertOne(document); - stdOutEventLog.ticketSubmitError(details); - } - - @Override - public void ticketDidNotWin(PlayerDetails details) { - Document document = new Document("email", details.getEmail()); - document.put("phone", details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); - document.put("message", "Lottery ticket was checked and unfortunately did not win this time."); - eventsCollection.insertOne(document); - stdOutEventLog.ticketDidNotWin(details); - } - - @Override - public void ticketWon(PlayerDetails details, int prizeAmount) { - Document document = new Document("email", details.getEmail()); - document.put("phone", details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); - document.put("message", String.format("Lottery ticket won! The bank account was deposited with %d credits.", - prizeAmount)); - eventsCollection.insertOne(document); - stdOutEventLog.ticketWon(details, prizeAmount); - } - - @Override - public void prizeError(PlayerDetails details, int prizeAmount) { - Document document = new Document("email", details.getEmail()); - document.put("phone", details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); - document.put("message", String.format("Lottery ticket won! Unfortunately the bank credit transfer of %d failed.", - prizeAmount)); - eventsCollection.insertOne(document); - stdOutEventLog.prizeError(details, prizeAmount); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java deleted file mode 100644 index 6d5af3280b21..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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) { - LOGGER.info("Lottery ticket for {} was submitted. Bank account {} was charged for 3 credits.", - details.getEmail(), details.getBankAccount()); - } - - @Override - public void ticketDidNotWin(PlayerDetails details) { - LOGGER.info("Lottery ticket for {} was checked and unfortunately did not win this time.", details.getEmail()); - } - - @Override - public void ticketWon(PlayerDetails details, int 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) { - LOGGER.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of {} failed.", - details.getEmail(), prizeAmount); - } - - @Override - public void ticketSubmitError(PlayerDetails details) { - 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/module/LotteryModule.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryModule.java deleted file mode 100644 index 72fb78dad9d7..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryModule.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.module; - -import com.google.inject.AbstractModule; -import com.iluwatar.hexagonal.banking.MongoBank; -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.database.LotteryTicketRepository; -import com.iluwatar.hexagonal.database.MongoTicketRepository; -import com.iluwatar.hexagonal.eventlog.LotteryEventLog; -import com.iluwatar.hexagonal.eventlog.MongoEventLog; - -/** - * Guice module for binding production dependencies - */ -public class LotteryModule extends AbstractModule { - @Override - protected void configure() { - bind(LotteryTicketRepository.class).to(MongoTicketRepository.class); - bind(LotteryEventLog.class).to(MongoEventLog.class); - bind(WireTransfers.class).to(MongoBank.class); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryTestingModule.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryTestingModule.java deleted file mode 100644 index 624acf5780a2..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryTestingModule.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.module; - -import com.google.inject.AbstractModule; -import com.iluwatar.hexagonal.banking.InMemoryBank; -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.database.InMemoryTicketRepository; -import com.iluwatar.hexagonal.database.LotteryTicketRepository; -import com.iluwatar.hexagonal.eventlog.LotteryEventLog; -import com.iluwatar.hexagonal.eventlog.StdOutEventLog; - -/** - * Guice module for testing dependencies - */ -public class LotteryTestingModule extends AbstractModule { - @Override - protected void configure() { - bind(LotteryTicketRepository.class).to(InMemoryTicketRepository.class); - bind(LotteryEventLog.class).to(StdOutEventLog.class); - bind(WireTransfers.class).to(InMemoryBank.class); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java deleted file mode 100644 index f8de9b5518fe..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.mongo; - -import java.io.FileInputStream; -import java.util.Properties; - -/** - * Mongo connection properties loader - */ -public class MongoConnectionPropertiesLoader { - - private static final String DEFAULT_HOST = "localhost"; - private static final int DEFAULT_PORT = 27017; - - /** - * Try to load connection properties from file. - * Fall back to default connection properties. - */ - public static void load() { - String host = DEFAULT_HOST; - int port = DEFAULT_PORT; - String path = System.getProperty("hexagonal.properties.path"); - Properties properties = new Properties(); - if (path != null) { - try (FileInputStream fin = new FileInputStream(path)) { - properties.load(fin); - host = properties.getProperty("mongo-host"); - port = Integer.parseInt(properties.getProperty("mongo-port")); - } catch (Exception e) { - // error occurred, use default properties - e.printStackTrace(); - } - } - System.setProperty("mongo-host", host); - System.setProperty("mongo-port", String.format("%d", port)); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java deleted file mode 100644 index 23d409ff4ba2..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.sampledata; - -import com.iluwatar.hexagonal.banking.InMemoryBank; -import com.iluwatar.hexagonal.domain.LotteryConstants; -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryService; -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.domain.PlayerDetails; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -/** - * Utilities for creating sample lottery tickets - */ -public class SampleData { - - private static final List PLAYERS; - - static { - PLAYERS = new ArrayList<>(); - PLAYERS.add(new PlayerDetails("john@google.com", "312-342", "+3242434242")); - PLAYERS.add(new PlayerDetails("mary@google.com", "234-987", "+23452346")); - PLAYERS.add(new PlayerDetails("steve@google.com", "833-836", "+63457543")); - PLAYERS.add(new PlayerDetails("wayne@google.com", "319-826", "+24626")); - PLAYERS.add(new PlayerDetails("johnie@google.com", "983-322", "+3635635")); - PLAYERS.add(new PlayerDetails("andy@google.com", "934-734", "+0898245")); - PLAYERS.add(new PlayerDetails("richard@google.com", "536-738", "+09845325")); - PLAYERS.add(new PlayerDetails("kevin@google.com", "453-936", "+2423532")); - PLAYERS.add(new PlayerDetails("arnold@google.com", "114-988", "+5646346524")); - PLAYERS.add(new PlayerDetails("ian@google.com", "663-765", "+928394235")); - PLAYERS.add(new PlayerDetails("robin@google.com", "334-763", "+35448")); - PLAYERS.add(new PlayerDetails("ted@google.com", "735-964", "+98752345")); - PLAYERS.add(new PlayerDetails("larry@google.com", "734-853", "+043842423")); - PLAYERS.add(new PlayerDetails("calvin@google.com", "334-746", "+73294135")); - PLAYERS.add(new PlayerDetails("jacob@google.com", "444-766", "+358042354")); - PLAYERS.add(new PlayerDetails("edwin@google.com", "895-345", "+9752435")); - PLAYERS.add(new PlayerDetails("mary@google.com", "760-009", "+34203542")); - PLAYERS.add(new PlayerDetails("lolita@google.com", "425-907", "+9872342")); - PLAYERS.add(new PlayerDetails("bruno@google.com", "023-638", "+673824122")); - PLAYERS.add(new PlayerDetails("peter@google.com", "335-886", "+5432503945")); - PLAYERS.add(new PlayerDetails("warren@google.com", "225-946", "+9872341324")); - PLAYERS.add(new PlayerDetails("monica@google.com", "265-748", "+134124")); - PLAYERS.add(new PlayerDetails("ollie@google.com", "190-045", "+34453452")); - PLAYERS.add(new PlayerDetails("yngwie@google.com", "241-465", "+9897641231")); - PLAYERS.add(new PlayerDetails("lars@google.com", "746-936", "+42345298345")); - PLAYERS.add(new PlayerDetails("bobbie@google.com", "946-384", "+79831742")); - PLAYERS.add(new PlayerDetails("tyron@google.com", "310-992", "+0498837412")); - PLAYERS.add(new PlayerDetails("tyrell@google.com", "032-045", "+67834134")); - PLAYERS.add(new PlayerDetails("nadja@google.com", "000-346", "+498723")); - PLAYERS.add(new PlayerDetails("wendy@google.com", "994-989", "+987324454")); - PLAYERS.add(new PlayerDetails("luke@google.com", "546-634", "+987642435")); - PLAYERS.add(new PlayerDetails("bjorn@google.com", "342-874", "+7834325")); - PLAYERS.add(new PlayerDetails("lisa@google.com", "024-653", "+980742154")); - PLAYERS.add(new PlayerDetails("anton@google.com", "834-935", "+876423145")); - PLAYERS.add(new PlayerDetails("bruce@google.com", "284-936", "+09843212345")); - PLAYERS.add(new PlayerDetails("ray@google.com", "843-073", "+678324123")); - PLAYERS.add(new PlayerDetails("ron@google.com", "637-738", "+09842354")); - PLAYERS.add(new PlayerDetails("xavier@google.com", "143-947", "+375245")); - PLAYERS.add(new PlayerDetails("harriet@google.com", "842-404", "+131243252")); - InMemoryBank wireTransfers = new InMemoryBank(); - Random random = new Random(); - for (int i = 0; i < PLAYERS.size(); i++) { - wireTransfers.setFunds(PLAYERS.get(i).getBankAccount(), - random.nextInt(LotteryConstants.PLAYER_MAX_SALDO)); - } - } - - /** - * Inserts lottery tickets into the database based on the sample data - */ - public static void submitTickets(LotteryService lotteryService, int numTickets) { - for (int i = 0; i < numTickets; i++) { - LotteryTicket ticket = new LotteryTicket(new LotteryTicketId(), - getRandomPlayerDetails(), LotteryNumbers.createRandom()); - lotteryService.submitTicket(ticket); - } - } - - private static PlayerDetails getRandomPlayerDetails() { - Random random = new Random(); - int idx = random.nextInt(PLAYERS.size()); - return PLAYERS.get(idx); - } -} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java deleted file mode 100644 index f7f7b274ded6..000000000000 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.service; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryService; -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.domain.PlayerDetails; -import com.iluwatar.hexagonal.module.LotteryModule; -import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Scanner; -import java.util.Set; - -/** - * Console interface for lottery players - */ -public class ConsoleLottery { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleLottery.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - MongoConnectionPropertiesLoader.load(); - Injector injector = Guice.createInjector(new LotteryModule()); - LotteryService service = injector.getInstance(LotteryService.class); - WireTransfers bank = injector.getInstance(WireTransfers.class); - try (final Scanner scanner = new Scanner(System.in)) { - boolean exit = false; - while (!exit) { - printMainMenu(); - String cmd = readString(scanner); - if ("1".equals(cmd)) { - queryLotteryAccountFunds(bank, scanner); - } else if ("2".equals(cmd)) { - addFundsToLotteryAccount(bank, scanner); - } else if ("3".equals(cmd)) { - submitTicket(service, scanner); - } else if ("4".equals(cmd)) { - checkTicket(service, scanner); - } else if ("5".equals(cmd)) { - exit = true; - } else { - LOGGER.info("Unknown command"); - } - } - } - } - - private static void checkTicket(LotteryService service, Scanner scanner) { - LOGGER.info("What is the ID of the lottery ticket?"); - String id = readString(scanner); - LOGGER.info("Give the 4 comma separated winning numbers?"); - String numbers = readString(scanner); - try { - String[] parts = numbers.split(","); - Set winningNumbers = new HashSet<>(); - for (int i = 0; i < 4; i++) { - winningNumbers.add(Integer.parseInt(parts[i])); - } - LotteryTicketCheckResult result = service.checkTicketForPrize( - new LotteryTicketId(Integer.parseInt(id)), LotteryNumbers.create(winningNumbers)); - if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) { - LOGGER.info("Congratulations! The lottery ticket has won!"); - } else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) { - LOGGER.info("Unfortunately the lottery ticket did not win."); - } else { - LOGGER.info("Such lottery ticket has not been submitted."); - } - } catch (Exception e) { - LOGGER.info("Failed checking the lottery ticket - please try again."); - } - } - - private static void submitTicket(LotteryService service, Scanner scanner) { - LOGGER.info("What is your email address?"); - String email = readString(scanner); - LOGGER.info("What is your bank account number?"); - String account = readString(scanner); - LOGGER.info("What is your phone number?"); - String phone = readString(scanner); - PlayerDetails details = new PlayerDetails(email, account, phone); - LOGGER.info("Give 4 comma separated lottery numbers?"); - String numbers = readString(scanner); - try { - String[] parts = numbers.split(","); - Set chosen = new HashSet<>(); - for (int i = 0; i < 4; i++) { - chosen.add(Integer.parseInt(parts[i])); - } - LotteryNumbers lotteryNumbers = LotteryNumbers.create(chosen); - LotteryTicket lotteryTicket = new LotteryTicket(new LotteryTicketId(), details, lotteryNumbers); - Optional id = service.submitTicket(lotteryTicket); - if (id.isPresent()) { - LOGGER.info("Submitted lottery ticket with id: {}", id.get()); - } else { - LOGGER.info("Failed submitting lottery ticket - please try again."); - } - } catch (Exception e) { - LOGGER.info("Failed submitting lottery ticket - please try again."); - } - } - - private static void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner) { - LOGGER.info("What is the account number?"); - String account = readString(scanner); - LOGGER.info("How many credits do you want to deposit?"); - String amount = readString(scanner); - bank.setFunds(account, Integer.parseInt(amount)); - LOGGER.info("The account {} now has {} credits.", account, bank.getFunds(account)); - } - - private static void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner) { - LOGGER.info("What is the account number?"); - String account = readString(scanner); - LOGGER.info("The account {} has {} credits.", account, bank.getFunds(account)); - } - - private static void printMainMenu() { - 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) { - System.out.print("> "); - return scanner.next(); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java deleted file mode 100644 index 1e35847b2e3d..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest { - - @Test - public void testApp() { - String[] args = {}; - App.main(args); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/InMemoryBankTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/InMemoryBankTest.java deleted file mode 100644 index 9c265a2ab551..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/InMemoryBankTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.banking; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * - * Tests for banking - * - */ -public class InMemoryBankTest { - - private final WireTransfers bank = new InMemoryBank(); - - @Test - public void testInit() { - assertEquals(bank.getFunds("foo"), 0); - bank.setFunds("foo", 100); - assertEquals(bank.getFunds("foo"), 100); - bank.setFunds("bar", 150); - assertEquals(bank.getFunds("bar"), 150); - assertTrue(bank.transferFunds(50, "bar", "foo")); - assertEquals(bank.getFunds("foo"), 150); - assertEquals(bank.getFunds("bar"), 100); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/MongoBankTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/MongoBankTest.java deleted file mode 100644 index 61529f3e4e59..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/banking/MongoBankTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.banking; - -import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; -import com.mongodb.MongoClient; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for Mongo banking adapter - */ -@Ignore -public class MongoBankTest { - - private static final String TEST_DB = "lotteryDBTest"; - private static final String TEST_ACCOUNTS_COLLECTION = "testAccounts"; - - private MongoBank mongoBank; - - @Before - public void init() { - MongoConnectionPropertiesLoader.load(); - MongoClient mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - mongoClient.dropDatabase(TEST_DB); - mongoClient.close(); - mongoBank = new MongoBank(TEST_DB, TEST_ACCOUNTS_COLLECTION); - } - - @Test - public void testSetup() { - assertEquals(0, mongoBank.getAccountsCollection().count()); - } - - @Test - public void testFundTransfers() { - assertEquals(0, mongoBank.getFunds("000-000")); - mongoBank.setFunds("000-000", 10); - assertEquals(10, mongoBank.getFunds("000-000")); - assertEquals(0, mongoBank.getFunds("111-111")); - mongoBank.transferFunds(9, "000-000", "111-111"); - assertEquals(1, mongoBank.getFunds("000-000")); - assertEquals(9, mongoBank.getFunds("111-111")); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java deleted file mode 100644 index ce5038369934..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.database; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Optional; - -import org.junit.Before; -import org.junit.Test; - -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.test.LotteryTestUtils; - -/** - * - * Tests for {@link LotteryTicketRepository} - * - */ -public class InMemoryTicketRepositoryTest { - - private final LotteryTicketRepository repository = new InMemoryTicketRepository(); - - @Before - public void clear() { - repository.deleteAll(); - } - - @Test - public void testCrudOperations() { - LotteryTicketRepository repository = new InMemoryTicketRepository(); - assertEquals(repository.findAll().size(), 0); - LotteryTicket ticket = LotteryTestUtils.createLotteryTicket(); - Optional id = repository.save(ticket); - assertTrue(id.isPresent()); - assertEquals(repository.findAll().size(), 1); - Optional optionalTicket = repository.findById(id.get()); - assertTrue(optionalTicket.isPresent()); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java deleted file mode 100644 index 8b248de8c065..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.database; - -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.domain.PlayerDetails; -import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; -import com.mongodb.MongoClient; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.Optional; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests for Mongo based ticket repository - */ -@Ignore -public class MongoTicketRepositoryTest { - - private static final String TEST_DB = "lotteryTestDB"; - private static final String TEST_TICKETS_COLLECTION = "lotteryTestTickets"; - private static final String TEST_COUNTERS_COLLECTION = "testCounters"; - - private MongoTicketRepository repository; - - @Before - public void init() { - MongoConnectionPropertiesLoader.load(); - MongoClient mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - mongoClient.dropDatabase(TEST_DB); - mongoClient.close(); - repository = new MongoTicketRepository(TEST_DB, TEST_TICKETS_COLLECTION, - TEST_COUNTERS_COLLECTION); - } - - @Test - public void testSetup() { - assertTrue(repository.getCountersCollection().count() == 1); - assertTrue(repository.getTicketsCollection().count() == 0); - } - - @Test - public void testNextId() { - assertEquals(1, repository.getNextId()); - assertEquals(2, repository.getNextId()); - assertEquals(3, repository.getNextId()); - } - - @Test - public void testCrudOperations() { - // create new lottery ticket and save it - PlayerDetails details = new PlayerDetails("foo@bar.com", "123-123", "07001234"); - LotteryNumbers random = LotteryNumbers.createRandom(); - LotteryTicket original = new LotteryTicket(new LotteryTicketId(), details, random); - Optional saved = repository.save(original); - assertEquals(1, repository.getTicketsCollection().count()); - assertTrue(saved.isPresent()); - // fetch the saved lottery ticket from database and check its contents - Optional found = repository.findById(saved.get()); - assertTrue(found.isPresent()); - LotteryTicket ticket = found.get(); - assertEquals("foo@bar.com", ticket.getPlayerDetails().getEmail()); - assertEquals("123-123", ticket.getPlayerDetails().getBankAccount()); - assertEquals("07001234", ticket.getPlayerDetails().getPhoneNumber()); - assertEquals(original.getNumbers(), ticket.getNumbers()); - // clear the collection - repository.deleteAll(); - assertEquals(0, repository.getTicketsCollection().count()); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryNumbersTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryNumbersTest.java deleted file mode 100644 index 8bd61db9cc50..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryNumbersTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.HashSet; - -import org.junit.Test; - -/** - * - * Unit tests for {@link LotteryNumbers} - * - */ -public class LotteryNumbersTest { - - @Test - public void testGivenNumbers() { - LotteryNumbers numbers = LotteryNumbers.create( - new HashSet<>(Arrays.asList(1, 2, 3, 4))); - assertEquals(numbers.getNumbers().size(), 4); - assertTrue(numbers.getNumbers().contains(1)); - assertTrue(numbers.getNumbers().contains(2)); - assertTrue(numbers.getNumbers().contains(3)); - assertTrue(numbers.getNumbers().contains(4)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testNumbersCantBeModified() { - LotteryNumbers numbers = LotteryNumbers.create( - new HashSet<>(Arrays.asList(1, 2, 3, 4))); - numbers.getNumbers().add(5); - } - - @Test - public void testRandomNumbers() { - LotteryNumbers numbers = LotteryNumbers.createRandom(); - assertEquals(numbers.getNumbers().size(), LotteryNumbers.NUM_NUMBERS); - } - - @Test - public void testEquals() { - LotteryNumbers numbers1 = LotteryNumbers.create( - new HashSet<>(Arrays.asList(1, 2, 3, 4))); - LotteryNumbers numbers2 = LotteryNumbers.create( - new HashSet<>(Arrays.asList(1, 2, 3, 4))); - assertTrue(numbers1.equals(numbers2)); - LotteryNumbers numbers3 = LotteryNumbers.create( - new HashSet<>(Arrays.asList(11, 12, 13, 14))); - assertFalse(numbers1.equals(numbers3)); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java deleted file mode 100644 index 4af8da3eabba..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; - -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.iluwatar.hexagonal.module.LotteryTestingModule; -import org.junit.Before; -import org.junit.Test; - -import com.iluwatar.hexagonal.banking.WireTransfers; -import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult; -import com.iluwatar.hexagonal.test.LotteryTestUtils; - -/** - * - * Test the lottery system - * - */ -public class LotteryTest { - - private Injector injector; - @Inject - private LotteryAdministration administration; - @Inject - private LotteryService service; - @Inject - private WireTransfers wireTransfers; - - public LotteryTest() { - this.injector = Guice.createInjector(new LotteryTestingModule()); - } - - @Before - public void setup() { - injector.injectMembers(this); - // add funds to the test player's bank account - wireTransfers.setFunds("123-12312", 100); - } - - @Test - public void testLottery() { - // admin resets the lottery - administration.resetLottery(); - assertEquals(administration.getAllSubmittedTickets().size(), 0); - - // players submit the lottery tickets - Optional ticket1 = service.submitTicket(LotteryTestUtils.createLotteryTicket("cvt@bbb.com", - "123-12312", "+32425255", new HashSet<>(Arrays.asList(1, 2, 3, 4)))); - assertTrue(ticket1.isPresent()); - Optional ticket2 = service.submitTicket(LotteryTestUtils.createLotteryTicket("ant@bac.com", - "123-12312", "+32423455", new HashSet<>(Arrays.asList(11, 12, 13, 14)))); - assertTrue(ticket2.isPresent()); - Optional ticket3 = service.submitTicket(LotteryTestUtils.createLotteryTicket("arg@boo.com", - "123-12312", "+32421255", new HashSet<>(Arrays.asList(6, 8, 13, 19)))); - assertTrue(ticket3.isPresent()); - assertEquals(administration.getAllSubmittedTickets().size(), 3); - - // perform lottery - LotteryNumbers winningNumbers = administration.performLottery(); - - // cheat a bit for testing sake, use winning numbers to submit another ticket - Optional ticket4 = service.submitTicket(LotteryTestUtils.createLotteryTicket("lucky@orb.com", - "123-12312", "+12421255", winningNumbers.getNumbers())); - assertTrue(ticket4.isPresent()); - assertEquals(administration.getAllSubmittedTickets().size(), 4); - - // check winners - Map tickets = administration.getAllSubmittedTickets(); - for (LotteryTicketId id: tickets.keySet()) { - LotteryTicketCheckResult checkResult = service.checkTicketForPrize(id, winningNumbers); - assertTrue(checkResult.getResult() != CheckResult.TICKET_NOT_SUBMITTED); - if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) { - assertTrue(checkResult.getPrizeAmount() > 0); - } else if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) { - assertEquals(checkResult.getPrizeAmount(), 0); - } - } - - // check another ticket that has not been submitted - LotteryTicketCheckResult checkResult = service.checkTicketForPrize(new LotteryTicketId(), winningNumbers); - assertTrue(checkResult.getResult() == CheckResult.TICKET_NOT_SUBMITTED); - assertEquals(checkResult.getPrizeAmount(), 0); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResultTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResultTest.java deleted file mode 100644 index 454d0dd010de..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResultTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.junit.Test; - -import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult; - -/** - * - * Unit tests for {@link LotteryTicketCheckResult} - * - */ -public class LotteryTicketCheckResultTest { - - @Test - public void testEquals() { - LotteryTicketCheckResult result1 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE); - LotteryTicketCheckResult result2 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE); - assertEquals(result1, result2); - LotteryTicketCheckResult result3 = new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 300000); - assertFalse(result1.equals(result3)); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketIdTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketIdTest.java deleted file mode 100644 index d4f0848ba680..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketIdTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Tests for lottery ticket id - */ -public class LotteryTicketIdTest { - - @Test - public void testEquals() { - LotteryTicketId ticketId1 = new LotteryTicketId(); - LotteryTicketId ticketId2 = new LotteryTicketId(); - LotteryTicketId ticketId3 = new LotteryTicketId(); - assertFalse(ticketId1.equals(ticketId2)); - assertFalse(ticketId2.equals(ticketId3)); - LotteryTicketId ticketId4 = new LotteryTicketId(ticketId1.getId()); - assertTrue(ticketId1.equals(ticketId4)); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketTest.java deleted file mode 100644 index a83f9033cfd0..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.Arrays; -import java.util.HashSet; - -import org.junit.Test; - -/** - * Test Lottery Tickets for equality - */ -public class LotteryTicketTest { - - @Test - public void testEquals() { - PlayerDetails details1 = new PlayerDetails("bob@foo.bar", "1212-121212", "+34332322"); - LotteryNumbers numbers1 = LotteryNumbers.create(new HashSet(Arrays.asList(1, 2, 3, 4))); - LotteryTicket ticket1 = new LotteryTicket(new LotteryTicketId(), details1, numbers1); - PlayerDetails details2 = new PlayerDetails("bob@foo.bar", "1212-121212", "+34332322"); - LotteryNumbers numbers2 = LotteryNumbers.create(new HashSet(Arrays.asList(1, 2, 3, 4))); - LotteryTicket ticket2 = new LotteryTicket(new LotteryTicketId(), details2, numbers2); - assertEquals(ticket1, ticket2); - PlayerDetails details3 = new PlayerDetails("elsa@foo.bar", "1223-121212", "+49332322"); - LotteryNumbers numbers3 = LotteryNumbers.create(new HashSet(Arrays.asList(1, 2, 3, 8))); - LotteryTicket ticket3 = new LotteryTicket(new LotteryTicketId(), details3, numbers3); - assertFalse(ticket1.equals(ticket3)); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/PlayerDetailsTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/PlayerDetailsTest.java deleted file mode 100644 index 2271ebf7c33d..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/PlayerDetailsTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.domain; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.junit.Test; - -/** - * - * Unit tests for {@link PlayerDetails} - * - */ -public class PlayerDetailsTest { - - @Test - public void testEquals() { - PlayerDetails details1 = new PlayerDetails("tom@foo.bar", "11212-123434", "+12323425"); - PlayerDetails details2 = new PlayerDetails("tom@foo.bar", "11212-123434", "+12323425"); - assertEquals(details1, details2); - PlayerDetails details3 = new PlayerDetails("john@foo.bar", "16412-123439", "+34323432"); - assertFalse(details1.equals(details3)); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/eventlog/MongoEventLogTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/eventlog/MongoEventLogTest.java deleted file mode 100644 index 07c40691beee..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/eventlog/MongoEventLogTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.eventlog; - -import com.iluwatar.hexagonal.domain.PlayerDetails; -import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; -import com.mongodb.MongoClient; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for Mongo event log - */ -@Ignore -public class MongoEventLogTest { - - private static final String TEST_DB = "lotteryDBTest"; - private static final String TEST_EVENTS_COLLECTION = "testEvents"; - - private MongoEventLog mongoEventLog; - - @Before - public void init() { - MongoConnectionPropertiesLoader.load(); - MongoClient mongoClient = new MongoClient(System.getProperty("mongo-host"), - Integer.parseInt(System.getProperty("mongo-port"))); - mongoClient.dropDatabase(TEST_DB); - mongoClient.close(); - mongoEventLog = new MongoEventLog(TEST_DB, TEST_EVENTS_COLLECTION); - } - - @Test - public void testSetup() { - assertEquals(0, mongoEventLog.getEventsCollection().count()); - } - - @Test - public void testFundTransfers() { - PlayerDetails playerDetails = new PlayerDetails("john@wayne.com", "000-000", "03432534543"); - mongoEventLog.prizeError(playerDetails, 1000); - assertEquals(1, mongoEventLog.getEventsCollection().count()); - mongoEventLog.prizeError(playerDetails, 1000); - assertEquals(2, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketDidNotWin(playerDetails); - assertEquals(3, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketDidNotWin(playerDetails); - assertEquals(4, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketSubmitError(playerDetails); - assertEquals(5, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketSubmitError(playerDetails); - assertEquals(6, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketSubmitted(playerDetails); - assertEquals(7, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketSubmitted(playerDetails); - assertEquals(8, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketWon(playerDetails, 1000); - assertEquals(9, mongoEventLog.getEventsCollection().count()); - mongoEventLog.ticketWon(playerDetails, 1000); - assertEquals(10, mongoEventLog.getEventsCollection().count()); - } -} diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/test/LotteryTestUtils.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/test/LotteryTestUtils.java deleted file mode 100644 index 7f6c0edab291..000000000000 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/test/LotteryTestUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.hexagonal.test; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import com.iluwatar.hexagonal.domain.LotteryNumbers; -import com.iluwatar.hexagonal.domain.LotteryTicket; -import com.iluwatar.hexagonal.domain.LotteryTicketId; -import com.iluwatar.hexagonal.domain.PlayerDetails; - -/** - * - * Utilities for lottery tests - * - */ -public class LotteryTestUtils { - - /** - * @return lottery ticket - */ - public static LotteryTicket createLotteryTicket() { - return createLotteryTicket("foo@bar.com", "12231-213132", "+99324554", new HashSet<>(Arrays.asList(1, 2, 3, 4))); - } - - /** - * @return lottery ticket - */ - public static LotteryTicket createLotteryTicket(String email, String account, String phone, - Set givenNumbers) { - PlayerDetails details = new PlayerDetails(email, account, phone); - LotteryNumbers numbers = LotteryNumbers.create(givenNumbers); - return new LotteryTicket(new LotteryTicketId(), details, numbers); - } -} diff --git a/intercepting-filter/README.md b/intercepting-filter/README.md deleted file mode 100644 index 4981299ad27b..000000000000 --- a/intercepting-filter/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: pattern -title: Intercepting Filter -folder: intercepting-filter -permalink: /patterns/intercepting-filter/ -pumlid: RSfB3i8m303Hgy014k-vZN5DQkIuaJ_q-fGzkz7JtCL8Q-DolUsPAnu0ZcSVadizAzZfi6JBJiS4qJenqU6D7smRXmnh2pFPBM1YN05o_KwyKcoqb-ZFEEcVz_BPLqtz0W00 -categories: Behavioral -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Provide pluggable filters to conduct necessary pre-processing and -post-processing to requests from a client to a target - -![alt text](./etc/intercepting-filter.png "Intercepting Filter") - -## Applicability -Use the Intercepting Filter pattern when - -* a system uses pre-processing or post-processing requests -* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers -* you want a modular approach to configuring pre-processing and post-processing schemes - -## Real world examples - -* [javax.servlet.FilterChain](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/FilterChain.html) and [javax.servlet.Filter](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/Filter.html) -* [Struts 2 - Interceptors](https://struts.apache.org/docs/interceptors.html) - -## Credits - -* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm) -* [Presentation Tier Patterns](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns) diff --git a/intercepting-filter/etc/intercepting-filter.png b/intercepting-filter/etc/intercepting-filter.png deleted file mode 100644 index ec792639eab5d118f808a130245e159a38806153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75351 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

    (!e^p1&*$-0K5gg`chf@4-T0FE;Z zo?E)yx+fDvQHEcI=Ld9x$@aV)rrd-}XfO}%@L_o4cm?^tutvuleKL}^UT}aRAM^oz zXT4wuN**+}?*7|92GF}g+6OvGMY&}*4{pGw!-7iGAgylb83$Q~4=>fZ=MG$~79IZj zu^BB-o|}u?epLrIHIE4@!&QCP#VRAk5_OmvC$nh|H^L&m;=6p9X0%)VZa&s0x>APo zkx;88l)N#`xD6PBdyKwUaVOf(oemJQTxF3?52hr$ci#x{F_nzp3h5=vLm5N>@L@*Z z9wXOx88z?7R{jFs|Kk}nY6IHC`)W@cA{B4ta#!1Ru;&B;b7;Pr^^DQXno2*;=?^3$#Bn>4q7VW4(y?P$ri%T}K)9OknP7#Ajpl`17~dpwY(_H$&8( zYkFL&#Y(aFf(psPP__Mk66ib*3r6B`sr1XKj!4c#IiTD846=N$9h3`V?u_S(Q|JiN zSK6+N{ypJE7P6fAjT3s$NNJmqB=Uz2!|>c_3nS3BQwo(^Z5 zj1u-TZmv+u`0LfFkT7DylbZL_F0L&`zVBWXta@x3H?Lj|*j5UWzbEmY=Jaa#!Oj}= zjA5C#Q`⪼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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/intercepting-filter/etc/intercepting-filter.urm.puml b/intercepting-filter/etc/intercepting-filter.urm.puml deleted file mode 100644 index 74444c2d0958..000000000000 --- a/intercepting-filter/etc/intercepting-filter.urm.puml +++ /dev/null @@ -1,89 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.intercepting.filter { - abstract class AbstractFilter { - - next : Filter - + AbstractFilter() - + AbstractFilter(next : Filter) - + execute(order : Order) : String - + getLast() : Filter - + getNext() : Filter - + setNext(filter : Filter) - } - class AddressFilter { - + AddressFilter() - + execute(order : Order) : String - } - class App { - + App() - + main(args : String[]) {static} - } - class ContactFilter { - + ContactFilter() - + execute(order : Order) : String - } - class DepositFilter { - + DepositFilter() - + execute(order : Order) : String - } - interface Filter { - + execute(Order) : String {abstract} - + getLast() : Filter {abstract} - + getNext() : Filter {abstract} - + setNext(Filter) {abstract} - } - class FilterChain { - - chain : Filter - + FilterChain() - + addFilter(filter : Filter) - + execute(order : Order) : String - } - class FilterManager { - - filterChain : FilterChain - + FilterManager() - + addFilter(filter : Filter) - + filterRequest(order : Order) : String - } - class NameFilter { - + NameFilter() - + execute(order : Order) : String - } - class Order { - - address : String - - contactNumber : String - - depositNumber : String - - name : String - - order : String - + Order() - + Order(name : String, contactNumber : String, address : String, depositNumber : String, order : String) - + getAddress() : String - + getContactNumber() : String - + getDepositNumber() : String - + getName() : String - + getOrder() : String - + setAddress(address : String) - + setContactNumber(contactNumber : String) - + setDepositNumber(depositNumber : String) - + setName(name : String) - + setOrder(order : String) - } - class OrderFilter { - + OrderFilter() - + execute(order : Order) : String - } - ~class DListener { - ~ DListener() - + actionPerformed(e : ActionEvent) - } -} -AbstractFilter --> "-next" Filter -DListener --+ Target -FilterChain --> "-chain" Filter -FilterManager --> "-filterChain" FilterChain -AbstractFilter ..|> Filter -AddressFilter --|> AbstractFilter -ContactFilter --|> AbstractFilter -DepositFilter --|> AbstractFilter -NameFilter --|> AbstractFilter -OrderFilter --|> AbstractFilter -@enduml diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml deleted file mode 100644 index 40888b7f3171..000000000000 --- a/intercepting-filter/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - intercepting-filter - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java deleted file mode 100644 index 2e48f73b28a0..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Base class for order processing filters. Handles chain management. - * - */ -public abstract class AbstractFilter implements Filter { - - private Filter next; - - public AbstractFilter() {} - - public AbstractFilter(Filter next) { - this.next = next; - } - - @Override - public void setNext(Filter filter) { - this.next = filter; - } - - @Override - public Filter getNext() { - return next; - } - - @Override - public Filter getLast() { - Filter last = this; - while (last.getNext() != null) { - last = last.getNext(); - } - return last; - } - - @Override - public String execute(Order order) { - if (getNext() != null) { - return getNext().execute(order); - } else { - return ""; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java deleted file mode 100644 index 1ba7ee8d391c..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Concrete implementation of filter This filter is responsible for checking/filtering the input in - * the address field. - * - * @author joshzambales - * - */ -public class AddressFilter extends AbstractFilter { - - @Override - public String execute(Order order) { - String result = super.execute(order); - if (order.getAddress() == null || order.getAddress().isEmpty()) { - return result + "Invalid address! "; - } else { - return result; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/App.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/App.java deleted file mode 100644 index 1315f1318eb7..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/App.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * - * When a request enters a Web application, it often must pass several entrance tests prior to the - * main processing stage. For example, - Has the client been authenticated? - Does the client have a - * valid session? - Is the client's IP address from a trusted network? - Does the request path - * violate any constraints? - What encoding does the client use to send the data? - Do we support - * the browser type of the client? Some of these checks are tests, resulting in a yes or no answer - * that determines whether processing will continue. Other checks manipulate the incoming data - * stream into a form suitable for processing. - *

    - * The classic solution consists of a series of conditional checks, with any failed check aborting - * the request. Nested if/else statements are a standard strategy, but this solution leads to code - * fragility and a copy-and-paste style of programming, because the flow of the filtering and the - * action of the filters is compiled into the application. - *

    - * The key to solving this problem in a flexible and unobtrusive manner is to have a simple - * mechanism for adding and removing processing components, in which each component completes a - * specific filtering action. This is the Intercepting Filter pattern in action. - *

    - * In this example we check whether the order request is valid through pre-processing done via - * {@link Filter}. Each field has its own corresponding {@link Filter} - *

    - * - * @author joshzambales - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - FilterManager filterManager = new FilterManager(); - filterManager.addFilter(new NameFilter()); - filterManager.addFilter(new ContactFilter()); - filterManager.addFilter(new AddressFilter()); - filterManager.addFilter(new DepositFilter()); - filterManager.addFilter(new OrderFilter()); - - Client client = new Client(); - client.setFilterManager(filterManager); - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java deleted file mode 100644 index 60b888dc7c1b..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java +++ /dev/null @@ -1,126 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import java.awt.BorderLayout; -import java.awt.GridLayout; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; - -/** - * The Client class is responsible for handling the input and running them through filters inside the - * {@link FilterManager}. - * - * This is where {@link Filter}s come to play as the client pre-processes the request before being displayed in the - * {@link Target}. - * - * @author joshzambales - * - */ -public class Client extends JFrame { // NOSONAR - - private static final long serialVersionUID = 1L; - - private transient FilterManager filterManager; - private JLabel jl; - private JTextField[] jtFields; - private JTextArea[] jtAreas; - private JButton clearButton; - private JButton processButton; - - /** - * Constructor - */ - public Client() { - super("Client System"); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setSize(300, 300); - jl = new JLabel("RUNNING..."); - jtFields = new JTextField[3]; - for (int i = 0; i < 3; i++) { - jtFields[i] = new JTextField(); - } - jtAreas = new JTextArea[2]; - for (int i = 0; i < 2; i++) { - jtAreas[i] = new JTextArea(); - } - clearButton = new JButton("Clear"); - processButton = new JButton("Process"); - - setup(); - } - - private void setup() { - setLayout(new BorderLayout()); - JPanel panel = new JPanel(); - add(jl, BorderLayout.SOUTH); - add(panel, BorderLayout.CENTER); - panel.setLayout(new GridLayout(6, 2)); - panel.add(new JLabel("Name")); - panel.add(jtFields[0]); - panel.add(new JLabel("Contact Number")); - panel.add(jtFields[1]); - panel.add(new JLabel("Address")); - panel.add(jtAreas[0]); - panel.add(new JLabel("Deposit Number")); - panel.add(jtFields[2]); - panel.add(new JLabel("Order")); - panel.add(jtAreas[1]); - panel.add(clearButton); - panel.add(processButton); - - clearButton.addActionListener(e -> { - for (JTextArea i : jtAreas) { - i.setText(""); - } - for (JTextField i : jtFields) { - i.setText(""); - } - }); - - processButton.addActionListener(e -> { - Order order = new Order(jtFields[0].getText(), jtFields[1].getText(), jtAreas[0].getText(), jtFields[2].getText(), - jtAreas[1].getText()); - jl.setText(sendRequest(order)); - }); - - JRootPane rootPane = SwingUtilities.getRootPane(processButton); - rootPane.setDefaultButton(processButton); - setVisible(true); - } - - public void setFilterManager(FilterManager filterManager) { - this.filterManager = filterManager; - } - - public String sendRequest(Order order) { - return filterManager.filterRequest(order); - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java deleted file mode 100644 index 52a0487c49aa..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Concrete implementation of filter This filter checks for the contact field in which it checks if - * the input consist of numbers and it also checks if the input follows the length constraint (11 - * digits) - * - * @author joshzambales - * - */ -public class ContactFilter extends AbstractFilter { - - @Override - public String execute(Order order) { - String result = super.execute(order); - if (order.getContactNumber() == null || order.getContactNumber().isEmpty() - || order.getContactNumber().matches(".*[^\\d]+.*") - || order.getContactNumber().length() != 11) { - return result + "Invalid contact number! "; - } else { - return result; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java deleted file mode 100644 index cc06c339d995..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Concrete implementation of filter This checks for the deposit code - * - * @author joshzambales - * - */ -public class DepositFilter extends AbstractFilter { - - @Override - public String execute(Order order) { - String result = super.execute(order); - if (order.getDepositNumber() == null || order.getDepositNumber().isEmpty()) { - return result + "Invalid deposit number! "; - } else { - return result; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java deleted file mode 100644 index 0cf2a1b6f7c0..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Filters perform certain tasks prior or after execution of request by request handler. In this - * case, before the request is handled by the target, the request undergoes through each Filter - * - * @author joshzambales - * - */ -public interface Filter { - - /** - * Execute order processing filter. - */ - String execute(Order order); - - /** - * Set next filter in chain after this. - */ - void setNext(Filter filter); - - /** - * Get next filter in chain after this. - */ - Filter getNext(); - - /** - * Get last filter in the chain. - */ - Filter getLast(); -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java deleted file mode 100644 index 1e0c0de35d97..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - - -/** - * Filter Chain carries multiple filters and help to execute them in defined order on target. - * - * @author joshzambales - */ -public class FilterChain { - - private Filter chain; - - - /** - * Adds filter - */ - public void addFilter(Filter filter) { - if (chain == null) { - chain = filter; - } else { - chain.getLast().setNext(filter); - } - } - - /** - * Execute filter chain - */ - public String execute(Order order) { - if (chain != null) { - return chain.execute(order); - } else { - return "RUNNING..."; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java deleted file mode 100644 index e9897ec9233e..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Filter Manager manages the filters and {@link FilterChain}. - * - * @author joshzambales - * - */ -public class FilterManager { - - private FilterChain filterChain; - - public FilterManager() { - filterChain = new FilterChain(); - } - - public void addFilter(Filter filter) { - filterChain.addFilter(filter); - } - - public String filterRequest(Order order) { - return filterChain.execute(order); - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java deleted file mode 100644 index 7efb181bb1a0..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Concrete implementation of filter. This filter checks if the input in the Name field is valid. - * (alphanumeric) - * - * @author joshzambales - * - */ -public class NameFilter extends AbstractFilter { - - @Override - public String execute(Order order) { - String result = super.execute(order); - if (order.getName() == null || order.getName().isEmpty() - || order.getName().matches(".*[^\\w|\\s]+.*")) { - return result + "Invalid name! "; - } else { - return result; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java deleted file mode 100644 index c298986527b2..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Order class carries the order data. - * - */ -public class Order { - - private String name; - private String contactNumber; - private String address; - private String depositNumber; - private String orderItem; - - public Order() {} - - /** - * Constructor - */ - public Order(String name, String contactNumber, String address, String depositNumber, String order) { - this.name = name; - this.contactNumber = contactNumber; - this.address = address; - this.depositNumber = depositNumber; - this.orderItem = order; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getContactNumber() { - return contactNumber; - } - - public void setContactNumber(String contactNumber) { - this.contactNumber = contactNumber; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getDepositNumber() { - return depositNumber; - } - - public void setDepositNumber(String depositNumber) { - this.depositNumber = depositNumber; - } - - public String getOrderItem() { - return orderItem; - } - - public void setOrderItem(String order) { - this.orderItem = order; - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java deleted file mode 100644 index bc9ff7d90414..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -/** - * Concrete implementation of filter. This checks for the order field. - * - * @author joshzambales - * - */ -public class OrderFilter extends AbstractFilter { - - @Override - public String execute(Order order) { - String result = super.execute(order); - if (order.getOrderItem() == null || order.getOrderItem().isEmpty()) { - return result + "Invalid order! "; - } else { - return result; - } - } -} diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java deleted file mode 100644 index 6652d1eb49cb..000000000000 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.DefaultTableModel; - -/** - * This is where the requests are displayed after being validated by filters. - * - * @author mjoshzambales - * - */ -public class Target extends JFrame { //NOSONAR - - private static final long serialVersionUID = 1L; - - private JTable jt; - private JScrollPane jsp; - private DefaultTableModel dtm; - private JButton del; - - /** - * Constructor - */ - public Target() { - super("Order System"); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setSize(640, 480); - dtm = - new DefaultTableModel(new Object[] {"Name", "Contact Number", "Address", "Deposit Number", - "Order"}, 0); - jt = new JTable(dtm); - del = new JButton("Delete"); - setup(); - } - - private void setup() { - setLayout(new BorderLayout()); - JPanel bot = new JPanel(); - add(jt.getTableHeader(), BorderLayout.NORTH); - bot.setLayout(new BorderLayout()); - bot.add(del, BorderLayout.EAST); - add(bot, BorderLayout.SOUTH); - jsp = new JScrollPane(jt); - jsp.setPreferredSize(new Dimension(500, 250)); - add(jsp, BorderLayout.CENTER); - - del.addActionListener(new DListener()); - - JRootPane rootPane = SwingUtilities.getRootPane(del); - rootPane.setDefaultButton(del); - setVisible(true); - } - - public void execute(String[] request) { - dtm.addRow(new Object[] {request[0], request[1], request[2], request[3], request[4]}); - } - - class DListener implements ActionListener { - @Override - public void actionPerformed(ActionEvent e) { - int temp = jt.getSelectedRow(); - if (temp == -1) { - return; - } - int temp2 = jt.getSelectedRowCount(); - for (int i = 0; i < temp2; i++) { - dtm.removeRow(temp); - } - } - } -} diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/AppTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/AppTest.java deleted file mode 100644 index eb347dce7541..000000000000 --- a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import org.junit.Test; - -/** - * - * Application test. - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java deleted file mode 100644 index 9b77ea19c687..000000000000 --- a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -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.when; - -/** - * Date: 12/13/15 - 3:01 PM - * - * @author Jeroen Meulemeester - */ -public class FilterManagerTest { - - @Test - public void testFilterRequest() throws Exception { - final Target target = mock(Target.class); - final FilterManager filterManager = new FilterManager(); - assertEquals("RUNNING...", filterManager.filterRequest(mock(Order.class))); - verifyZeroInteractions(target); - } - - @Test - public void testAddFilter() throws Exception { - final Target target = mock(Target.class); - final FilterManager filterManager = new FilterManager(); - - verifyZeroInteractions(target); - - final Filter filter = mock(Filter.class); - when(filter.execute(any(Order.class))).thenReturn("filter"); - - filterManager.addFilter(filter); - - final Order order = mock(Order.class); - assertEquals("filter", filterManager.filterRequest(order)); - - verify(filter, times(1)).execute(any(Order.class)); - verifyZeroInteractions(target, filter, order); - } -} \ No newline at end of file diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java deleted file mode 100644 index 877340355d62..000000000000 --- a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.ArrayList; -import java.util.List; - -import static junit.framework.TestCase.assertSame; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * Date: 12/13/15 - 2:17 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class FilterTest { - - private static final Order PERFECT_ORDER = new Order("name", "12345678901", "addr", "dep", "order"); - private static final Order WRONG_ORDER = new Order("name", "12345678901", "addr", "dep", ""); - private static final Order WRONG_DEPOSIT = new Order("name", "12345678901", "addr", "", "order"); - private static final Order WRONG_ADDRESS = new Order("name", "12345678901", "", "dep", "order"); - private static final Order WRONG_CONTACT = new Order("name", "", "addr", "dep", "order"); - private static final Order WRONG_NAME = new Order("", "12345678901", "addr", "dep", "order"); - - @Parameters - public static List getTestData() { - final List testData = new ArrayList<>(); - testData.add(new Object[]{new NameFilter(), PERFECT_ORDER, ""}); - testData.add(new Object[]{new NameFilter(), WRONG_NAME, "Invalid name!"}); - testData.add(new Object[]{new NameFilter(), WRONG_CONTACT, ""}); - testData.add(new Object[]{new NameFilter(), WRONG_ADDRESS, ""}); - testData.add(new Object[]{new NameFilter(), WRONG_DEPOSIT, ""}); - testData.add(new Object[]{new NameFilter(), WRONG_ORDER, ""}); - - testData.add(new Object[]{new ContactFilter(), PERFECT_ORDER, ""}); - testData.add(new Object[]{new ContactFilter(), WRONG_NAME, ""}); - testData.add(new Object[]{new ContactFilter(), WRONG_CONTACT, "Invalid contact number!"}); - testData.add(new Object[]{new ContactFilter(), WRONG_ADDRESS, ""}); - testData.add(new Object[]{new ContactFilter(), WRONG_DEPOSIT, ""}); - testData.add(new Object[]{new ContactFilter(), WRONG_ORDER, ""}); - - testData.add(new Object[]{new AddressFilter(), PERFECT_ORDER, ""}); - testData.add(new Object[]{new AddressFilter(), WRONG_NAME, ""}); - testData.add(new Object[]{new AddressFilter(), WRONG_CONTACT, ""}); - testData.add(new Object[]{new AddressFilter(), WRONG_ADDRESS, "Invalid address!"}); - testData.add(new Object[]{new AddressFilter(), WRONG_DEPOSIT, ""}); - testData.add(new Object[]{new AddressFilter(), WRONG_ORDER, ""}); - - testData.add(new Object[]{new DepositFilter(), PERFECT_ORDER, ""}); - testData.add(new Object[]{new DepositFilter(), WRONG_NAME, ""}); - testData.add(new Object[]{new DepositFilter(), WRONG_CONTACT, ""}); - testData.add(new Object[]{new DepositFilter(), WRONG_ADDRESS, ""}); - testData.add(new Object[]{new DepositFilter(), WRONG_DEPOSIT, "Invalid deposit number!"}); - testData.add(new Object[]{new DepositFilter(), WRONG_ORDER, ""}); - - testData.add(new Object[]{new OrderFilter(), PERFECT_ORDER, ""}); - testData.add(new Object[]{new OrderFilter(), WRONG_NAME, ""}); - testData.add(new Object[]{new OrderFilter(), WRONG_CONTACT, ""}); - testData.add(new Object[]{new OrderFilter(), WRONG_ADDRESS, ""}); - testData.add(new Object[]{new OrderFilter(), WRONG_DEPOSIT, ""}); - testData.add(new Object[]{new OrderFilter(), WRONG_ORDER, "Invalid order!"}); - - return testData; - } - - private final Filter filter; - private final Order order; - private final String result; - - /** - * Constructor - */ - public FilterTest(Filter filter, Order order, String result) { - this.filter = filter; - this.order = order; - this.result = result; - } - - @Test - public void testExecute() throws Exception { - final String result = this.filter.execute(this.order); - assertNotNull(result); - assertEquals(this.result, result.trim()); - } - - @Test - public void testNext() throws Exception { - assertNull(this.filter.getNext()); - assertSame(this.filter, this.filter.getLast()); - } - -} diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java deleted file mode 100644 index f52f6deeceaf..000000000000 --- a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.intercepting.filter; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/13/15 - 2:57 PM - * - * @author Jeroen Meulemeester - */ -public class OrderTest { - - private static final String EXPECTED_VALUE = "test"; - - @Test - public void testSetName() throws Exception { - final Order order = new Order(); - order.setName(EXPECTED_VALUE); - assertEquals(EXPECTED_VALUE, order.getName()); - } - - @Test - public void testSetContactNumber() throws Exception { - final Order order = new Order(); - order.setContactNumber(EXPECTED_VALUE); - assertEquals(EXPECTED_VALUE, order.getContactNumber()); - } - - @Test - public void testSetAddress() throws Exception { - final Order order = new Order(); - order.setAddress(EXPECTED_VALUE); - assertEquals(EXPECTED_VALUE, order.getAddress()); - } - - @Test - public void testSetDepositNumber() throws Exception { - final Order order = new Order(); - order.setDepositNumber(EXPECTED_VALUE); - assertEquals(EXPECTED_VALUE, order.getDepositNumber()); - } - - @Test - public void testSetOrder() throws Exception { - final Order order = new Order(); - order.setOrderItem(EXPECTED_VALUE); - assertEquals(EXPECTED_VALUE, order.getOrderItem()); - } - -} diff --git a/interpreter/README.md b/interpreter/README.md deleted file mode 100644 index 8600f0300220..000000000000 --- a/interpreter/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: pattern -title: Interpreter -folder: interpreter -permalink: /patterns/interpreter/ -pumlid: JSf13eCm30NHgz034E-vZGaM62Kcih_BzQ6xxjv8yr6hBJT9RzC1Z5Y8dE-oAuvSCyJhPH13gLSdRNapsEdaBy-RXEus3mR4BQXpl21zVnykFmlgVvVqNaRszW00 -categories: Behavioral -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Intent -Given a language, define a representation for its grammar along -with an interpreter that uses the representation to interpret sentences in the -language. - -![alt text](./etc/interpreter_1.png "Interpreter") - -## Applicability -Use the Interpreter pattern when there is a language to -interpret, and you can represent statements in the language as abstract syntax -trees. The Interpreter pattern works best when - -* the grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time -* efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable - -## Real world examples -* [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) -* [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html) -* All subclasses of [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html) -* [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html) - - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/interpreter/etc/interpreter.png b/interpreter/etc/interpreter.png deleted file mode 100644 index 223148e00d8b068d0298b51e2aa62701481f0616..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27047 zcmbTeXIN8Fv@IIDpn?d9bVcb>q=Wzh(vdE`qaeM87U>o`N|7ccbRo2W^b(2+7;5N* z79u3{CSCg5cDdmM4kV7 z213=vS894)|Ahj-96LECQri`Zmn(>3^Pu8+0m0@}i(8gyR7YtI<(5yiGG{x_Hi%wl z)2q#lm~xC5W73|1L>tVo*NN)ixMSut+GPJguZtRolD(bXaH2pmkZ+rROO8o>VLqs8oF z4P`n-oARNP(d8ZB_@?mn9-$4c2A$5YK6#To?gh~AQw+Guw~=knhCK6sUBf=zNG2DnBEbB_36@no0B(cv3JCQW<+sv0|s zCcdncWJbGOcs|Khap&gfWUTk~pFO7~U@Fm|<6Bj{^siGa&1!Gn&5pXGNJ{3h@l75$r0y07Hal`0KrYHNUamd`3b%G;W^lzf~dKX!BtTOYnUHCw z!rP;iz|cxk*L!FbyNl}dZ6@w8E$rQiH;vc|ahLO=@qEs{!;}Bc`}{SP*1tEqZ=I$D z@8~?*YS|VLI6bJ`_7KY#xd6d^+f=ePPI+3v%qDDUKJs z-lAs*)0p63TX^WoGF+U$&)w@)g*CuybsxG{pW7ZyzyGhc~;4e>wQNqrCcrR zjll8Y1BhF_mi}{YbM8UM(V6POYZS_vXPK3mfy8^n*c$Or8?UrZzLCbWpe(3-lAza3a^uqSPZWBrWDL@4qMeX6)iPQ zFWP^1;7Au!so?-Cy{!r!zG0+8bGz|sp%Tdlg?NByib+_RzaO5FJCP-U<)y$2?&Yl{ zThy$#Ht#3k_+{MJ{9FDivl-V}&Ey&~H=iy)WNopUv7X*L4ehn~7W}68Sx4U#7TOTn z*MxMS6VFET>$|XF@LAF$1sL5ux7ewaWqrXqPjY6J8nfz7lpp^e*Po3qhe!{0X#WTE zwrm~`7G*GD)3kL|(M`HX@8eeu$SfWzl6=a}O=RW7^~zHGhub`2cW2sT3BevOC>99( z$4BeAVirx12Y$=d34Mq_*NTIK*vA^nMLNefB2S9dez*`J)qG3i8zY|?W<|H0ekYj( z_7+?(`>IqySGYiFcc0tP*n_bFrry{3d#An-h&a6_${xdn59KJLIvKm@mA(shEGN(Y zFtGhw#aHRvA0cw3@X7l-Oe0rEpwoxLCx)!4b@jdrW&Ec|rU6*cU%ZTI`q`GlO3kVa z|LO8jucVtq){PLuwSb-mgz@nk0~x3*X&vj4_XNa@J@_t0*okcb;6jUWXeMfB9N>9s24haZs$1{_Lrr2G4@5+Z*? zZvnMzdK!dTIrQ>kd-LhPC8PzW)7w)}zVC&LHZ#(G#uUSUHtUTGJjh?-l-X~0V-ET= z+`46$?B=&xQ+zs0+$yaommnW;yArWC)wK#~wWb*!77Sc4Iye&Udq)K0x519(X2F zzo#DKOH94ZwO>aRW-#IwpMQ(rcz2mQC50LhX^iMOUYmZ^To5p!|=N_8yw$Er285fwg@5TS~q;n$sSovc&KN@d!XkPBaa-j2YxNedT|j`7j2BL+tFnkrd=gKDXJn6 z9&O%EzZ0brCE#@haH*W13M4kUGJx&y^06VApm+v|4LN%YZOIBbw!~kd9iT!X7XSb2 z(*J=|jmMW1QXLoWMfrEgO%D&&3V_{Cv!GjT~E*KMW(ojHh?q zN(#y!J=?hj)U)MI(r-4sBX%~NLMoF+n{D=lbj(oZTTyBD;xqp;(G?;9%zxq*k}FE` z@3x5Rc7H-U_iD^)s#~Ep_jny7s4K(f;{r!AyC2P%`)dRiy(k;Wk@T2Oa|3_Yjb?S` z67_`@ElJ}iy6wDR@iZQJmWO4Q-|AdDiu1iPpa#o2VKTzgt}+jyw3eq_Q0x4cBYJngIP1C|j@PIlZPwHAL-V>5pX zuUvDQQxJb9Ad1eC%&fptq~RTOI^s{WB3BIh6bkMXNzuelhDK;uRhqg`VhRiED1vPB z%qGO_)=}_=5}GNM_l4QBQ^Mn~90=RSHYyt640=(+a#*FpssZ}@5Yjd@%CMw~Nl7ds zFYe)qEWkf4A^}S1&&^irNd<4S#Z7=?hMFv2j4GI1@T1~!tuH@o;FbT;zqQ=&)G(WL zS}M(WnA9z+8Wb9A^~mU``X|R-wNCCTjo|(^?_xtXJ+cuCfEStp>~g%?ak3qn?BO|2 zgPsq-xA1wo4Ora5Q?k>nlVAyz@n1|zhB?Ai2YZcG$z6t6MF4nAIwxi+Y#x$y<ov}$Vth@&PgTJc#s-e;E!CR@ z$57{S`RqsP06jv|Be`lI3<~Vnz>_yHkrwQFTTv@_d7g(j8nSu3=u>d6q5HolZ~s%0 zEHN+i_nSI_;@)0Xp~pS8qR!%tFnfFF#ick2%@CnNB@Hq;+J9`ZXrL%Y+v0y{O8z%o zGI1I@h@roKrU0k>?y`+pscsL9CxhNj{rv8a8N`I+Q4YvYcZ zVe?M+MoQ4r>$|eF^{!O#>!ARM=;btcBm6D?ex;^WlL^$ht1811a+sxRRvV!a!uD^9 zc8Df>Nteu{5I+>T`T55I=WSO33k2JH&>%`4R75-BQ9n~w1&(N(jGtmwBlD^p?Hc#|U zIBOI^41SRDi{G*gym^C(yMCwvof>D2k!520z22N4L)}NXBe_p?4;Ug^9YlY&kLiY% znqFzkKhw26(?D-Yd60VsZTQShGqQ(?b$2(R1 z8@0=1sNQ?3G$sKgVnTmWFoD=Ov$DVH->|tRmH|2KdSV=xqN>hKNIAZ>XGe%`D>I$m z?JE==O=R&NZ^-MONc-lHSLizbi2s4aw6ot5q`KKa8p+_@GCJY#>ZYL;28IXA$hN;( z#4rAkFlIoscG7^8B$&o?KbP=3AF5|s3ExHX<)JtO($)UXtisx{qlxphE69|T58B`e zvsOyG+YiNd3cnCZgT^zh<1rV;rlIS>Gx1Hul>js98G`z9^Li6fbncVx4R@>C|LD%~ zMsUB%B~9;RC)O#Z=XzU)JKyUl$;-SYTxlyl-L)D!aKIN=xZ)xY$nL;~ZZaEAen9=5 zQHcHlV$%FJ^!3}4a9~ugJtDu&c94>;?5=)UJgoquLg`Yta9n(GNhF;jfBJ|N!iE0r z8uJ32rGQl;aPd!fxOp{2x0-R`r&}$9lP&`|%kNgw5>K41>b06_uT#`z8?1#jU(9Pz z^e-j_?>3kt7nI>KKFZ4iBA{^Lmo3<2#+l7Y?Mr2*S1|c|jA}lJ23G#P(o@a?+wuDz zpJWj4qNlE#Nsv9ur9`@bYG4RS)@lFlp~|DoroPdpEkld0uC`-iOVtv8w_n}x`Rh_> zLf2Mn-EM0ajt-2E3DrXDZ>@w_qc!`q)C?J_FnO-xpzwr;&ODwF{d!kgCiwWJ8a(Af z#s$w^v`~xl?fPG=*q2JKW@ZxCe!JJ$oX=RB9^k&e8K`Vw2Jvv5SuDI_Jk}({$4lKT zFnOi6QPUbPp}D())zO_@lN#e_65=2Vq(6{}ti5KeqYJr)cA3+D!fvfz16>s*6U@IGl!DpYV<8h>@X{qks`BDGl$LQLx<>z`&F<<0%3O0c)WEy`NEgo zB^8*=QQS7uHDi@qAWqXxyvCia2KtZwX>K8($#G<+tONJ2Ihbq6=R(u5H5S(*()LV> zotcV!N7p2t$Slu%ZDBM+CFN-Ew!Uz60y)YrAi5u z{ZUq|OXyPm`=O4CSJ54!JMIxv@6IA!sNROLXx4z3-T*q(lm9zS;D0JB|6e_;=vqwW zq}>Ls089b?TKy>E?zYg!n}+&jrt`GkR@A$?3a&4JLUwK0pV^L;JZIkF=!f-*r;Nhe z4%sLAyA4VFR@Ao|BBtK^$dYn2ha-uNu#+#stSOI4(>4U_hdUjmAq&4#5U=z^>HYC+ zU@BFB+Gj_Y>4kVmVi}u*`kIl9gdk!hv5YCi^A`7jJE8^C0)6K^7%3MtwuSUwblhg-|Ds`ClJ|WhYA*4MP z4?a}f7s#Eg5^!u-4h%G|@<-Iw>KepSI}yMBeqQz~){XEyjH=@GZ*QmQF@=Kk|8VbA zjIP&yC8c;DH1108RTtMrglqTa3-5_RXS%sxdV)QC4e$6v`}x^^^atsgqi;TZz4-5O zF8!0(sc1TZQWUDUr{{LP0{?Owbnit29En)o>wI;+{dEa(H8(;-PimLXqc2^uwyH|6 z3+9`x zm|I$Arl&JAGBUETWMpJmn434b&s+r5Ke2!6A4D^xs9>i9KQ?A$Y@GV#%UHR!a+8In ziOF(_L_&w6N^u1f@(5&<^2-ChCYesddrvE+E?Ro-@~zKTC!lxW_AhDwIa^{RH8(f+ z;lqc*!op5YP8FX!H15PlOBhfx*@X=bITqyg^QU9G->X?1*@f-$a@uF<>7V;{jZem7 zgtJO=B()-}qxU`=op-4w(?Zh<260gLTDDU5NQYKEiuOb$n_Z~2@p@nv8G|7G3M5h^ zF~09boOF8%Jx;O)B2J#sNU^I})lG3U#LoT` zu1ZF*Mq_QheR{E=}NBZz6apfz31{;W=Qz_>ebuF^`o zOcS$4&%O-G)v-;+Eh48>c6tZ9$BQ!k?m5VQ%b$+vk#Re$^!!p?V`5TvuiXBV?prb{ zq#&-wY2Lu@!@h}7buz&g1-~m#R0PMm^UaO$7nvKw`)5)p(T>c?DHTFh##MTS zo3~4yVTL?&LWjm~N7|7eQ8!1{{PToqqLLHgf+)Y_go2526cvOR|@vf z*>n3yp7IXIXO%EEWpKw-Tnx57Hiixdoa1+BU0fUto%yNeBJ-b6mE)8KGe7&g#*2() z@;l9X+|j)Vc5JU}#zf*Pjq3HuU9GB;mQB}GUoS{$9)A8$x3~a(>3o)xwY7`QTytb3 zUef3ISE+dlAOE!P-l}fB&i#Mx_mI>a!1qa$o?>M0dNI~%1#7VA+ZED!@s%nr_lSm~ zH6r!)2ES|_Rx7-hl`JZi5tseIAzWq(fN8mSgo&jLSW;44;&Afe!;LSg^-!0!#r9~z z+GFm2fL}z7aj1EJuj3Et+j&}jdGstFiKL^WLn9pP|EwgBvw>e2q)YCfJ?85Ll5F>o z-#A$m&*@Y`6fsrc=TQQ3eWc-Vafoed?&~XrW;HjJlo0kLc63N8DF^%e_*B4`)lsTY1f75d08;?bz>*bZT>T04!%NPhZvMFW z?WBQL4M@932d{``YD!8<%e#KT^8ydRH~PqU4DI@)tE)sz%Qhy;iDDcaK4m3SwdDh@ ze?5`QmBd7U049wWniD(to^lp=Fx&>HgbZzqYb2g#NL)g~Z?=uBJi7@UMg_MA(fG<8 zt*(+9e0(rDBVw3w$7&8v&N&M&2Zzoje|ZvH$ocNW=Tg%JY&tw6g9UgoI9xLLG(e#A zbsI-fDT0hsH=}>rX?FtJh0mYz>`Gq%pwPh3Fw!hU?;H$KJ1e81H|Xxt(Y3>(j-GnX ztCy#USW)Y%ol;Mn{P%~k&@SfuDZ7}DA616C(>Vc%H1or7i)D#|RGwXY)UCMK7D@m9){T3+LD*au3q`v z34E28m!Hb07A|*)am*o+=-Xx5e&m;0fBg!ZvU%>n%E0iMkq`RPt}la6Qdg?2B`+~F zXuWpCv2(mE)BiFTu;oY-Yv!@HIzDux(tCYMTpZWe+q>)aRrAHpy8k^r68f`S2{PHn z#l^+SDyLh)aZYM>;PxmEH}~tMm)Ed^E&%$>s~$n8#|P8ia0j&0lbt(s6Jh>u$;jy0rV88Fx&vI}catY3!XorzULQu^pFo~9an?#s^3&e_s^00#cRz@V*cW2{`h z`Bz?E-rDbXi0pS(CH`U}f>*?Gktl(0(G<@je?zhjcZR(T3MzDuKbd{)?X#=j!MLg( zdXx>?uvs;>1=D=aEV@6#L4Y&u_Vn~jOiX~eduF%4s_)Hg+L@4S^?mq|bw5g}vL!unpo}Y(@jRl;iis{NZcbw?g-{0c&5D#qdUzA-6jfEcfH(<+T}i>iiHeGl?Ozf-hspPO>QTEAQ++0fzQ?&MQfGb)av4 z0-z6aY24SEV-?ut3U8A@>@4l}J~A04jDUklEJ|C?ge7i*A)1TSC%$@d2eiUg28YLw zWD=Gpt;5JmzA&v)+?iL_eh|@_zzTiy#>n-en!_{L?QZ`+zh&#`a_E_BE&AYXC4o_2AHL6n}a_p;35)u-Cg6*-Oy)Ni3P8NYntPmNq zguJDUp*~b4utd3f=zlVMNm3IOb_>jxiP3eHBMn;UIfmYRBlZcPBlj2uLhs9RVz}C$ z$(8M3Orz?{CKHXC$oqrc5&dq5wh|hptE&qU^w#kN8%zvy;Mj|D7U=gwMS#Xwl*BR( zXG!nBpwQO5h@Dc&gC*|32OQ?!x?GQ;R?W&Bl3_3%=cbc;(l%NDIaelDC&lUb&mZ@9 zp{Vay4+o(|Cs#*KREDFw6D=(@FP>!bbH&gwa{m#@ZLPV2A)D*h8d@^+*?VQ_;0#`= zR#G#5kgV2x8RzwDdL-~^%vQV)cNN1P=W=iFs>8fEqS2no4(ITTJ0L6e_;udXdyPg{ z(T=)^9ezf6$J{xZM}(TG;x8`)E_7YQkmU_%4b|Hi`gGA2?ATUc|B;d z=?S7{yeG+4U|G#NY|OuThY+pq3F7!oKU}1->3L_qwY7Ej>n(@Tx;L9S zQ!A>e^o?$e_XQxDTnW-}&HC$|g_fnyPsYua9vN=2n;oYlO-pE=nOig21w4z@zu{zu zv9u4@b%WOxn$4Fna6>epog-^Eo)qZAb&^S0BqWu;ou<_6@^aDZ=b8|a+)K_gkZi9* zXNh#4@Kb%CsJvn^2Jguq3aAX-jnTwB8Sw^bDE_Dn)mt-_?B*|-*E#85SS!01wmZMS zc58}`;7(m+Ug!X>t?yK=d~(O_`Tmx6v3bSD(ae+tZ!CCNqyz@THF+)fYMgBwf*bor z7-7TjZ#AAg#?x4Evj+6pyyGjiq&7}M-%_wNHJb5#iyxjLW zW4^y%TX8LI8KCDG*#=tXD}pZ1n(n7QvieOr(gR?n3tEdlqLVrPqW) zd)0owdA|(C%yw)o6Q(vP2!9VYoHUA}_VafmB_C&24PW=~n}~23E7=z)#Ltv4Zo-<; z;5%BCK6%yyCRW##8Q?y%53BKeUA_4>msSX49{6SbicyQYLHZlh4XxW18r_r@K3=*S z_Pq9!wK$7iOV}EjK?DC#=j340x+@zY?99Q~cSx*eFyO1%YIyL9OBeb_Gj(vOfs?Rk zFG^ZkzUtYdI-rWL?D{D-c`%8`0bm&)PX+Z>@-9yL*eQjAyv+5u^77({r1#HfgTX`N z$S%!EMa7jdIV@&d7v9_Lm=gGxdMKOEv+Awn-ll3_LuWEp24)9WCRiKGI+=fE84#-v zQnY@P@+nMLk-j&sQr>s-BrxS~*q}$|UPbjx(t7!1@=m_}C?9Ksr?VCb?XgWn=FV#z z*>D8&jmpPUOeJXN}b{)3~MTcrsV@a)`__Mxhp#!fd`%9}5p9FPqJ_4 zf~S}6HmzdIr^_%d7!3eT3ul}0R?K$68H;)}K_l}otJb2tlda=7f^BTt5m&vgE$k=? zOFScoXbMK?sN1>mN>+1lXU7cris=cbgl+bL6(S?7-Gfb1S zTh|t$Sq+yV=5!3D#Nj!!LOChuY{=j2mp1tl*pe7s_0FCi^}l#PqM~_GuhRfkW%EAGrp>_}qFycHv@KkqIIyZZ zsXqqs4SqO~Tk%8em>mdU(PkxSn>FYocW>`n-FeqCExV5IBT4*lSk+XN8uHhZiP$05 zAQCu@_XKk3r~r)SO&21V`j<^ce>X3TVbU2=Umi)DhcwyUw^v3j zGr`au{kt7w54t~J!HccUyCKD=tlC_rDa;m`Ki$^|E@`;iVlHW~Q~SB0HPAb9O_|wq z=~kp6rsybLa%~S*osOSxJK60}C6xJH%KpjPxeA#(l?}q&UpdH#Nt}n^Mn^d~IE2`B z?#xDB%W~9>vGVZnc>P+T2a%eaP7-0aQAY%hxJW%Ce22b|Otg`xRefWNY%VlhErY<< zCvN+1e(Pl$x@j_UDWH~NRpI2lh-EUr@=PRG^mAeHzWm=)LeGEe;VyMPfK-Qh&=eOJ z+t?|`B2s|p?LkP=eSZzSHWzyuHiOdIaI!1GX__=P#~7jIMyyJ;y(j*vf%tUsW&#hx zrYR6-P4|q2#KnDoe}8AS(DRsF*iNh?=GgI$*H-KEaj=V(AT3h4@R(2XA!y_hhHPFZ z2UzV*b~A?uT8!On7=B-E|8L@8FDolHd0e^6GNiq3XV%cv(lP}ex8J%<@C^O{%t&bCFGgTwYEywe8QGXb>sx)ejLjx-yp zpEDm;b5^Eq;Wb2`Pwx28zpmJdeJPYkqsuk=ZA_%rx$nu-r>j-N-4y``dGJTnuHh2$ zW@w|=2hvC+vUlGd+oND~E0qSso4Ai~iMr^SgN;HGi zf%Q_#L9=8A&itNqlFam6X6$lDnA$uwmF#qNO+ER_!bkOCtcl1(PyZrZU)-Dz{aicx zjbyp%L@hvdf#{Ve*QQ_j+ZwYSJnZV*S86`%<+)M%=*3#hG&7M&!O&ro-VK1fQ>{Io$>z3fR7>ztb9*p>6n>?3dK^Ea zmq-^`nSA6sXurvo#_oK+AtEk8cA55Q&ouSWqv$NKkCkhquPE!ie6VZBCE4Su;u@`}{ zBD3J`xJ-_UlfTa~kA-)G=ab+oF@>tjj66%x)JgIkrva>ikL_<{SXLjrgPEH!1`pKd z+M9YD>d!yyrC}_t#VM7ZpaAHbj7z{81XZJ>~*5fkUm zEYQA>%g+$$_G-HA)PC_RIbTe6D^E#yx5B2Apz4aDKBb=##70Q0{2fc$O`RsjEd0ZO z;3WvwwaDQl{O*BuXL{tT;TZ+spj6n9@*O%x9)ho7-#Z)*dUYda^z?htgxQhY{O6$! zApzEw3ZEfXbx4Zg}cFn;9P}Lu%W@d@3<;&DuAUz5o`r^Mv#}OJ9VDdw5ORfv% z5YZ0P>Dy%2TCxXL=JLU;N&+E4=vT|P&DT@~xQp!;(9=-kpXi2kpPyv)(~}<@(=(!j z&-Q~iYPk(BBGYtB5Bp@!0>o&mG@HtX;JSAZ2*l$WwPH)}!*0vdt=~UBe4fFYoQW!| z{KQ|}P7Oy{`kZv4Z}D%ZSX6i_tovfqrKk1|Zg!!SAev-a+-{zpp0vw{Hw6WMLw<0{ zX{^$Bf^XTL@%x?l+9J(_(yv`(fw({0`-_D&R~F=xq<`yqp6GAo8*B&}8PllSN^FcKAVH4q~Nll<>C)w0>X{k9% z@#ZX?a6G?KiY|pKv|T)%C_9-zPw$pmsQU-@N$p2)-sL5PUlWl?8a4O6Iijten$oyd zQP>X>rR9Ef=i%1w;71B=exOTY&8z;leNC}eIGtT&l~#XT9K7dh?!=QAdn{sp_cM#0 z%b}P4Ji9euCt&U8TG!?5?)Li474H)f(CZ5rvJdh#^SePrv+ah$<~w$k)w?`G+Iw0< z;!TAUtI3`VSfDo3)2G7W#a5RZ0BuGIpD)*>0lLb_#Cem(HVxQq6x%g|Xj+ey6B9oR zii?lKi+Zupt4ESevPGuci(VRdtkfIjAVBg z1}<2==iT|j#|KE{f%oRGfSBJBLoT!#4UHQkrI?WAT`Q2IZKe;a&d$z&GIEoWvJZ3}E6nIew*KQO8N?fHg_o(7lDtEA-I$XjXc9V`Jk&KkqD3 zu&Zn7q;VD~3-cTD>gAJhuY5xvB^Hcs8gU9yhRZi;M=lK*tGPAAUZ*!aiYECd_zR(G{{%W6E|9 z^@S`5wu5rvrOH1JN^${IiKoyJ#(rjOx+Ld-l(@KYL+rJ;kAYFXKbi7!e!DlmHeg zkZN5~S9hd5se*FU%=5O{V8IiI8F|iwa9Yg{+#^l9q4ZB7_ z?}~cuUwj+0bjXK74*T^-P|>I@yI3DQH8$W;un{i4`lMN-2g;!@lE21PGpM0}uF!SE zR};N#qhJkpBrX~ItWD_m&`cjNBVQ{C-9Lz*6;Tp|*1aQXScrMy&m8z>yaR4P1!vw6gk{ zS~FQV;cR({6I?!RKfE@-Q4r|041=$mEZ_|u+CMf-8~AW*RjYft-G+jaQtfJ6@;IZP zFy^X2NuU_~llC?`jdjJF_ju31K3#&*B_MCl{pSX_X@nkGo%Ag|Jv~X_oXIV}Ctki} zkK62SDkwBW`UK*tcKW^U;$Rx6Rj+`L7rYTOPv(Ob)VgI$MOUUV#7PAvyJQ3JK(_AY zvKMCgK6!@*nahwovq<_b!)gb*m$hw|Ly;reOfNeum8NlM2@S5lnQ@_U`+7Q6qs0d= zbZV2QVz~i|(vZ~9O15Bj;1yN?b!{DHxdGBv1n57=Wi<`P-Q5pE@x_SWw(IwHveu?g z5@qz=S~at2IUFfdbp@KE@j#>DQvYgeL2m(%bwCViuLFlZWjK@& z@BWI{e?gU$cp1zU8Zg^*N9evN9@pb9@OQSgv!k4-a&F#E-xyxmC7hiQ&I47IwV36v zTrqwMnh=#&Nh!bPXzU3ePN;eDn*Cl$ZDtHjo&Hhfgn}O9vRjt9@h_uYWMbRpa`NZ~*j=0XZq$IyfD3;epT*(E9)Kn_!%$KO}Zu|*6oq~ zA&Y#?T0Cvp*&H4ghEVU=m^*gI#&WgfZ&&hAw&*?nqVGw+9S`tONyNrXjNj|-OU1?h z(jte+6O$V<(4P#&iFuJ(d4;1ln>xHDQ!Mb~%`ug|F$lZiZbIT?(6c$9Nx2Y${-h`w z$36;mL=`BOHak@UyC&x5C>*TCMR_est0zMe#xGB(-Z#6ungtEtkd&9Cyerl+FvjQq z)Ni=Bs>@Jv(hUL^3c{AYZcG4c zvuz|73dc+}+Nbhb7i#{X4s{-eUy!AVVcR`IRgt1&}Hv}=%&^&b|SC#TJ|IR3Lg zJw3oK^ePHxVUBLfbEczjV5vXbaz(xOV65v_dT2(;%AFj94_f}_1)S`$9!Y}XZIJZl zs~o+HpbzALG$*?@bayY2hglN4epI>^&}|wH?B3u;DVz>VjeUMt()%E|194y|;zK@` z*{&{Y@f*1AsB`ylz1wGa8jP;cnQEMAmomz}pPZZwFxGo-&U5!r0y_*l8icucdwZXw zSJdGYVLHdx@8g`4TLZT)GiQt^NdFsghX>zoR@!4>THLf&W7MJdGWl-im>(jaMpn>A!3LB?8pu+KLJx7a93P0JzVE_ZqTx%i6im+=l(-- zsFjtKy}ioM*S5Cvz;0RBCDjWr83Cs6B1h>I)yCh0#RA2pI|*3R>bfWG{J<5MayaXo z-w$u}G5?)k=?mD$pbSrU{kQfzg=5{=A)5X{_gyfdbL+yoC5__enAE`cV>@C+m^V&0{z507Wdpt*ngF7%*reAm!b* zaSeh|4#|vs^-BzljFaWo;Y`iKx=!N<7eSTZp%-aB4o&cvT6uX@#i^F8GcO=nGEaIE zGNqvN#hUN`hs!+mw0bVCE}=!@xJFr%JVw=AS{TBkk}A0LYvKiNG7nxMDJiLYS`b4? z8x!j#4$hS1V|V^FKR1>((d4cmjb&oH=o+SuO$@q zx%o{_TKI?;s3g@Mn-_SNt#IlXj!KeUWwkWmwY!8_b<0l`Z5G6E*XRUos?fVTrrxJo5ok#X|=(DyB=i_uhy}YQd7V2BI5D1mIeCwd-cZ2 zENkTJnW)fM3-7;&#jyd$z>im0Hv_Vpsgc$bj}wrv%rt{HxIdq8fx+|yBaNpaF1Lno zl9?km-$m2YV(I$jpLrwpsBdzNq-^O*^nrL9o!o-6bU8pYK-gw!b$CxK{Sp%rs;H~` zq9^{ya3?a7%v)nWX1gH|F4OpT^GJ(d)$z<{h5%!2+FWiY8_+FF513!|Oz7~b6%#DSQ!8Ig+0h;e4RTY1{4N8Q5h8G2EYX#AeJn0lz8KxD zCmji(fn%1^-e)7q9Imd@2gT86++;xu;e?aQkpqFunxdy?#Mv@weB<`7xg~USc~&*l z&tams^{%iUEyI3vcf-5qn+-ia8q3-5mNnDLW4Y-6#1<6Hti=$Y!qyQ}D#t@ICkeu` zZ;yRO9G&t32kl&7;(X>%Wx`kALwV~~CqYH@bKTwgWy$XUmJR5A^OMM=zJM9h&)A?% z>RC^S3)X@C3cjvkL_^-}S}IU-tnl=sqzwZku= z-|&H-VYO;J3w@ca%*^;E|JpIpO&5KKXUOyE>4E7xBb4K#Pk{aSwhE@FZ~9x7qZy4% zO(%I4eGxYZ5cW+gM0p2ShcGT*diw>Kr?@86*)3=rF3@u9QU4rb zKUDDq6%(hK3Oa8fLAtlgxWk?WAh#QTWu6@`SW#dR;<^z;FZG50>bi}OuXct8Ct=Cohj316?nt zXJquOxZm9s+c;k0Pq6uAHPAkF#jEQw$P)mKd*L#iy-4ZZLZC^m;sU6jSXuDw-*o>N z&C?mnK-JSz2hWzlFD#`$hi^aK;}QW)mAjsPfu0em!c#=P`li7uJ$JnxPg{~fxD0Jd7bpzoUa}fKpf`&VhUdqcf_wE6w%Dm5{Nf*vnpGE6N$sT_z7Bz3o2fS0nJoh z|7p|WvhyV50rm~=%d~rUbYBEWPaXt&gN|QaOAEK+9ela3-t%n3?bPi|`B*7W1KGo$ z5px;zk^-Xn_L$^_XwaGiVH`?6Gc7DHFE1`GMpARKt(=t+re2@}_3xhI796W(q~i*8 zIbx_mS1$rV9^{VbFqnd70Gr#ZL=x%iV#>AACm2sXVS{`&6{=#5=HoV6YF+=sa%8ckU#90=;Ae zn!m-51}~!$^_v#s=zI`S2irF@o64%=u6UUx3MbTA|9wCA&83S3K|Oz*ZVst5mZ1M* z5T&TwX#RWoICKo{lPpI~6H16;j>$A}|7M_>cxgwc^2ADT1Z@jTqw)C4>W$b4Sdg6C z0QMbzn7TE2L!sp(j(Mh9c5;Qsc_2{M1Q3DhoFs_oTFX0Aoz--6Onu=n%vA~8u>eUg zQl7+5=p&P9brU|>DfQ~F;vfI2MFo!_Yo@MGWv8?*UM>HRIe?=evqFZ3hV9B&EOvdo z(hgT@j%|t%wp#);hQ?|@fP|+5%Y53^RnbiYde#DX`-|o@IL2ngJ+!X4VMMeO)%CYx=ePCBlG!^qo$3xfQRdJwTZIgGiy$JUtDe8)=MsP9lCZ+ z?~0blI;OS8jzGZ-<>ku{y6>G`tVG5VFM}2@Yo>tmsXY-~ishO0FrX?x3q1D!zP;BRL~LOt4SA?u-R0q65F{~vWb4^DZB{8g zZN!hap9Kcq`ZsWcqyEP541NAw7>ov`gc{(Hk^xHD+kk&7=Y{dzI4rlc{JS`3nVKAm z`rDEH&K==;1-V@zs$bmamYmLhZUz6p2#NYHuKjc^SZKfyRz%0@&H4Nm<6a+cr{2Ri zmEv>Y7DO;y#?1!niqlki1VNqp_wcDkB>myok?FdUB)BX2N)DsA{jYxeZuV zJ<$1rCy@S&ld)ANkfzc&R2cg4ji{y@;%c?~uY29PYryWwe0|FXVm$nU1s{e{H<^%0 zb?|%}^|hpTo1aSbG(6+p0SBW0dmKFXK)Cs31ugDmw+gWOj7U5du(9cZ=2sO>uA{PR zbi5s?sPtZi4>W@7AiUCjJ4M>R<7#3v85H^Y*+A*&JSv1b$U zwc6n|B?lBLxdKw-Yq&bZ2H1ILhP7ZFRikx#o@_-zI^@F8A#W~$8s1gK-Ub5enh7|3 zt8!zH^gUuJUbAL*&Y`xyDpT*jnZZW~9CD*TD~`T%)fM19NgWgSPSvtdJ0|5NEj}2+ z8_6MMTb3mES3rt?fZ-t`xbR)^6Nf!3Ja`fXw@<$E%s0me%3LyXhWXT#Ltmtsi!n&9 ze>Cq_a(!AFCkxff4Q6p=Pk`~5O{t1+%-(=C#j?jqU#G`-p`=UcRjedq1V08VfBd3% ze``}#pPQ|yjTC8|Q0FUHOOI&dk{vFgMW&6TI;f;5b^Vxmg?@FPbh{VqDBj}xO}oao zAdjQ`80YK*o%2CN16@=u%hj0{ksatRa}=oTWeIOh2U6kZ+Vm2%@KZCk9&@|ecZ67n zvFMU9vdXA*Q{vN!SDonw(VTtBG8D zC%VogglS-0lUB$nC*ukVZs`v6-*3_<3N6~Ysy=a7N!;5um{xn{ZYh=QL#~}uLkZH=b zRRey*G$*UrCQw+{_RxCw$~YK)lMytq>{zteeZzBH{&q;$I_#Q5605NHD>88ro_sbj_&|CRbmm|_4;XPy zf>WUR_wQohah=t_MdPrJ)W@FgHIb%Mr!z-N)Lx2TEJ5mpbH{8zPKUkkAKt-C_78S?IPYBKv~fM(rpJ=9v|; zHZP&=w<@U@=I2~vN;_!Ths3uA*|5m#WIXh5If_S(U(0rQkB=|*1vFsbQyvn z#!$t{!dzX`0$p;(rON87g{=5_pN{Y4coDj$$@mBvj`j8pz5l(@ss_bGE9UYZk*9TK_EF%#C> z5d9%9q%nEIwuR#stNzHr=VN~=BWxD_NY-6?%s9#|KLwS%a)%0b0@q&k`g{P%dJd<( z&;Fu^OZ#LJy-*`Euyf*JRfzaCfuu66LM^4JcF)-FmZ?MeNFxKXwG8Tlc~*MEaUi3G zsW3dER;@ih^VAj=p~*(y?qJ5g4l6>@2ycLGnUH7q7%Vurf1DU-w zvGeBo%{8El_t%Tf&CLLlmF=Cvf*WLE(R*O9;VnRh!x8uH-6Il-pz6?0wdinP2lI&m zog1IW?ECf=Ui`n2)FRC+3O$c46vPl<|4kr(!zWpLfYs!-TFFnnW|i){K2z?yx$?@lItaAY z&4zZuU;&_;4jVWoF0Ppka1Pe{;68^CQ$HMlmIhLwep-8v(tbAdb&HMy*w+n%@xfgu zx`&6aeD_K|*gr4@y!Hwj+(9FO(VJT6uyz4>9j12i^5xraPXWR>$SbH_Y>bfyu-n)L zQ0z_t#d^65^cz6M_Wc7cE-sdqgzw%0+O+^gWhlVcH9r7=x}~MXYzWZL1%NS5SmMi^ z)8J45WCByWY3UER-gbk%e)3z(wskOOA)p1veoy534Yv0jI1`f{YO)((#~wkSzW<5K z?=X}7prG(Md2D>g*OP?#nsoBQd~QOnXHz+}Fhh3cTa1PO01NNkz*zX;FBev`0N21I zVH*YiFbh`!`94$>p5?4+YfJh4bJqP0uoI#0b2dVy(k>`<655Oxfwh#|Kfep93<7Su z?g@ZD{)7;RnsQ4fD6u}{Av3!BlGKTxze=)jr;f?diCK#tIwPIQF7#r>&4swb(~UDa*UQi#cA%h*~vk+ z{kfvmI*DU{QO8;F0O~jo@Z1S=NL*w!wq*`ufFjI2-N|=2jNDZ)akGfR08sp#3k(@(J*JDRtTQXfWh1s>ge#G#5vbx=>hp>v_2pc^8tcCaO~@DAeRd?+qEv_d4T^R;(JfNo6-( z4w<&DgL!O$PExGeJ{Ns#lic!{T9k+5&z(*qE|7OWbzlf4gg}z_tp3WyDG&hV9-z=* zgNkg8GeE_XI3bBPlkOb=8Pkb@|4MUYuKkMaO<~J!C{6mRH^J@p+#VAeVv!QwuJd$( zAHupF|WMQ@u|PqmCkBzPUpzA(>Mwm4b%UL#LY&= zO920lj}tF=HkyC!lY8t-X^Rot=>xC#AbVG)1C0U>PDgvYPc_CymjS9dm6^i+kEeo_ zB1ho$v*814n{(L}7wd7ICV{#^dmWJ>!*hMapXyDYu4pWoQrG`7a;Lr$y}hOgAokwx zsvk=4qm<9~^OD#zJ!(`fjHVZ_XYbUKwv!?mE_H6bnh{~s^SG>JI_O-wl}nW-7d|{# zothv^EQ~g&>7^8%t46sgxJq&?&b@bb~A|`yF%I zD7@_7nA5~aBW)G>i6XHSt?+RnnR-&3j`%xOlNV&JN|FT89yhURj-VtTgX#JDZIiZ1 z66~}?r}gK%?vi<^(@$^20yW%whGFS0jP4bW(eeUaV9x;h*UcGS(&ywZZjmp77AYQ9 z#49;o9fVKWa$%(b8l#f+fdUCn7awTN@zqMT)aq05O(up!oxJapiVk|msxpoNdTSYxrX`zd4 znaTL9W^t4h@otF~SlRkbkhNA%z>PiWb(6iWa{@XFGk1cS6c;N|%e!vSQeqXCqst<$ zk4d>pOX`_plx{d#k4H4@!du)nU;C(zCQClC_a@psMiFJ|N3hu+VLzw||}qTR|(p*hb7d*4df(;R8Itt(LtJJVV}n4f)Ly{iuKclf+JuIV!0 z4fqYK@^S-&#PK(&JhZHoypQGC>7Z1h>N5FI#oehLpr51fP!h*am1b6@5B%?CXM9h z0sgLx9w%!VV;1cr{BEy5y2@U|iOqx$!-GfRXw5583SjSZMWN`07ofxC1wxtvv(Y4i zjp=;nY+aZ1ygoo#QYE56H#Drz z<^PFu`;0R|<_@&r`L0SKdvyrE{wwpMse%LaG5R^#`WG$yAv#-J8BY6KzK2)h64;so z{)1_;e6@*RD)bLa{Y#)1tFi~r(~%iDv_Y`d9$|is*yyOJK;uN1tvlO{y!uT z05SaXX}e;&igiz9y}dLXx2Fh6SPYb#M}Y1QHm1U*4=fA%R;v7NenxuMebDF))oBNu)6(RrZJ>@YX5yc|1T=W z%u+(!^mPB9&&M=Dz6`EJgSekWIdic!35b{cAG9@E4uDl&*6k||%bP{%&7q?7>7@h? zJ~H2`#L;6|$3~`Dr{ck8RBXtd=7&2+gVy%$Yv1GQZ4U@C{+cGXgfeE3t>y*|UPKVh zlUoaV^sU>hAL=xqIy&yYRhKG6eheShC}Le*it zTo$ty>kU_hH?#EHQD2mtG_BFc!(R+2#iw0R(2KPqk4si#(KZ*-qWOda_@Y z>M6-D(qSb}yv=kyY82TS`qs3)xGP6IkvlFrLA~B}Z>Q#n;``4I)%eF?UIJ#L%J8g@ zDcvit_&jwjVi8ME@DxDZGfM4x?fkhkEt)br`q4&pNEpKb&lN1ZIi7MW09AW(6VKFz z@LV2zdwFK-wQ#eOnXbGRBTUc#o4DU4mT)k;NB*2R~9z&r2(d;GGOvNzpwo>!Aq=9Z{u`&Zt8R^q8vh`R;Iv4^CuW&N$&m9?8)f{|MuG@b zk-`WQWuk32uOq=QqBk&Gl|@P$*lI4;PN-Vq~OX7`3X%NXi z5vz^j+0M-^OV0AVwQ0Q57=cSGggM#lMe zHQPTwzG}BWR*4_&ahOR=(HGZ2MYoag^y?$xeWE>kpK)(l4FjN5g4h-*lHoTNiW^?oOrt1Ow*^)+?mt48fW9)%%OZH`8j$BEutscQzjG! zdpyJF4pW{Xfd>!XU-gur*|}Zax+An>nw`Zo@NuDx<{D6YS2}7 z#m%SlIGPuPK%GzCE|_F1{#-v?HdM2mJt|*QcG7HKSi;?r8dN2%Om!V9%Nb8;$y*-GG%nF|}cN8LJ@5Bi>5wuE&$Z<$|XQ-9ILp)ggCF~`XzJjqFTLGSKuj_q5 zd-h;)25=9nlWZ;-YPB_INFxut?AR`lMu@H?X0vT1OWmWnWZTErZI3c>bnWjw6Qf6p z7~Lg#4`0~of(@1d1*zLNN3zSXrI@-%x@wH@`q(tH+3cjz=xFbOK&9kEvs`r_;HL7D zp(0)6XH{liZDQIg+Og?*!{)aRwMyyv*Cn`^c_=n$;rG_`reNOorYKW_HA~qRfxJEy zki7rk2hs~N&#E;_Ps1C?nWH0=@(NRb0~b`&wYiucUd_Dl*O{_}ie};wi3i$&5wDUy zTW>t=ZxtjpWzc;fPqM#U4^-Mo!7u<8ne1Q`M}vx$SYj7yDQ>j$yRo$^Q+?E{he`MFI*$<-RhLH$@<8wdvf(pAiL}>x=|M~pvmUo z8D1*e&@>~=%1;(VRA@sT%&&>I@=wiLz#RGZc?VOy$$>dZ=XA%6^tZ8u3lU>QfXZFg zx-D`JG@7E~x-D6^+wM^1Eo73tV-ohsM24ipC*|&u$b1#O=Cgh_Q8gD_Ov=oV2D3K% zrj}*BnLao%kcOA@w6J|DquRGInPXV<{IYeDpQd!?c`Wl)jq}8glYV)bYxxt%0)C?K z)z+ebD{AqOcJ_VGqF+QV0`CqkNzSycHE&nh$y&BB9QIPk-WLQ^}##C>@g zYw|9(1Wnwa@eYlg%X-@JRNXmIV((!E9Yg9)TiqiZ4>A{v-uQd`fLM2~;Qg>PIcprQK5bdf@9*!kDYbFj`q zkSUU-)01eDTs?et>zq5gImaj(x#`53s{cc-S=+QJOk-wW5++FUgL@-oygjJVV7pDM zm0n7s!9~7zHdudi16{?gC-dC^!eA7|j$ zU{dC1D%&$8b_bK{;P|Bpk?J(7B3+MK9otLSMZcOaw3S=X34jN$BZJvLhoVG7!rGm7jvEdSp}4F_Fj&~IC~tuTDik~CzN%vGP2Hp zYK#^>?CegRBv}TwYY6T4O+IOhcE-fEyDK)7e*95*Z<%HW@f(*iMEusMh2l=JBkX2= zNBGm=xnx-8!$$PkyD0aPKl#|uvN|P-2==v7E;>C1W}Nk#MZ^bpoL5aXY)w72>gS57>Sl@Cf)fEb{lCD~ew%d`nd2a95$fEB}c+lYYwN*8c!s4tXE| diff --git a/interpreter/etc/interpreter.ucls b/interpreter/etc/interpreter.ucls deleted file mode 100644 index 84dc79a3e922..000000000000 --- a/interpreter/etc/interpreter.ucls +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/interpreter/etc/interpreter.urm.puml b/interpreter/etc/interpreter.urm.puml deleted file mode 100644 index e1286a2a932a..000000000000 --- a/interpreter/etc/interpreter.urm.puml +++ /dev/null @@ -1,52 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.interpreter { - class App { - - LOGGER : Logger {static} - + App() - + getOperatorInstance(s : String, left : Expression, right : Expression) : Expression {static} - + isOperator(s : String) : boolean {static} - + main(args : String[]) {static} - } - abstract class Expression { - + Expression() - + interpret() : int {abstract} - + toString() : String {abstract} - } - class MinusExpression { - - leftExpression : Expression - - rightExpression : Expression - + MinusExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } - class MultiplyExpression { - - leftExpression : Expression - - rightExpression : Expression - + MultiplyExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } - class NumberExpression { - - number : int - + NumberExpression(number : int) - + NumberExpression(s : String) - + interpret() : int - + toString() : String - } - class PlusExpression { - - leftExpression : Expression - - rightExpression : Expression - + PlusExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } -} -MultiplyExpression --> "-leftExpression" Expression -MinusExpression --> "-leftExpression" Expression -PlusExpression --> "-leftExpression" Expression -MinusExpression --|> Expression -MultiplyExpression --|> Expression -NumberExpression --|> Expression -PlusExpression --|> Expression -@enduml diff --git a/interpreter/etc/interpreter_1.png b/interpreter/etc/interpreter_1.png deleted file mode 100644 index f10342a1df90d7dc99a680bcb821bbbc289c0a33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46272 zcmZsD1yq&K);`i8NQ1;dxV7ZVj8{3bjpv<42Y zDnMFHM9n36M;Ap6U;0mbVCG7?cOb)80tcF>Y#D(#1ULviiAtJmDEMkR4!?ZgiLyz` zy(65x8LukgGyUURf+oJ+Dp!0HE|*UK{iLtSZEx{JO;b~y=Vt3{d+Vby4HY&jBD~iD z$Cs*EICw8%3T#9a70HJm*q86d*fd$F;eVumcGC-~k)*)({c^Vt8PWIDY_8yv+Uh(E-6^> zZ!HSG@6W5!$#1FFSOu{gll`E44b9C-5x(q>?q$+sDLy?Ovx$P@q9VFdz^=pRTT!4>llReXoXN8(5WjBY*!y3g~0sc-n=Aw|hb3-nYaMdpM;djzoQWV%L zUZaP7)3wqL>rY@X*vav6gM(?3x7hID)>Bgc3?05)Q9pFGLJfaLGpWG&Z}K?I>jNnq zK0Y4CCecMu#nc&Ay`6QHRKeM#ue_Qkl~9@ZgVXJ9y=M2m{>QNl%0?Yu9J(1>_nYiK|sKCZ#+tgP7n_lSG}u4r6c-t zlz_kc^G|YpqTBKrr8tHEG15yj*i4fviB2ujWB=UTG?nD8NL5K*y?9m|?4Z_fUe7vW zcKVZEo0!n;&(V5ZyNtGF9suhZnJlA97pk<2n@sbbYHwTM(-eM98kk(I%2`@986WGJV zL*7z4vF_|Zou>K&r3 zXPf>MCD7nv5%=_UoUitFdn1L0KMP+|S?Hdep8kHiGOBEX)&~k7mOe3`oXGE^!x0}M@;dPoGY%2+m+y|RFSz7*3wrld2`iKgTF{acZ;-1QhbB)W;uNg6t+mU92@p)YY(5qa_dyqTJ{?S)S(lF;Bx z6ZX}&lgY~FvBLObm3E{sT_Yo@#WtjR=d#<|{;67DgI^H`eDaTf^D1qH9LT5J$e@fWn zETsjGkuz&dmsBkjKdVQW;eH}1nvzoQPP_YmIx9}ty+1zGmQUCkYeL4)Jk87eas$FRqqbJ$0J~_!VvDS#o15QFGU{KUjud0W~HV( z8KTm7c*`VQJvWz@JbU7_s*>i<{V2+V#SD^uDXSMY%r(^$^F_|p+Gqo^P(}5zRAoP+i*2@1Z8UZZ2LE&GE{y2zf)k^bn&5>;C({|dl2;0q56q~10pZej- zwk!0yezJ4G9GzIkzlHLvJwmVjFpZJz>+ckKVG_Fv@V301t&@Y1ocs_E3h+Yc9jSf$ z6RlQ3GNAyBO=jFrTmH$|9Qcnr@i$d-&kQHOLPe#@La1r50~UVZH4deg=q9~4+!*>2 z)O~lG)JFn`R;pb~r9BsjS@_+oJk)e+rrv>oA>wW*14(Y#a*Qb)?-z2a69K1$2sQ0| zQ5Y$aukOXsDx>BA8mXC3(rL~@&jz8NNmYZHkC;K+JplMx7aE2#ekf2lNli*#p1(KjjWb6d#o={xBJixp z^2aYN@uQ*KNI>UwM(R9JVtIn{VNp@K+6K&5`AQc^8#WU1qA- zL1bNCj#sAJ{84Kd3x=2;0z%5})G29A5@$Xmu26?)NxJstX6_0XSW5lx0FGb*moIhB zHvFD#&)NqiLJOX^us4VU$7h+Mi2O?HXJRIhF};P_TK2 zxNEYH2%bX&0#F=YFjy58;^)N^>l#UVGC8nTUM>;E0-rSVwF-+ zSWOKfvqxuGLc-|q+?@Yza1e24KDEo9j?VgkJV5HN*XI|m<&Lh)VP8Zm;m`!L4Ds&hl3iE$wA_)ub6MutMQ<^f zCd8_vf}|-?%K$J^SH*AI(4xApxgz0tLUCJ?=i)*{w3 zlS`9WMwu*$u>>Y&ZSJ?_(5XqS3P)+o?<^aL4%r6|*XMf4(7C!uY*PM35CtPR>--4` z{f<|Af8r~9LHFi`!Z$H*Gtbrs{|3>_6{QL`!wZFz>w5227|RBFo`)ItT>njh@+0Lz zuF&3JEr*YpWjA#&n9(?2*4o$@=MJ{48kQK16_f;*{@c5yXiWaW^BSo4V&j@R@&4|s zTv??Z)@5gLvAs0E)``7}BAea(mWkfg7&S@j#AN`+OnKCATHK|tF`k@-e!=i^>&#yc z!W(9IG$r8cq4M;GNu-~MnG(x0aakP!TG z621z4H+|@bDb~zqTW?B|@tiFHRN6lO*#;kh*Z8(7uP_~)8O95Bg`fUoS}$&{YJF-$ zKM>vqkFq7DXK{B$ifZ5(tC;zB;6Y2nsLF*K!{AC~l<>;1!T+ zksMKtAR2E8amnyRXmwh1b7Mdn`QPz9$IEJMqGx7j4;)6a1pz0` zwpEk(h!ZA5BlW-hqcDp*Ppyk-7z@+Ew#@ihI&l#F>FtekM+Kkz!`Ni^NG7r+#i{d8 zSdT^5qP@&`Z`->-%Ew3WVWzI5+)#Fs#dS++G4G4xai#5ln+d*udslWCepvAC$gH&L zmw(pRr%Xp97DhJdu{$Nb+<}y@BW1C*2zb8bjn2tE`}&ua&hx4Lve-vL7~B8nxomV(4mkROVQUMF(qquD{7S@w?C zmwiy2EyfB2nK2bpy2>p7*nl%;XpY&O$10MvPw_ZPocF(IY5ggs7X!zD%ktp6 z7evg!&2YZ{!whe%#~9%=p&U`as0m&G?@3+l3?P0VQ)Gnop@OU;2m!Ere`u!d=+gT7 zY3p6P^_&2vo6YQ$x1@5U?> zGXFC6O4!FG8-??rG2-=tDoZnT8LuBnDeW5b@qMk9Or;l@C59j?TirV9KEWDuV=!8SC7wLf$5pzf|-#UvM(M@#V zCq_Pea_Ew=9RK7KS-8HpNGMk|HuKnFx-vaIifLh|d%FmS4h{}pEWy8QG>i+DkJqn~ zlY{S33Zw&S`AhJu*tgHz*q-Ay=0c!G?yPW;$EW?a*udl^`mO8&!-5`D!tlRG6q-De zd_w~RZ$}!zY0LbNG$w1r$mc9dXpH#f0>|j#?zFiz6I*;6GDo&E&c%PGBLB`Sa8IND zaSWh2Jgh>j`5~PBE2DTZ`OYZa&B%2M;C}UhqfGck+M9ft_Grju1smhDVbWTR$Sn_}Ekl4?Md`u}3KV1gv zAwl?8rXtJDAP?S!@?chv*w-(0hBWyaM8U6qbB@4ZG`%z=B>#2Z6w0g*82CTq{3{C+ z<$~eYf3R5Y8s(#W8%{i4-q$vOZ@*zSo@dj zY2{E4^oA?e^OMc5;fg*W1DDyy1!*AkU)wd*m!zI&xHnTzMrM^JINN)a&cUQP5R`BD zb}9&jkUUoptv}a;LP2k@pA|Y$0pa3ZbPVh-zT=I4+54X{^$r0txsUtJq#;2cAL7x0 zdS_(N@sVF`Q3Wq5DOG-{eR`Pd(aICFL+uJ9n%++f->(3<802w3ai4*XS)4t(zk z@yKLPPhWrk>QZ|(m7Ns5wfR?}+c*89!Xi2u3~OtCGBFJ7z*i%$OI#-_hIy0aG51Dt zHjh@bltWrSRi?huo}7C7j)>&5E)h$SxJ+-{X;0jX!`qw4EXjD_4BkgK*G+m&6RedI zoA`TT!ZDu>U%Zg_@OU-B;ni1(pj};%24tjMMK5LN>AS;aWj8m{O}+(i*1&%2JrIMY z(enN&eK)!<6AtF;C!4Ml-xY&!+1X#he5oqlUA#*Z{6K-0FjsVY>xQAz*ByPebofkV zssZLflPXYOWWPGHlegTNRj2_Y2+Dfx>QdM2?z+$u>!PX}oy5aaS;EK8ZuG-@@yqtO zJYmp$Qhfuoqg`I7`J+3~Y7Sl~J+}AvLu&d6OV@98lKZHtqLJwrO?Nuk>_&L$98>SK zOT$UckjM4-J+p3>Bf2w{^PUw42Zu-~*0Vit3>UXQan4Q@VdB){LZjkDV2QcY^Lfg! z8C`gux0g%->G4C;rS|^2Nwa*O8*9hCo-av+A{i0_@|WXT=|5QY4aYA=&bQ~BuMc*H zW{(cHWrAD~>vltWHGdgsQnGQ(H6R8tAg(m55x&@JQ+`LrnMcjf#OKN;fWXf$8#8Fp zoy3Fn_|*3nAM-WZM&e@vrte3RlHmo~wM#(#qhK$4_iKbpCfAmp9f&eFm$6#r3|=YU z`YPQ36RNIG$Zpt}VKh>agnalUEF41cyaQDSvN}l-nfLqNhsDOXzM9&HFiNXZMN!`_ zN1|SfWg3xx3!B&g1gk)O`D{P!Po-%gkTbK#BCoQS!i6;AUucU0y^x&0CMJLR|ChHm zhzYPhj^!zri1;vBkyh8$*V{Hu#8Yo1YQYxH51WVNiC$Q=4Re{W z`Q6bBwv^v_ASORdC!igsx4~IY{sE+cau7hAF1OVEu^OEBtz58dx$qtP4_?T`JJ~u7 z*s{NQ0rbMnO=5)1zx(^bKb1%<-apT(xCQ}!?MZ-Jz&Dvc3@L3XU8DIo3!>#e(*!1? zpT{d(Y`sq~{d=&;aSy_4 zH79CNlq)an`e2bEbqPplLLSf#Rfx^}+}pBrHW}etg%lEwH0pl@vf*Z`dwmROAV?z4 z-I2x2s!eqt43=hQ8%^IM2u-FF`4V>e2cWop)F24r`nsJsyq>u)=*;qD+VYQr_j+(} zwq=Y$qySExAV8YW4n9mw>P)ozJHoQEs^1tI+|Z?^L-bk%(i?YCEXSFh*ZO3FG zqz(%Lp|9^5Xxo!hzJF+4S(e3nzQKv3F zT6K6h3n2m8rfW7mj=;F_LA$2t@18F1b|T07*@kXPN>2zs_fkQJ;;2e?AOTc|EJWe> zhfhjoTBC{Wa3;=%_Ary0^VX<+0yw}@3N<0YBxVK%I~!&JOxANVMGHGkO$Crw4Pqy+ zA+SSyii3bBFNS8%vdA8XwC&G7!>JoS(v%F=6d$F0P}ugrgbk%|On!M{Wz@MUEB^|E zl}43{Oo^AOhp-(Md0>TavfFhBk$TGfQ0(a!BF*QwxsT;aHSbmhft~_D5z~>&NBSkkG(iQX=_P6P^%snRdL7 zd0{|;pRX`Z98aR`4k7xJ89lP8IyC#~5lM6eHlss4m_!Osp&X<>5M@ISpzYuNwA@7K zmVp=zx=haL*|v-lQ|i!b7!9uLy(Tt+Owd`_lO6VMcZxuxm;~h7NIAH-j4!vWuVAzc z1pkv4AaQ>+Zeo&#iP2ZXwolwIj?x2GMSeEs zx>i9}Ao%btJ_AE+dO9&oO@I$MoQ5IULm>_l!<+^liQ>ADXxybizo$d(+i97- zUAe*{`G`m@Tj$3*g?(=I-E8dZKNeh3{FbFx+Cy$eqHSnQ*OU1wW&AezqgEXpQpJQ6 zTk`c=k3gN~db;}#nRe@*v^8)wP*w#>fdRKiW7E|He#kQV*eO6>GHeFxZ%#n#M zDyHrEO-U=ZL?)+XO`SkW+`ppmtOrFVxpTOkMQGR799YpO*~pFp>C_A+3qc~l2?ASW zUdz^i3$~|1LsHP8m_}XlBRR(34wbbP((XyV0{QvHp7`YBUti6SFbAD1ZUm{28rQd! zm)o_N4xaTSyGKhy)W6<87WMV`SC@Q?w1VC>NUQ(b(*SjL#PVJEE2nJo7rA%yDIU?y z1EVVM-%H=5uxuA~G3k4wh`xzj8BJ@U=3AGZTOp;21WK#yVS#;m%CF?yd(!Be6GoEI z@^ejq@vHl58g{TuP^$4D&V49U_?C@EO7($p?tj@{IP$N$!arnQrHLt6Gw0t0jbU5x z;v5(C6BG6SB*KRUQjq^7{rIK9qyI49ATsq%P-HBtvSLae#4oh^0H?eTWG*la6&O1F zK`QMSRX$|S`58b2v}RU~zNx9HB8gCYK;mMZ)#83Ijr9X!X@%cwCq3zx|P{18}#y*fJY*#qm>2k!KT>9-Y=kPvHL zWNB&V?_6RVDGH&Ejthn4K$C<+UNprgpX#&1$h6w}zj@m+eSLxi@@R+U?-Pck!%n<3ueu5KWimPD&^&WQK&A{5(0XTj11j3I~Wpy;}^%4 zWq;>CMc4n*ZS>^e9&o<-=$*}L$LfHu7(l|^_h~ebocVAh2lk&M0wDb-*Zar4c@q+# z)%w5%w3dKGYro1aBmb%iAa){Guk>1{qErkRQU4d?ZT1U6Pjpgz{Ge7k)1{bI{K6e; zIAuw2*l1xiTMrU+WHt0C!IJipO%^R!B~Qt#H=f7+$_XkUP^XfkLUqXenu8;nQPsQr zk;qid2MJJIn?$kMVYpp7*&2I<9~)DJ8az?<9;T3tuUOvWg^Uf0{J-$f)Y8*!UlJ>2 z5T~LxDvXC`C@IM=wcMYSG&$$6zQm;AD1n?88Lg_!UGL3radT;#x`f#A>&t62P?keR zxw5wrB=~Qmx|=#4Bv`iht9T1`C(ECLgksarJSK74aebf$9QBG_`6MceV5_8cuv|+x zWukw4>tFVBWFFWGz>-|7l24r>A};{7TtJ-4PsoxCXiFc7>1KlzeMvok5-#%}RSu#m zd9eAr+0G7+h~=6~wJ85zA56*m=YzlDGT%Lz&f~SEb_9(f&B?g(}sL#3+AD{TYi)ryCg=`6i$A zZAUqpUU4n$V*5{NWMrg%i@S0Sp|^r?Diq8@5R(EuE<4OW>~#Cj)%iICtSeVB?MrBA zEHwN5Pyeg4UDYjY?-KCYV1@^LGLC|hKta*8_2a2U&J$^Qc`gnP)vbuYz`(_y0ncHm zBAV&K5OMrcrb1+FBv}(_X-9`yX$>(msgKK4CnR0fNKTOxm*4brMNa7%(3T!Xb_w@EY#*zkWZ^#T2 z%T%F(aq48}bP)bTK@HiSU z$dD}R3qaI1jIxmYd{D4J%|^1?5DNkw&6dU^c=9DE=>H;M^wUWeit+Mz$LPA2m zJKWeuG6HUAR?nXoqT$iGU!F*(WR~bP2b-2szV=^fYQRHndz7E`Rv3#Nwxt$}6&@0@ zJ)9L_(P<4zudwZLCQbPv)T&$D*u`H#c(F|CM`vd(uE*aJ#djwwJIBX0CIf#Udf$4D zD#P6GZXq62|S>PX?fDt3jhCNazs^=91$U@BjQrKx)t^{oyq|BCQ;@OGg(+B-iS=4NXInqrWr~LY z7u29eqNAsuo}7H~rc9VR2M6^df{G-8-R-sOsZWXm?(5Z`LY~*4CP{fZUx2gnNKr`C zC8+1%=IZa)uTL2!(?xtn6S^3JE{@l;zJukNWpl!dqzP~3QGulh*{?`(JtpQbkux&N zhSIvYy3*3o6-;7?(q-r7+RQag{{D@3n>ntZ$$k$HKwhu5{4;=Gr(^7XdrcgrpCc3N z_IJ-bTNqws@P5Rec-GR}Tn_*+X`U zql}cVUd@8CrgrquDclY%lYls-dk_{eWN4(9q<~KYb0-1vOL}BbDhFmsrmP-JibtSXEtp>W%c6 zbE2SBzx4^ZK%HCy`=3(%KWYhx-sC=`%I2W%4i5O)bgj)6(dzzw>-(R`T#plYY`|XM zjM{uz6#fb}9*E$2nPNeEvyGNc#$Sk7^}v=?Ta0b(PS=t!#|aM^MnIWD6F5xI_UHAf z#V;-{KFl_#_lw?MZkLYa$XaH8`uxF}JJXYkBanucGlPE1Y?J71u~QTmdJ;`^Ne_XGg8xVShzJ`T_e1h!$T z#U$(r~<*q>m5y}nlGC{yNs ze|LKW4vEEl%MAccPHlGWmZy5u#RxJKd2lL{t1m%VNKdDbk44s$pw|Ce^tQUd@=wWD zd=?M(xvUy;*ZY7c5Q48fleLM-w;wQ! z0*&H={O|8rSXkm&bVsC=8$y2l5|fpcy|*DR@C^Vwixaag9{l`0^T1A_p_ni9@@@#k7 zvPMo@dwP8^&9VRlr-BqHOhz?l6A_ResPo>=<|bnw_DdI|&FR|G=H}*0oJjo7_sgn4 z03$3eFIRfreC&@ix3<1r>nD|u>g$f)|wtblV7AsDn4E7qG7r(o@q*S*j;jwL`>b}X~v0Km7Ev~HK z6BFm}`Ws1DSZo1cTwpJGTP@>rr)55L)Q%|XSN1 z`*dsU_d74!Q#m;~&NuJCF#w#0>rFab??0y=vSJ z4hs4~Fwy92h%b5?Uru7ETtCi6xjj1Ax0Zvem?nwitaVMiz_aH&M5Vx#V;PdBIW!2VBs zx##b|O7Q69$|@>AEmdPcj4t!uC5u5oL`yg2WMdm1>!i_eiImoipjE@|J3SY>4y&r>AN?s@FEnzmQSRmrNQC&Bc(jV!OF^d+Ut6KUY?U< z{PAPMr8pX*>0oMgWhGvl`={&1-WbN;fa3xZu=XbBegYJT_Y(k-myk(Kiu!dp$`dlP z@uGywRc5V4kGFSv`rQ_&ekTEX zY+fcTkNHY;1nRhvZbEr?du6lO=69%hb7lq+{ks1Nz)Mf;bDj@VCtxT4{c21L&~tkG zx0T(v2ee%PmIG=H8c>g=UqOK7ZVZKf`7%_QBqKbTdbrXZy`hS4v;o3jxj}ndTbq%F zg@HlTb4?cG=jsj{k&R{`U-}F9vO|-SU)M4~aH1)S9PG8LyW>G2YoBgo4;biKEMLf;RAbw$T|>tpWD{S$pqz$M#50FCaUtx($fW9>-?hwXqQX zj^fG!M-R|403kOZm?~?68YOtobb)#y2>hU3y&B{)dGL$_0|OJbFqm<5RwRc>pD<-S ztG>yuWR5KgWrhs|RE6ms$v*Ap~%@L%>gni(@0bH=?HFc%%<2vun1j!Vt9~~YZo}Fz5fxry;mI~DRXlb7Np#-%JbH{v<@$m4lV?N8A`~Lkq zU{PnsPpOmuCy0-9HQL2XnirRh2kzqpOEO<9t`0Ia`?cmCO*Y~V>Q zHC-1{udOZ&1m^C6!5c243i>TO8=MQ%k!83beK%ne9$b>5z$AWm!Q#* zlu{NGL%h5pfAvw=O>9Y7n1*T5xv;%~Mft!W~F_!6EzpQIHC@3hDl*fb-Y?BDW%Bo}z8X6h`G6r@abcy@> zaytlQ)$H@nYL{4Bue~K1W~})1`5$0_tRRp2(xaw7pV}xWDY?vIj7b4fpR+X_u34Za zO>=5OaGS7?^}Tn6{ij!DWu;-^>LRN<^O-T`DAJ{Gfb}@WnF&D!%06}hMgpJn9$9ji z{c6vTcyW$&ZvdQt70D)MEdIUu4aEwN$UD3xtmMaWiDu_j@?b!$Zh;czASb z4382P373uPjf)qOn4WNTQicCK+?{LYmwj(qFoA^^2nBo?GDtS{wvC6Io3J5J_EBix z#nfOj-vi-+M`4Bes>Ui}SP4_s4U3gzJ>#~T$WzXGvy>wn&kI{=ne;L%51bb0gjkN| z4X2AB)P&m4%*@p3nj!y+k|t8^1W}Wk4V<|8Pu~F<2e1wpzBs|b#6rqDgq}yHkvZQ( zynStV1Ny#SEHhQt)cC8S62(~x8DYTprCfD}KU1d04Ut&@?mAQe{4~?43ezCGVSy`? zn3+~J$JU6lBUve91aN0ry(*#G^Ve&p@?>vT>>Mj>^R;?_ah3CzG9)SUmM1GsDHYx( z9E3ghzhif|zNWTsaf)=gFt{$Q7R-nireHt@>%2P6eG0;_kEj|D26G%BuV&b-;cy$; z@~QvSKhFs}sFI0i!Q?W)D^~`MoWxgsxG%iU0artZJV!U$3bY!c8F2NuK4frO5)bUi=X0JX4exdU#0fZFM`^u3_)z$*t+Um0!%S}(=kbIzew0EYr>Y<9pFpfQ0PvCg=cuuIX!r7ky@{tw2t zFeQpQA8d|M_zxY*fa<=jw>OTalTQx=YL=h<>%6srl#@iXfhXmQOVxT!E;uQrOLyr`W6IjcHz1Ds z-kAW|YvQjeUpRp0HcqqqAfpM2U-&`uL_frR*pX0BD#cv4CNjkzn-Tn-453+A_w)62 z+?j}6JvlvXS6pFM$wplX=$-?pA|_Nw?b&ATqam_L(VT}mK%4p-plC>pL3?mDU~(WE z1N|s=&d%|gj6Gg4P$*Q?4ESTPOmR_>5?vv_N{TcjqsVsl>!;1NHGh)G^V=IYGVi(h zA3q*>90FK>!!hJJj=?Jj)J2m&C{zB=<5=|t)q+9Mw~0|j0#e_#3{onIPzFL$FE6i% z4{?v&5^!xvG2W_4jwT%+-zY=Kl@9J+d0aXwj6V;0OvJMAtMdynweP6}xa;-Ij7|ec zRn9~Fl^+DMO^J0#nc7-y6<#jrFm)l{?SNpI5O;L}Lj2#n0j5~FZbSxRXP3Cx3a#+{ zx#nIqLs3!qkqkdu#rkdsC04>6O!n?(_qH<=8oD|Tvc>uldkRT$;y z=tji`S7nFUrUYOR!w2xhzY>L3Am;M$;4!2eU*rWuGavPub=n33g_6sWL`V}rKCCJ!CdM%EX=kFGNxi^GMhty~fXvUJe(^b>tIpWj8lr)r z;qK1P0>6o~c%2!+a}AKKTmTijqOpWoo zj8^R|uAlksug~pj`l-STXAgGTPBwq1Bqvw6wcG({cRShe+KxMZ#?ku=FwO^8zE{7{ z0V}MlHJuq+?n~eR2QF&0JWDcsjj9G=Vl8vJ3n5s1(JD!toG9pZrG1d-cfdmJ-?a!? zXjPd-R#(H`y!ooaMq7b}Ev~Jt{jk{_5zqo};46gBHNLc0E&G$-TwjB@Tq$q{qArl9 zO$U~Mu{i3Z*u4yt>!hfTcnfN3Yv;=i11{GyaaQ`=?|@3FQK*4g4J3HlD~m;}hhc$& zR1nDLu%=d^wh6e^%#b1AKCWj`Gs1=j2AL->vpJQRwQ~~0$t830NHCT5G1MOU&h+#! zMJHEY+(P)B`dTP?Y7V$q;I*l=Q9p<1{nH=e*_7?Wd2UZ`}@NeeF9 z<1avtytx_9J`B`BV5Vh;I;9As;$NdJPP>Vrp+J|hp$L_u07?73(6*Db{|Tf%Kt%W< z{!@ZmJp=v((AE>w2sf%o)ZqTb0CTfp=6lW1v=ZEM7%Rvb$P_U%mx@bT@6&TK++bIvZjEAtgYEX+LkSG_1Zt3Icm?(&!4gmp#yE;H1?yWuxt^0d6A==MyV#9 zc*i%qdjy4jcYZ5N6C)Az5)-k{HItK*nKVnlzhAh4;4+~G&$m-9U2_Ly$IAxya-96E zh_8ts-)w()X+*MF4voq;?bNLRN^da1^B#O;x(Gm9M;bw7#_#j!%MQEOKe;UMgGHMs zZb4BH)3Z3_gH=Etj`Pc;qUKla^@>eR?zmu z*dc1vfbu zo}HAs9&<5ReX>!+sY>xRI;Ung+GUfV{Q3$BJ0b4 zgR+1&C{QS|qN$LLX8}@KtK()=YpW1bb#--n3DCSuEjj=iP%f$$sIl?z{5?K)J6!UU z67ZfV)MU;6PMr*DSB^cvwfvtz-j=-+;jIAs1Y|AhFmY9oIZfL4F zxL0B$M@QXlGq12e!FK$2-VmSOLI(oMC##@6eXI~+;`aQ|4BS$E{kk!bGb8NNbva3B zC!1a9;`Ffsc zpng`Amrnv%2ODfLUZhoFBpvw%qTGJ4_!HzmRwgDL1)!LYiAyO2g6U5QBcm1XXYV*b zv)kp$))om7Q7x!^nQ_nXYbd;V^E3$$&8u$|L#il0e{-tZaG_C&k4D zdDJ#p{SPiIcH$0j^I>fOvbD9fvAzylAK*p`%1j$$<8~6Qw^sn@k*86Np*j?S-3qG7 zZvba71r_O@J~}NJXgSqyni$Lx@Mz#+vn$y!g~hNeZvTk}w=KRV5iu!ec6}j6F#480 zY1Ra~-IGz748*(TXo966NTOa?FUuNN0E7cv2$-

    RbT=gS}}OA(Q<7Dr*4A?i25 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 Zw{U@_m?wJ9WE=cBuc&@5NB+|7{{jyvKF|OF diff --git a/interpreter/pom.xml b/interpreter/pom.xml deleted file mode 100644 index 8c0ab09a07c5..000000000000 --- a/interpreter/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - interpreter - - - junit - junit - test - - - diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/App.java b/interpreter/src/main/java/com/iluwatar/interpreter/App.java deleted file mode 100644 index 7404f9757bf3..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/App.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Stack; - -/** - * - * The Interpreter pattern is a design pattern that specifies how to evaluate sentences in a - * language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a - * specialized computer language. The syntax tree of a sentence in the language is an instance of - * the composite pattern and is used to evaluate (interpret) the sentence for a client. - *

    - * In this example we use the Interpreter pattern to break sentences into expressions ( - * {@link Expression}) that can be evaluated and as a whole form the result. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * - * Program entry point. - *

    - * Expressions can be evaluated using prefix, infix or postfix notations This sample uses postfix, - * where operator comes after the operands - * - * @param args command line args - * - */ - public static void main(String[] args) { - String tokenString = "4 3 2 - 1 + *"; - Stack stack = new Stack<>(); - - String[] tokenList = tokenString.split(" "); - for (String s : tokenList) { - if (isOperator(s)) { - Expression rightExpression = stack.pop(); - Expression leftExpression = stack.pop(); - LOGGER.info("popped from stack left: {} right: {}", - leftExpression.interpret(), rightExpression.interpret()); - Expression operator = getOperatorInstance(s, leftExpression, rightExpression); - LOGGER.info("operator: {}", operator); - int result = operator.interpret(); - NumberExpression resultExpression = new NumberExpression(result); - stack.push(resultExpression); - LOGGER.info("push result to stack: {}", resultExpression.interpret()); - } else { - Expression i = new NumberExpression(s); - stack.push(i); - LOGGER.info("push to stack: {}", i.interpret()); - } - } - LOGGER.info("result: {}", stack.pop().interpret()); - } - - public static boolean isOperator(String s) { - return s.equals("+") || s.equals("-") || s.equals("*"); - } - - /** - * Get expression for string - */ - public static Expression getOperatorInstance(String s, Expression left, Expression right) { - switch (s) { - case "+": - return new PlusExpression(left, right); - case "-": - return new MinusExpression(left, right); - case "*": - return new MultiplyExpression(left, right); - default: - return new MultiplyExpression(left, right); - } - } -} diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/Expression.java b/interpreter/src/main/java/com/iluwatar/interpreter/Expression.java deleted file mode 100644 index bea4d40517b4..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/Expression.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -/** - * - * Expression - * - */ -public abstract class Expression { - - public abstract int interpret(); - - @Override - public abstract String toString(); -} diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java b/interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java deleted file mode 100644 index b3f2299c34ad..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -/** - * - * MinusExpression - * - */ -public class MinusExpression extends Expression { - - private Expression leftExpression; - private Expression rightExpression; - - public MinusExpression(Expression leftExpression, Expression rightExpression) { - this.leftExpression = leftExpression; - this.rightExpression = rightExpression; - } - - @Override - public int interpret() { - return leftExpression.interpret() - rightExpression.interpret(); - } - - @Override - public String toString() { - return "-"; - } - -} diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java b/interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java deleted file mode 100644 index 809b5331cf53..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -/** - * - * MultiplyExpression - * - */ -public class MultiplyExpression extends Expression { - - private Expression leftExpression; - private Expression rightExpression; - - public MultiplyExpression(Expression leftExpression, Expression rightExpression) { - this.leftExpression = leftExpression; - this.rightExpression = rightExpression; - } - - @Override - public int interpret() { - return leftExpression.interpret() * rightExpression.interpret(); - } - - @Override - public String toString() { - return "*"; - } - -} diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java b/interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java deleted file mode 100644 index 2309d3190be9..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -/** - * - * NumberExpression - * - */ -public class NumberExpression extends Expression { - - private int number; - - public NumberExpression(int number) { - this.number = number; - } - - public NumberExpression(String s) { - this.number = Integer.parseInt(s); - } - - @Override - public int interpret() { - return number; - } - - @Override - public String toString() { - return "number"; - } -} diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java b/interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java deleted file mode 100644 index 56c68b9db0bf..000000000000 --- a/interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -/** - * - * PlusExpression - * - */ -public class PlusExpression extends Expression { - - private Expression leftExpression; - private Expression rightExpression; - - public PlusExpression(Expression leftExpression, Expression rightExpression) { - this.leftExpression = leftExpression; - this.rightExpression = rightExpression; - } - - @Override - public int interpret() { - return leftExpression.interpret() + rightExpression.interpret(); - } - - @Override - public String toString() { - return "+"; - } -} diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/AppTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/AppTest.java deleted file mode 100644 index b2d6db1575c1..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java deleted file mode 100644 index 2241b882b05e..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.IntBinaryOperator; - -import org.junit.Test; - -/** - * Date: 12/14/15 - 11:48 AM - * - * Test Case for Expressions - * @param Type of Expression - * @author Jeroen Meulemeester - */ -public abstract class ExpressionTest { - - /** - * Generate inputs ranging from -10 to 10 for both input params and calculate the expected result - * - * @param resultCalc The function used to calculate the expected result - * @return A data set with test entries - */ - static List prepareParameters(final IntBinaryOperator resultCalc) { - final List testData = new ArrayList<>(); - for (int i = -10; i < 10; i++) { - for (int j = -10; j < 10; j++) { - testData.add(new Object[]{ - new NumberExpression(i), - new NumberExpression(j), - resultCalc.applyAsInt(i, j) - }); - } - } - return testData; - } - - /** - * The input used as first parameter during the test - */ - private final NumberExpression first; - - /** - * The input used as second parameter during the test - */ - private final NumberExpression second; - - /** - * The expected result of the calculation, taking the first and second parameter in account - */ - private final int result; - - /** - * The expected {@link E#toString()} response - */ - private final String expectedToString; - - /** - * Factory, used to create a new test object instance with the correct first and second parameter - */ - private final BiFunction factory; - - /** - * Create a new test instance with the given parameters and expected results - * - * @param first The input used as first parameter during the test - * @param second The input used as second parameter during the test - * @param result The expected result of the tested expression - * @param expectedToString The expected {@link E#toString()} response - * @param factory Factory, used to create a new test object instance - */ - ExpressionTest(final NumberExpression first, final NumberExpression second, final int result, - final String expectedToString, final BiFunction factory) { - - this.first = first; - this.second = second; - this.result = result; - this.expectedToString = expectedToString; - this.factory = factory; - } - - /** - * Get the first parameter - * - * @return The first parameter - */ - final NumberExpression getFirst() { - return this.first; - } - - /** - * Verify if the expression calculates the correct result when calling {@link E#interpret()} - */ - @Test - public void testInterpret() { - final E expression = this.factory.apply(this.first, this.second); - assertNotNull(expression); - assertEquals(this.result, expression.interpret()); - } - - /** - * Verify if the expression has the expected {@link E#toString()} value - */ - @Test - public void testToString() { - final E expression = this.factory.apply(this.first, this.second); - assertNotNull(expression); - assertEquals(expectedToString, expression.toString()); - } -} diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java deleted file mode 100644 index 65e7e4515e37..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.List; - -/** - * Date: 12/14/15 - 12:08 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class MinusExpressionTest extends ExpressionTest { - - /** - * Create a new set of test entries with the expected result - * - * @return The list of parameters used during this test - */ - @Parameters - public static List data() { - return prepareParameters((f, s) -> f - s); - } - - /** - * Create a new test instance using the given test parameters and expected result - * - * @param first The first expression parameter - * @param second The second expression parameter - * @param result The expected result - */ - public MinusExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { - super(first, second, result, "-", MinusExpression::new); - } - -} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java deleted file mode 100644 index 12ea3586340c..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.List; - -/** - * Date: 12/14/15 - 12:08 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class MultiplyExpressionTest extends ExpressionTest { - - /** - * Create a new set of test entries with the expected result - * - * @return The list of parameters used during this test - */ - @Parameters - public static List data() { - return prepareParameters((f, s) -> f * s); - } - - /** - * Create a new test instance using the given test parameters and expected result - * - * @param first The first expression parameter - * @param second The second expression parameter - * @param result The expected result - */ - public MultiplyExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { - super(first, second, result, "*", MultiplyExpression::new); - } - -} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java deleted file mode 100644 index 9f18355ef575..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/14/15 - 12:08 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class NumberExpressionTest extends ExpressionTest { - - /** - * Create a new set of test entries with the expected result - * - * @return The list of parameters used during this test - */ - @Parameters - public static List data() { - return prepareParameters((f, s) -> f); - } - - /** - * Create a new test instance using the given test parameters and expected result - * - * @param first The first expression parameter - * @param second The second expression parameter - * @param result The expected result - */ - public NumberExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { - super(first, second, result, "number", (f, s) -> f); - } - - /** - * Verify if the {@link NumberExpression#NumberExpression(String)} constructor works as expected - */ - @Test - public void testFromString() throws Exception { - final int expectedValue = getFirst().interpret(); - final String testStingValue = String.valueOf(expectedValue); - final NumberExpression numberExpression = new NumberExpression(testStingValue); - assertEquals(expectedValue, numberExpression.interpret()); - } - -} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java deleted file mode 100644 index d11ba8a8d4ed..000000000000 --- a/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.interpreter; - -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.List; - -/** - * Date: 12/14/15 - 12:08 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class PlusExpressionTest extends ExpressionTest { - - /** - * Create a new set of test entries with the expected result - * - * @return The list of parameters used during this test - */ - @Parameters - public static List data() { - return prepareParameters((f, s) -> f + s); - } - - /** - * Create a new test instance using the given test parameters and expected result - * - * @param first The first expression parameter - * @param second The second expression parameter - * @param result The expected result - */ - public PlusExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { - super(first, second, result, "+", PlusExpression::new); - } - -} \ No newline at end of file diff --git a/layers/README.md b/layers/README.md deleted file mode 100644 index 62b562938d9a..000000000000 --- a/layers/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Layers -folder: layers -permalink: /patterns/layers/ -pumlid: BSR13OCm30NGLSe0n7UsCS62L8w9x6yGszD3t-bDpQhc9kdwEO0H2v7pNVQ68zSCyNeQn53gsQbftWns-lB5yoRHTfi70-8Mr3b-8UL7F4XG_otflOpi-W80 -pumlformat: svg -categories: Architectural -tags: - - Java - - Difficulty-Intermediate - - Spring ---- - -## Intent -Layers is an architectural style where software responsibilities are - divided among the different layers of the application. - -![alt text](./etc/layers.png "Layers") - -## Applicability -Use the Layers architecture when - -* you want clearly divide software responsibilities into different parts of the program -* you want to prevent a change from propagating throughout the application -* you want to make your application more maintainable and testable - -## Credits - -* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697) diff --git a/layers/etc/layers.png b/layers/etc/layers.png deleted file mode 100644 index a4bd8b19ddad1cac0134b6fd8aec15d9697039d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97428 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

    - * This example demonstrates a traditional 3-layer architecture consisting of data access layer, business layer and - * presentation layer. - *

    - * The data access layer is formed of Spring Data repositories CakeDao, CakeToppingDao and - * CakeLayerDao. The repositories can be used for CRUD operations on cakes, cake toppings and cake layers - * respectively. - *

    - * The business layer is built on top of the data access layer. CakeBakingService offers methods to - * retrieve available cake toppings and cake layers and baked cakes. Also the service is used to create new cakes out of - * cake toppings and cake layers. - *

    - * The presentation layer is built on the business layer and in this example it simply lists the cakes that have been - * baked. - *

    - * We have applied so called strict layering which means that the layers can only access the classes directly beneath - * them. This leads the solution to create an additional set of DTOs ( CakeInfo, - * CakeToppingInfo, CakeLayerInfo) to translate data between layers. In other words, - * CakeBakingService cannot return entities ( Cake, CakeTopping, - * CakeLayer) directly since these reside on data access layer but instead translates these into business - * layer DTOs (CakeInfo, CakeToppingInfo, CakeLayerInfo) and returns them - * instead. This way the presentation layer does not have any knowledge of other layers than the business layer and thus - * is not affected by changes to them. - * - * @see Cake - * @see CakeTopping - * @see CakeLayer - * @see CakeDao - * @see CakeToppingDao - * @see CakeLayerDao - * @see CakeBakingService - * @see CakeInfo - * @see CakeToppingInfo - * @see CakeLayerInfo - * - */ -public class App { - - private static CakeBakingService cakeBakingService = new CakeBakingServiceImpl(); - - /** - * Application entry point - * - * @param args Command line parameters - */ - public static void main(String[] args) { - - // initialize example data - initializeData(cakeBakingService); - - // create view and render it - CakeViewImpl cakeView = new CakeViewImpl(cakeBakingService); - cakeView.render(); - } - - /** - * Initializes the example data - */ - private static void initializeData(CakeBakingService cakeBakingService) { - cakeBakingService.saveNewLayer(new CakeLayerInfo("chocolate", 1200)); - cakeBakingService.saveNewLayer(new CakeLayerInfo("banana", 900)); - cakeBakingService.saveNewLayer(new CakeLayerInfo("strawberry", 950)); - cakeBakingService.saveNewLayer(new CakeLayerInfo("lemon", 950)); - cakeBakingService.saveNewLayer(new CakeLayerInfo("vanilla", 950)); - cakeBakingService.saveNewLayer(new CakeLayerInfo("strawberry", 950)); - - cakeBakingService.saveNewTopping(new CakeToppingInfo("candies", 350)); - cakeBakingService.saveNewTopping(new CakeToppingInfo("cherry", 350)); - - CakeInfo cake1 = - new CakeInfo(new CakeToppingInfo("candies", 0), Arrays.asList(new CakeLayerInfo( - "chocolate", 0), new CakeLayerInfo("banana", 0), new CakeLayerInfo("strawberry", 0))); - try { - cakeBakingService.bakeNewCake(cake1); - } catch (CakeBakingException e) { - e.printStackTrace(); - } - CakeInfo cake2 = - new CakeInfo(new CakeToppingInfo("cherry", 0), Arrays.asList( - new CakeLayerInfo("vanilla", 0), new CakeLayerInfo("lemon", 0), new CakeLayerInfo( - "strawberry", 0))); - try { - cakeBakingService.bakeNewCake(cake2); - } catch (CakeBakingException e) { - e.printStackTrace(); - } - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/Cake.java b/layers/src/main/java/com/iluwatar/layers/Cake.java deleted file mode 100644 index 10490709e259..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/Cake.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.HashSet; -import java.util.Set; - -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; - -/** - * - * Cake entity - * - */ -@Entity -public class Cake { - - @Id - @GeneratedValue - private Long id; - - @OneToOne(cascade = CascadeType.REMOVE) - private CakeTopping topping; - - @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER) - private Set layers; - - public Cake() { - setLayers(new HashSet<>()); - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public CakeTopping getTopping() { - return topping; - } - - public void setTopping(CakeTopping topping) { - this.topping = topping; - } - - public Set getLayers() { - return layers; - } - - public final void setLayers(Set layers) { - this.layers = layers; - } - - public void addLayer(CakeLayer layer) { - this.layers.add(layer); - } - - @Override - public String toString() { - return String.format("id=%s topping=%s layers=%s", id, topping, layers.toString()); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeBakingException.java b/layers/src/main/java/com/iluwatar/layers/CakeBakingException.java deleted file mode 100644 index fa338a40add3..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeBakingException.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -/** - * - * Custom exception used in cake baking - * - */ -public class CakeBakingException extends Exception { - - private static final long serialVersionUID = 1L; - - public CakeBakingException() {} - - public CakeBakingException(String message) { - super(message); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java b/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java deleted file mode 100644 index 080d4f6a42d4..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.List; - -/** - * - * Service for cake baking operations - * - */ -public interface CakeBakingService { - - /** - * Bakes new cake according to parameters - */ - void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException; - - /** - * Get all cakes - */ - List getAllCakes(); - - /** - * Store new cake topping - */ - void saveNewTopping(CakeToppingInfo toppingInfo); - - /** - * Get available cake toppings - */ - List getAvailableToppings(); - - /** - * Add new cake layer - */ - void saveNewLayer(CakeLayerInfo layerInfo); - - /** - * Get available cake layers - */ - List getAvailableLayers(); -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java b/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java deleted file mode 100644 index e8deee73a767..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * - * Implementation of CakeBakingService - * - */ -@Service -@Transactional -public class CakeBakingServiceImpl implements CakeBakingService { - - private AbstractApplicationContext context; - - public CakeBakingServiceImpl() { - this.context = new ClassPathXmlApplicationContext("applicationContext.xml"); - } - - @Override - public void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException { - List allToppings = getAvailableToppingEntities(); - List matchingToppings = - allToppings.stream().filter(t -> t.getName().equals(cakeInfo.cakeToppingInfo.name)) - .collect(Collectors.toList()); - if (matchingToppings.isEmpty()) { - throw new CakeBakingException(String.format("Topping %s is not available", - cakeInfo.cakeToppingInfo.name)); - } - List allLayers = getAvailableLayerEntities(); - Set foundLayers = new HashSet<>(); - for (CakeLayerInfo info : cakeInfo.cakeLayerInfos) { - Optional found = - allLayers.stream().filter(layer -> layer.getName().equals(info.name)).findFirst(); - if (!found.isPresent()) { - throw new CakeBakingException(String.format("Layer %s is not available", info.name)); - } else { - foundLayers.add(found.get()); - } - } - CakeToppingDao toppingBean = context.getBean(CakeToppingDao.class); - CakeTopping topping = toppingBean.findOne(matchingToppings.iterator().next().getId()); - CakeDao cakeBean = context.getBean(CakeDao.class); - Cake cake = new Cake(); - cake.setTopping(topping); - cake.setLayers(foundLayers); - cakeBean.save(cake); - topping.setCake(cake); - toppingBean.save(topping); - CakeLayerDao layerBean = context.getBean(CakeLayerDao.class); - for (CakeLayer layer : foundLayers) { - layer.setCake(cake); - layerBean.save(layer); - } - } - - @Override - public void saveNewTopping(CakeToppingInfo toppingInfo) { - CakeToppingDao bean = context.getBean(CakeToppingDao.class); - bean.save(new CakeTopping(toppingInfo.name, toppingInfo.calories)); - } - - @Override - public void saveNewLayer(CakeLayerInfo layerInfo) { - CakeLayerDao bean = context.getBean(CakeLayerDao.class); - bean.save(new CakeLayer(layerInfo.name, layerInfo.calories)); - } - - private List getAvailableToppingEntities() { - CakeToppingDao bean = context.getBean(CakeToppingDao.class); - List result = new ArrayList<>(); - Iterator iterator = bean.findAll().iterator(); - while (iterator.hasNext()) { - CakeTopping topping = iterator.next(); - if (topping.getCake() == null) { - result.add(topping); - } - } - return result; - } - - @Override - public List getAvailableToppings() { - CakeToppingDao bean = context.getBean(CakeToppingDao.class); - List result = new ArrayList<>(); - Iterator iterator = bean.findAll().iterator(); - while (iterator.hasNext()) { - CakeTopping next = iterator.next(); - if (next.getCake() == null) { - result.add(new CakeToppingInfo(next.getId(), next.getName(), next.getCalories())); - } - } - return result; - } - - private List getAvailableLayerEntities() { - CakeLayerDao bean = context.getBean(CakeLayerDao.class); - List result = new ArrayList<>(); - Iterator iterator = bean.findAll().iterator(); - while (iterator.hasNext()) { - CakeLayer next = iterator.next(); - if (next.getCake() == null) { - result.add(next); - } - } - return result; - } - - @Override - public List getAvailableLayers() { - CakeLayerDao bean = context.getBean(CakeLayerDao.class); - List result = new ArrayList<>(); - Iterator iterator = bean.findAll().iterator(); - while (iterator.hasNext()) { - CakeLayer next = iterator.next(); - if (next.getCake() == null) { - result.add(new CakeLayerInfo(next.getId(), next.getName(), next.getCalories())); - } - } - return result; - } - - @Override - public List getAllCakes() { - CakeDao cakeBean = context.getBean(CakeDao.class); - List result = new ArrayList<>(); - Iterator iterator = cakeBean.findAll().iterator(); - while (iterator.hasNext()) { - Cake cake = iterator.next(); - CakeToppingInfo cakeToppingInfo = - new CakeToppingInfo(cake.getTopping().getId(), cake.getTopping().getName(), cake - .getTopping().getCalories()); - List cakeLayerInfos = new ArrayList<>(); - for (CakeLayer layer : cake.getLayers()) { - cakeLayerInfos.add(new CakeLayerInfo(layer.getId(), layer.getName(), layer.getCalories())); - } - CakeInfo cakeInfo = new CakeInfo(cake.getId(), cakeToppingInfo, cakeLayerInfos); - result.add(cakeInfo); - } - return result; - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeDao.java b/layers/src/main/java/com/iluwatar/layers/CakeDao.java deleted file mode 100644 index d1788b1e0832..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; - -/** - * - * CRUD repository for cakes - * - */ -@Repository -public interface CakeDao extends CrudRepository { - -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeInfo.java deleted file mode 100644 index a1a2cb12eb9f..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.List; -import java.util.Optional; - -/** - * - * DTO for cakes - * - */ -public class CakeInfo { - - public final Optional id; - public final CakeToppingInfo cakeToppingInfo; - public final List cakeLayerInfos; - - /** - * Constructor - */ - public CakeInfo(Long id, CakeToppingInfo cakeToppingInfo, List cakeLayerInfos) { - this.id = Optional.of(id); - this.cakeToppingInfo = cakeToppingInfo; - this.cakeLayerInfos = cakeLayerInfos; - } - - /** - * Constructor - */ - public CakeInfo(CakeToppingInfo cakeToppingInfo, List cakeLayerInfos) { - this.id = Optional.empty(); - this.cakeToppingInfo = cakeToppingInfo; - this.cakeLayerInfos = cakeLayerInfos; - } - - /** - * Calculate calories - */ - public int calculateTotalCalories() { - int total = cakeToppingInfo != null ? cakeToppingInfo.calories : 0; - total += cakeLayerInfos.stream().mapToInt(c -> c.calories).sum(); - return total; - } - - @Override - public String toString() { - return String.format("CakeInfo id=%d topping=%s layers=%s totalCalories=%d", id.orElse(-1L), - cakeToppingInfo, cakeLayerInfos, calculateTotalCalories()); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeLayer.java b/layers/src/main/java/com/iluwatar/layers/CakeLayer.java deleted file mode 100644 index a6dc920f93e3..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeLayer.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; - -/** - * - * CakeLayer entity - * - */ -@Entity -public class CakeLayer { - - @Id - @GeneratedValue - private Long id; - - private String name; - - private int calories; - - @ManyToOne(cascade = CascadeType.ALL) - private Cake cake; - - public CakeLayer() {} - - public CakeLayer(String name, int calories) { - this.setName(name); - this.setCalories(calories); - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public final void setName(String name) { - this.name = name; - } - - public int getCalories() { - return calories; - } - - public final void setCalories(int calories) { - this.calories = calories; - } - - @Override - public String toString() { - return String.format("id=%s name=%s calories=%d", id, name, calories); - } - - public Cake getCake() { - return cake; - } - - public void setCake(Cake cake) { - this.cake = cake; - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeLayerDao.java b/layers/src/main/java/com/iluwatar/layers/CakeLayerDao.java deleted file mode 100644 index d1edebe7aa88..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeLayerDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; - -/** - * - * CRUD repository for cake layers - * - */ -@Repository -public interface CakeLayerDao extends CrudRepository { - -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java deleted file mode 100644 index f776c320e0a5..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.Optional; - -/** - * - * DTO for cake layers - * - */ -public class CakeLayerInfo { - - public final Optional id; - public final String name; - public final int calories; - - /** - * Constructor - */ - public CakeLayerInfo(Long id, String name, int calories) { - this.id = Optional.of(id); - this.name = name; - this.calories = calories; - } - - /** - * Constructor - */ - public CakeLayerInfo(String name, int calories) { - this.id = Optional.empty(); - this.name = name; - this.calories = calories; - } - - @Override - public String toString() { - return String.format("CakeLayerInfo id=%d name=%s calories=%d", id.orElse(-1L), name, calories); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeTopping.java b/layers/src/main/java/com/iluwatar/layers/CakeTopping.java deleted file mode 100644 index 47b2a44bae2d..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeTopping.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToOne; - -/** - * - * CakeTopping entity - * - */ -@Entity -public class CakeTopping { - - @Id - @GeneratedValue - private Long id; - - private String name; - - private int calories; - - @OneToOne(cascade = CascadeType.ALL) - private Cake cake; - - public CakeTopping() {} - - public CakeTopping(String name, int calories) { - this.setName(name); - this.setCalories(calories); - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public final void setName(String name) { - this.name = name; - } - - public final int getCalories() { - return calories; - } - - public void setCalories(int calories) { - this.calories = calories; - } - - @Override - public String toString() { - return String.format("id=%s name=%s calories=%d", id, name, calories); - } - - public Cake getCake() { - return cake; - } - - public void setCake(Cake cake) { - this.cake = cake; - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeToppingDao.java b/layers/src/main/java/com/iluwatar/layers/CakeToppingDao.java deleted file mode 100644 index fdbc0f3b4905..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeToppingDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; - -/** - * - * CRUD repository cake toppings - * - */ -@Repository -public interface CakeToppingDao extends CrudRepository { - -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java deleted file mode 100644 index 031243f4a9f2..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.Optional; - -/** - * - * DTO for cake toppings - * - */ -public class CakeToppingInfo { - - public final Optional id; - public final String name; - public final int calories; - - /** - * Constructor - */ - public CakeToppingInfo(Long id, String name, int calories) { - this.id = Optional.of(id); - this.name = name; - this.calories = calories; - } - - /** - * Constructor - */ - public CakeToppingInfo(String name, int calories) { - this.id = Optional.empty(); - this.name = name; - this.calories = calories; - } - - @Override - public String toString() { - return String.format("CakeToppingInfo id=%d name=%s calories=%d", id.orElse(-1L), name, calories); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java b/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java deleted file mode 100644 index 57bb0a561b0f..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * View implementation for displaying cakes - * - */ -public class CakeViewImpl implements View { - - private static final Logger LOGGER = LoggerFactory.getLogger(CakeViewImpl.class); - - private CakeBakingService cakeBakingService; - - public CakeViewImpl(CakeBakingService cakeBakingService) { - this.cakeBakingService = cakeBakingService; - } - - public void render() { - cakeBakingService.getAllCakes().stream().forEach(cake -> LOGGER.info(cake.toString())); - } -} diff --git a/layers/src/main/java/com/iluwatar/layers/View.java b/layers/src/main/java/com/iluwatar/layers/View.java deleted file mode 100644 index 7cf56530807d..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/View.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -/** - * - * View interface - * - */ -public interface View { - - void render(); - -} diff --git a/layers/src/main/resources/META-INF/persistence.xml b/layers/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index da9820d8a7db..000000000000 --- a/layers/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/layers/src/main/resources/applicationContext.xml b/layers/src/main/resources/applicationContext.xml deleted file mode 100644 index eca3670b0fbf..000000000000 --- a/layers/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/layers/src/main/resources/logback.xml b/layers/src/main/resources/logback.xml deleted file mode 100644 index 1da6e5828175..000000000000 --- a/layers/src/main/resources/logback.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - layers.log - - layers-%d.log - 5 - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - - - - - - - - - - - - - diff --git a/layers/src/test/java/com/iluwatar/layers/AppTest.java b/layers/src/test/java/com/iluwatar/layers/AppTest.java deleted file mode 100644 index 841d0ecb5305..000000000000 --- a/layers/src/test/java/com/iluwatar/layers/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java b/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java deleted file mode 100644 index abefc9f2cbdb..000000000000 --- a/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * Date: 12/15/15 - 7:57 PM - * - * @author Jeroen Meulemeester - */ -public class CakeBakingExceptionTest { - - @Test - public void testConstructor() throws Exception { - final CakeBakingException exception = new CakeBakingException(); - assertNull(exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void testConstructorWithMessage() throws Exception { - final String expectedMessage = "message"; - final CakeBakingException exception = new CakeBakingException(expectedMessage); - assertEquals(expectedMessage, exception.getMessage()); - assertNull(exception.getCause()); - } - -} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java b/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java deleted file mode 100644 index 1c6eb15173d1..000000000000 --- a/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/15/15 - 9:55 PM - * - * @author Jeroen Meulemeester - */ -public class CakeBakingServiceImplTest { - - @Test - public void testLayers() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final List initialLayers = service.getAvailableLayers(); - assertNotNull(initialLayers); - assertTrue(initialLayers.isEmpty()); - - service.saveNewLayer(new CakeLayerInfo("Layer1", 1000)); - service.saveNewLayer(new CakeLayerInfo("Layer2", 2000)); - - final List availableLayers = service.getAvailableLayers(); - assertNotNull(availableLayers); - assertEquals(2, availableLayers.size()); - for (final CakeLayerInfo layer : availableLayers) { - assertNotNull(layer.id); - assertNotNull(layer.name); - assertNotNull(layer.toString()); - assertTrue(layer.calories > 0); - } - - } - - @Test - public void testToppings() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final List initialToppings = service.getAvailableToppings(); - assertNotNull(initialToppings); - assertTrue(initialToppings.isEmpty()); - - service.saveNewTopping(new CakeToppingInfo("Topping1", 1000)); - service.saveNewTopping(new CakeToppingInfo("Topping2", 2000)); - - final List availableToppings = service.getAvailableToppings(); - assertNotNull(availableToppings); - assertEquals(2, availableToppings.size()); - for (final CakeToppingInfo topping : availableToppings) { - assertNotNull(topping.id); - assertNotNull(topping.name); - assertNotNull(topping.toString()); - assertTrue(topping.calories > 0); - } - - } - - @Test - public void testBakeCakes() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final List initialCakes = service.getAllCakes(); - assertNotNull(initialCakes); - assertTrue(initialCakes.isEmpty()); - - final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); - final CakeToppingInfo topping2 = new CakeToppingInfo("Topping2", 2000); - service.saveNewTopping(topping1); - service.saveNewTopping(topping2); - - final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); - final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); - final CakeLayerInfo layer3 = new CakeLayerInfo("Layer3", 2000); - service.saveNewLayer(layer1); - service.saveNewLayer(layer2); - service.saveNewLayer(layer3); - - service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, layer2))); - service.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer3))); - - final List allCakes = service.getAllCakes(); - assertNotNull(allCakes); - assertEquals(2, allCakes.size()); - for (final CakeInfo cakeInfo : allCakes) { - assertNotNull(cakeInfo.id); - assertNotNull(cakeInfo.cakeToppingInfo); - assertNotNull(cakeInfo.cakeLayerInfos); - assertNotNull(cakeInfo.toString()); - assertFalse(cakeInfo.cakeLayerInfos.isEmpty()); - assertTrue(cakeInfo.calculateTotalCalories() > 0); - } - - } - - @Test(expected = CakeBakingException.class) - public void testBakeCakeMissingTopping() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); - final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); - service.saveNewLayer(layer1); - service.saveNewLayer(layer2); - - final CakeToppingInfo missingTopping = new CakeToppingInfo("Topping1", 1000); - service.bakeNewCake(new CakeInfo(missingTopping, Arrays.asList(layer1, layer2))); - } - - @Test(expected = CakeBakingException.class) - public void testBakeCakeMissingLayer() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final List initialCakes = service.getAllCakes(); - assertNotNull(initialCakes); - assertTrue(initialCakes.isEmpty()); - - final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); - service.saveNewTopping(topping1); - - final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); - service.saveNewLayer(layer1); - - final CakeLayerInfo missingLayer = new CakeLayerInfo("Layer2", 2000); - service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, missingLayer))); - - } - - @Test(expected = CakeBakingException.class) - public void testBakeCakesUsedLayer() throws CakeBakingException { - final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); - - final List initialCakes = service.getAllCakes(); - assertNotNull(initialCakes); - assertTrue(initialCakes.isEmpty()); - - final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); - final CakeToppingInfo topping2 = new CakeToppingInfo("Topping2", 2000); - service.saveNewTopping(topping1); - service.saveNewTopping(topping2); - - final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); - final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); - service.saveNewLayer(layer1); - service.saveNewLayer(layer2); - - service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, layer2))); - service.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer2))); - - } - -} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeTest.java b/layers/src/test/java/com/iluwatar/layers/CakeTest.java deleted file mode 100644 index f43f5508fc1e..000000000000 --- a/layers/src/test/java/com/iluwatar/layers/CakeTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import org.junit.Test; - -import java.util.HashSet; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/15/15 - 8:02 PM - * - * @author Jeroen Meulemeester - */ -public class CakeTest { - - @Test - public void testSetId() { - final Cake cake = new Cake(); - assertNull(cake.getId()); - - final Long expectedId = Long.valueOf(1234L); - cake.setId(expectedId); - assertEquals(expectedId, cake.getId()); - } - - @Test - public void testSetTopping() { - final Cake cake = new Cake(); - assertNull(cake.getTopping()); - - final CakeTopping expectedTopping = new CakeTopping("DummyTopping", 1000); - cake.setTopping(expectedTopping); - assertEquals(expectedTopping, cake.getTopping()); - } - - @Test - public void testSetLayers() { - final Cake cake = new Cake(); - assertNotNull(cake.getLayers()); - assertTrue(cake.getLayers().isEmpty()); - - final Set expectedLayers = new HashSet<>(); - expectedLayers.add(new CakeLayer("layer1", 1000)); - expectedLayers.add(new CakeLayer("layer2", 2000)); - expectedLayers.add(new CakeLayer("layer3", 3000)); - - cake.setLayers(expectedLayers); - assertEquals(expectedLayers, cake.getLayers()); - } - - @Test - public void testAddLayer() { - final Cake cake = new Cake(); - assertNotNull(cake.getLayers()); - assertTrue(cake.getLayers().isEmpty()); - - final Set initialLayers = new HashSet<>(); - initialLayers.add(new CakeLayer("layer1", 1000)); - initialLayers.add(new CakeLayer("layer2", 2000)); - - cake.setLayers(initialLayers); - assertEquals(initialLayers, cake.getLayers()); - - final CakeLayer newLayer = new CakeLayer("layer3", 3000); - cake.addLayer(newLayer); - - final Set expectedLayers = new HashSet<>(); - expectedLayers.addAll(initialLayers); - expectedLayers.addAll(initialLayers); - expectedLayers.add(newLayer); - assertEquals(expectedLayers, cake.getLayers()); - } - - @Test - public void testToString() { - final CakeTopping topping = new CakeTopping("topping", 20); - topping.setId(2345L); - - final CakeLayer layer = new CakeLayer("layer", 100); - layer.setId(3456L); - - final Cake cake = new Cake(); - cake.setId(1234L); - cake.setTopping(topping); - cake.addLayer(layer); - - final String expected = "id=1234 topping=id=2345 name=topping calories=20 " - + "layers=[id=3456 name=layer calories=100]"; - assertEquals(expected, cake.toString()); - - } - -} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java b/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java deleted file mode 100644 index 8a62e074bad6..000000000000 --- a/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.*; - -/** - * Date: 12/15/15 - 10:04 PM - * - * @author Jeroen Meulemeester - */ -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 - */ - @Test - public void testRender() { - - final List layers = new ArrayList<>(); - layers.add(new CakeLayerInfo("layer1", 1000)); - layers.add(new CakeLayerInfo("layer2", 2000)); - layers.add(new CakeLayerInfo("layer3", 3000)); - - final List cakes = new ArrayList<>(); - final CakeInfo cake = new CakeInfo(new CakeToppingInfo("topping", 1000), layers); - cakes.add(cake); - - final CakeBakingService bakingService = mock(CakeBakingService.class); - when(bakingService.getAllCakes()).thenReturn(cakes); - - final CakeViewImpl cakeView = new CakeViewImpl(bakingService); - - assertEquals(0, appender.getLogSize()); - - cakeView.render(); - 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/lazy-loading/README.md b/lazy-loading/README.md deleted file mode 100644 index 4b7a580c3f6f..000000000000 --- a/lazy-loading/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: pattern -title: Lazy Loading -folder: lazy-loading -permalink: /patterns/lazy-loading/ -pumlid: LSXB3W8X303Gg-W1e7jlqu66gIc5zED4JwzRTo_lpjeaEwN9xOpO_W0mlEhWEFD89sjBWpHgMnDOyi90WoU-i7Ho7besHf2fmqJ_0GG_xo8BE-i0YlONDMtMdLE- -categories: Other -tags: - - Java - - Difficulty-Beginner - - Idiom - - Performance ---- - -## Intent -Lazy loading is a design pattern commonly used to defer -initialization of an object until the point at which it is needed. It can -contribute to efficiency in the program's operation if properly and -appropriately used. - -![alt text](./etc/lazy-loading.png "Lazy Loading") - -## Applicability -Use the Lazy Loading idiom when - -* eager loading is expensive or the object to be loaded might not be needed at all - -## Real world examples - -* JPA annotations @OneToOne, @OneToMany, @ManyToOne, @ManyToMany and fetch = FetchType.LAZY - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) diff --git a/lazy-loading/etc/lazy-loading.png b/lazy-loading/etc/lazy-loading.png deleted file mode 100644 index bec0a7afbefe08d3741e4f2b5c4043c62977790e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11671 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 HHVODIUz$3B diff --git a/lazy-loading/etc/lazy-loading.ucls b/lazy-loading/etc/lazy-loading.ucls deleted file mode 100644 index 9f4ccd1a446d..000000000000 --- a/lazy-loading/etc/lazy-loading.ucls +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lazy-loading/etc/lazy-loading.urm.puml b/lazy-loading/etc/lazy-loading.urm.puml deleted file mode 100644 index aaf49f1df941..000000000000 --- a/lazy-loading/etc/lazy-loading.urm.puml +++ /dev/null @@ -1,40 +0,0 @@ -@startuml -package com.iluwatar.lazy.loading { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Heavy { - - LOGGER : Logger {static} - + Heavy() - } - class HolderNaive { - - LOGGER : Logger {static} - - heavy : Heavy - + HolderNaive() - + getHeavy() : Heavy - } - class HolderThreadSafe { - - LOGGER : Logger {static} - - heavy : Heavy - + HolderThreadSafe() - + getHeavy() : Heavy - } - class Java8Holder { - - LOGGER : Logger {static} - - heavy : Supplier - + Java8Holder() - - createAndCacheHeavy() : Heavy - + getHeavy() : Heavy - } - ~class HeavyFactory { - - heavyInstance : Heavy - ~ HeavyFactory() - + get() : Heavy - } -} -HolderThreadSafe --> "-heavy" Heavy -HolderNaive --> "-heavy" Heavy -HeavyFactory --> "-heavyInstance" Heavy -@enduml \ No newline at end of file diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml deleted file mode 100644 index 9d3652feb89a..000000000000 --- a/lazy-loading/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - lazy-loading - - - junit - junit - test - - - 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 deleted file mode 100644 index 0a5eac75953f..000000000000 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Lazy loading idiom defers object creation until needed. - *

    - * This example shows different implementations of the pattern with increasing sophistication. - *

    - * Additional information and lazy loading flavours are described in - * http://martinfowler.com/eaaCatalog/lazyLoad.html - * - */ -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) { - - // Simple lazy loader - not thread safe - HolderNaive holderNaive = new HolderNaive(); - Heavy heavy = holderNaive.getHeavy(); - LOGGER.info("heavy={}", heavy); - - // Thread safe lazy loader, but with heavy synchronization on each access - HolderThreadSafe holderThreadSafe = new HolderThreadSafe(); - Heavy another = holderThreadSafe.getHeavy(); - LOGGER.info("another={}", another); - - // The most efficient lazy loader utilizing Java 8 features - Java8Holder java8Holder = new Java8Holder(); - Heavy next = java8Holder.getHeavy(); - 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 deleted file mode 100644 index 1c23611c3136..000000000000 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Heavy objects are expensive to create. - * - */ -public class Heavy { - - private static final Logger LOGGER = LoggerFactory.getLogger(Heavy.class); - - /** - * Constructor - */ - public Heavy() { - LOGGER.info("Creating Heavy ..."); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - LOGGER.error("Exception caught.", e); - } - 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 deleted file mode 100644 index 5e4552ecfee4..000000000000 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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. - * - */ -public class HolderNaive { - - private static final Logger LOGGER = LoggerFactory.getLogger(HolderNaive.class); - - private Heavy heavy; - - /** - * Constructor - */ - public HolderNaive() { - LOGGER.info("HolderNaive created"); - } - - /** - * Get heavy object - */ - public Heavy getHeavy() { - if (heavy == null) { - heavy = new Heavy(); - } - return heavy; - } -} 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 deleted file mode 100644 index b36ec24ba107..000000000000 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * {@link #getHeavy()} call costs additional synchronization overhead. - * - */ -public class HolderThreadSafe { - - private static final Logger LOGGER = LoggerFactory.getLogger(HolderThreadSafe.class); - - private Heavy heavy; - - /** - * Constructor - */ - public HolderThreadSafe() { - LOGGER.info("HolderThreadSafe created"); - } - - /** - * Get heavy object - */ - public synchronized Heavy getHeavy() { - if (heavy == null) { - heavy = new Heavy(); - } - return heavy; - } -} 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 deleted file mode 100644 index faa553c5eb36..000000000000 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.function.Supplier; - -/** - * - * This lazy loader is thread safe and more efficient than {@link HolderThreadSafe}. It utilizes - * Java 8 functional interface {@link Supplier} as {@link Heavy} factory. - * - */ -public class Java8Holder { - - private static final Logger LOGGER = LoggerFactory.getLogger(Java8Holder.class); - - private Supplier heavy = () -> createAndCacheHeavy(); - - public Java8Holder() { - LOGGER.info("Java8Holder created"); - } - - public Heavy getHeavy() { - return heavy.get(); - } - - private synchronized Heavy createAndCacheHeavy() { - class HeavyFactory implements Supplier { - private final Heavy heavyInstance = new Heavy(); - - @Override - public Heavy get() { - return heavyInstance; - } - } - if (!HeavyFactory.class.isInstance(heavy)) { - heavy = new HeavyFactory(); - } - return heavy.get(); - } -} diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java deleted file mode 100644 index 917ccb8d3a10..000000000000 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import org.junit.Test; - -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertSame; -import static junit.framework.TestCase.assertNull; - -/** - * Date: 12/19/15 - 11:58 AM - * - * @author Jeroen Meulemeester - */ -public abstract class AbstractHolderTest { - - /** - * Get the internal state of the holder value - * - * @return The internal value - */ - abstract Heavy getInternalHeavyValue() throws Exception; - - /** - * Request a lazy loaded {@link Heavy} object from the holder. - * - * @return The lazy loaded {@link Heavy} object - */ - abstract Heavy getHeavy() throws Exception; - - /** - * This test shows that the heavy field is not instantiated until the method getHeavy is called - */ - @Test(timeout = 3000) - public void testGetHeavy() throws Exception { - assertNull(getInternalHeavyValue()); - assertNotNull(getHeavy()); - assertNotNull(getInternalHeavyValue()); - assertSame(getHeavy(), getInternalHeavyValue()); - } - -} diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AppTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AppTest.java deleted file mode 100644 index cefa9918ac70..000000000000 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java deleted file mode 100644 index 39e8a55d70ab..000000000000 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import java.lang.reflect.Field; - -/** - * Date: 12/19/15 - 12:05 PM - * - * @author Jeroen Meulemeester - */ -public class HolderNaiveTest extends AbstractHolderTest { - - private final HolderNaive holder = new HolderNaive(); - - @Override - Heavy getInternalHeavyValue() throws Exception { - final Field holderField = HolderNaive.class.getDeclaredField("heavy"); - holderField.setAccessible(true); - return (Heavy) holderField.get(this.holder); - } - - @Override - Heavy getHeavy() { - return holder.getHeavy(); - } - -} \ No newline at end of file diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java deleted file mode 100644 index d4017363d392..000000000000 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import java.lang.reflect.Field; - -/** - * Date: 12/19/15 - 12:19 PM - * - * @author Jeroen Meulemeester - */ -public class HolderThreadSafeTest extends AbstractHolderTest { - - private final HolderThreadSafe holder = new HolderThreadSafe(); - - @Override - Heavy getInternalHeavyValue() throws Exception { - final Field holderField = HolderThreadSafe.class.getDeclaredField("heavy"); - holderField.setAccessible(true); - return (Heavy) holderField.get(this.holder); - } - - @Override - Heavy getHeavy() throws Exception { - return this.holder.getHeavy(); - } - -} \ No newline at end of file diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java deleted file mode 100644 index 3e5078397653..000000000000 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.lazy.loading; - -import java.lang.reflect.Field; -import java.util.function.Supplier; - -/** - * Date: 12/19/15 - 12:27 PM - * - * @author Jeroen Meulemeester - */ -public class Java8HolderTest extends AbstractHolderTest { - - private final Java8Holder holder = new Java8Holder(); - - - @Override - Heavy getInternalHeavyValue() throws Exception { - final Field holderField = Java8Holder.class.getDeclaredField("heavy"); - holderField.setAccessible(true); - - final Supplier supplier = (Supplier) holderField.get(this.holder); - final Class supplierClass = supplier.getClass(); - - // This is a little fishy, but I don't know another way to test this: - // The lazy holder is at first a lambda, but gets replaced with a new supplier after loading ... - if (supplierClass.isLocalClass()) { - final Field instanceField = supplierClass.getDeclaredField("heavyInstance"); - instanceField.setAccessible(true); - return (Heavy) instanceField.get(supplier); - } else { - return null; - } - } - - @Override - Heavy getHeavy() throws Exception { - return holder.getHeavy(); - } - -} \ No newline at end of file diff --git a/marker/.gitignore b/marker/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/marker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/marker/README.md b/marker/README.md deleted file mode 100644 index 5bcdf96643db..000000000000 --- a/marker/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Marker Interface -folder: marker -permalink: /patterns/marker/ -categories: Design -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Using empty interfaces as markers to distinguish special treated objects. - -![alt text](./etc/MarkerDiagram.png "Marker Interface") - -## Applicability -Use the Marker Interface pattern when - -* you want to identify the special objects from normal objects (to treat them differently) -* you want to mark that some object is available for certain sort of operations - -## Real world examples - -* [javase.8.docs.api.java.io.Serializable](https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) -* [javase.8.docs.api.java.lang.Cloneable](https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html) - -## Credits - -* [Effective Java 2nd Edition by Joshua Bloch](https://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683) diff --git a/marker/etc/MarkerDiagram.png b/marker/etc/MarkerDiagram.png deleted file mode 100644 index 6ed4f9c567809787d9317733a2e4fe40cbe3284c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6461 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 WzLyy+Lj79=qN54ic(48-^uGXLahsh0 diff --git a/marker/etc/MarkerDiagram.ucls b/marker/etc/MarkerDiagram.ucls deleted file mode 100644 index 0f8376e40e23..000000000000 --- a/marker/etc/MarkerDiagram.ucls +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/marker/etc/marker.urm.puml b/marker/etc/marker.urm.puml deleted file mode 100644 index 02af47ddf261..000000000000 --- a/marker/etc/marker.urm.puml +++ /dev/null @@ -1,2 +0,0 @@ -@startuml -@enduml \ No newline at end of file diff --git a/marker/pom.xml b/marker/pom.xml deleted file mode 100644 index 91cf2c48a6df..000000000000 --- a/marker/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - marker - - - junit - junit - test - - - - - diff --git a/marker/src/main/java/App.java b/marker/src/main/java/App.java deleted file mode 100644 index d8fd54ecb3b9..000000000000 --- a/marker/src/main/java/App.java +++ /dev/null @@ -1,70 +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. - */ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Created by Alexis on 28-Apr-17. - * With Marker interface idea is to make empty interface and extend it. - * Basically it is just to identify the special objects from normal objects. - * Like in case of serialization , objects that need to be serialized must implement serializable interface - * (it is empty interface) and down the line writeObject() method must be checking - * if it is a instance of serializable or not. - *

    - * Marker interface vs annotation - * Marker interfaces and marker annotations both have their uses, - * neither of them is obsolete or always better then the other one. - * If you want to define a type that does not have any new methods associated with it, - * a marker interface is the way to go. - * If you want to mark program elements other than classes and interfaces, - * to allow for the possibility of adding more information to the marker in the future, - * or to fit the marker into a framework that already makes heavy use of annotation types, - * then a marker annotation is the correct choice - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - final Logger logger = LoggerFactory.getLogger(App.class); - Guard guard = new Guard(); - Thief thief = new Thief(); - - if (guard instanceof Permission) { - guard.enter(); - } else { - logger.info("You have no permission to enter, please leave this area"); - } - - if (thief instanceof Permission) { - thief.steal(); - } else { - thief.doNothing(); - } - } -} - diff --git a/marker/src/main/java/Guard.java b/marker/src/main/java/Guard.java deleted file mode 100644 index 4dd2a48872e6..000000000000 --- a/marker/src/main/java/Guard.java +++ /dev/null @@ -1,37 +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. - */ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class defining Guard - */ -public class Guard implements Permission { - - private static final Logger LOGGER = LoggerFactory.getLogger(Guard.class); - - protected static void enter() { - - LOGGER.info("You can enter"); - } -} diff --git a/marker/src/main/java/Permission.java b/marker/src/main/java/Permission.java deleted file mode 100644 index 2a85b336304d..000000000000 --- a/marker/src/main/java/Permission.java +++ /dev/null @@ -1,28 +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. - */ -/** - * Interface without any methods - * Marker interface is based on that assumption - */ -public interface Permission { -} diff --git a/marker/src/main/java/Thief.java b/marker/src/main/java/Thief.java deleted file mode 100644 index b8d6464e51ac..000000000000 --- a/marker/src/main/java/Thief.java +++ /dev/null @@ -1,40 +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. - */ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class defining Thief - */ -public class Thief { - - private static final Logger LOGGER = LoggerFactory.getLogger(Thief.class); - - protected static void steal() { - LOGGER.info("Steal valuable items"); - } - - protected static void doNothing() { - LOGGER.info("Pretend nothing happened and just leave"); - } -} diff --git a/marker/src/test/java/AppTest.java b/marker/src/test/java/AppTest.java deleted file mode 100644 index 85fb61b16d9b..000000000000 --- a/marker/src/test/java/AppTest.java +++ /dev/null @@ -1,35 +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. - */ -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/marker/src/test/java/GuardTest.java b/marker/src/test/java/GuardTest.java deleted file mode 100644 index eb3a4b75719f..000000000000 --- a/marker/src/test/java/GuardTest.java +++ /dev/null @@ -1,38 +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. - */ -import org.junit.Test; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertThat; - -/** - * Guard test - */ -public class GuardTest { - - @Test - public void testGuard() { - Guard guard = new Guard(); - assertThat(guard, instanceOf(Permission.class)); - } -} \ No newline at end of file diff --git a/marker/src/test/java/ThiefTest.java b/marker/src/test/java/ThiefTest.java deleted file mode 100644 index f950809cc333..000000000000 --- a/marker/src/test/java/ThiefTest.java +++ /dev/null @@ -1,36 +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. - */ -import org.junit.Test; - -import static org.junit.Assert.assertFalse; - -/** - * Thief test - */ -public class ThiefTest { - @Test - public void testThief() { - Thief thief = new Thief(); - assertFalse(thief instanceof Permission); - } -} \ No newline at end of file diff --git a/mediator/README.md b/mediator/README.md deleted file mode 100644 index 084e59256dbe..000000000000 --- a/mediator/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: pattern -title: Mediator -folder: mediator -permalink: /patterns/mediator/ -pumlid: FSV14SCm20J0Lk82BFxf1akCJKOW3JhizfDNVhkRUktP9AE_Bc2kDr7mKqx5bKSkYJeSuYXr66dFXy517xvvRxBqz7qo8E6BZDSFPDAKCO84zP-IOMMczIy0 -categories: Behavioral -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Intent -Define an object that encapsulates how a set of objects interact. -Mediator promotes loose coupling by keeping objects from referring to each -other explicitly, and it lets you vary their interaction independently. - -![alt text](./etc/mediator_1.png "Mediator") - -## Applicability -Use the Mediator pattern when - -* a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand -* reusing an object is difficult because it refers to and communicates with many other objects -* a behavior that's distributed between several classes should be customizable without a lot of subclassing - -## Real world examples - -* All scheduleXXX() methods of [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html) -* [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-) -* submit() and invokeXXX() methods of [java.util.concurrent.ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) -* scheduleXXX() methods of [java.util.concurrent.ScheduledExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html) -* [java.lang.reflect.Method#invoke()](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/mediator/etc/mediator.png b/mediator/etc/mediator.png deleted file mode 100644 index 1ba1984ee1a836308c669f1fee1dd02ce0d0e107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36948 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 diff --git a/mediator/etc/mediator.ucls b/mediator/etc/mediator.ucls deleted file mode 100644 index 1f3ead9fa40e..000000000000 --- a/mediator/etc/mediator.ucls +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mediator/etc/mediator.urm.puml b/mediator/etc/mediator.urm.puml deleted file mode 100644 index 04e75d2b8841..000000000000 --- a/mediator/etc/mediator.urm.puml +++ /dev/null @@ -1,69 +0,0 @@ -@startuml -package com.iluwatar.mediator { - enum Action { - + ENEMY {static} - + GOLD {static} - + HUNT {static} - + NONE {static} - + TALE {static} - - description : String - - title : String - + getDescription() : String - + toString() : String - + valueOf(name : String) : Action {static} - + values() : Action[] {static} - } - class App { - + App() - + main(args : String[]) {static} - } - class Hobbit { - + Hobbit() - + toString() : String - } - class Hunter { - + Hunter() - + toString() : String - } - interface Party { - + act(PartyMember, Action) {abstract} - + addMember(PartyMember) {abstract} - } - class PartyImpl { - - members : List - + PartyImpl() - + act(actor : PartyMember, action : Action) - + addMember(member : PartyMember) - } - interface PartyMember { - + act(Action) {abstract} - + joinedParty(Party) {abstract} - + partyAction(Action) {abstract} - } - abstract class PartyMemberBase { - - LOGGER : Logger {static} - # party : Party - + PartyMemberBase() - + act(action : Action) - + joinedParty(party : Party) - + partyAction(action : Action) - + toString() : String {abstract} - } - class Rogue { - + Rogue() - + toString() : String - } - class Wizard { - + Wizard() - + toString() : String - } -} -PartyImpl --> "-members" PartyMember -PartyMemberBase --> "-party" Party -Hobbit --|> PartyMemberBase -Hunter --|> PartyMemberBase -PartyImpl ..|> Party -PartyMemberBase ..|> PartyMember -Rogue --|> PartyMemberBase -Wizard --|> PartyMemberBase -@enduml \ No newline at end of file diff --git a/mediator/etc/mediator_1.png b/mediator/etc/mediator_1.png deleted file mode 100644 index 0b48ffdbaee74cb5d13117fd3e400c94be50e2fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59727 zcmbrmbySsWyFIK3NQVN_Er@h?cbC$+KtSnKT50KSq)WO4q$C!d0s_*Fba(vj#olk8 zbH@0__{P|O?7dmfbJulWG3UIV&nimN=qQ9J4<0-~mz9xFd+^{9(}M?aNJwzt|2$S_ zGLgg@-G8VjXK_m`44HX@Y z_C^FPk`K!(nPBAKeF+r=1ol~)R4xDZyPy|PgGQcDKMx8E(TX%m>^8>&X1)z3v7hfu zS8cAaTP42Fm3xz~w8Q+py0#0s4jVpGtKTWcIqJ?O1lehQok58-5nEbwm zkLBX@^~j28+s>t`(x(5+m7i@S&`wO&Ypg?m93no*u2y9xrl#-}%+Z3x`WVktjcc=l zhht0c&mVhH(Phi=%Cm#F&U*&2!7@|cxmsG2+rMjyw6$U_CWk-w)L>J2oNjA(tC0%S z36TGgXCatR#A$HZkroz?s4#J#p46)U&S%g>7_KPj{!LU{N$K?M+pgth?(cOxI=Z?U zLg&FHnx%f2#2bGWN5-b=zow+n$9~VwCaHYFu-l(RmdsgXSg1A?Mb*G=ou5j9@zmJV z=TX;U6$t`Wq486~Pq!b$wjyz;MvGM=pqX^*ZrA5XW6BqYZ^$!kW`kd0_YlxR%aI+{ zf9CEWi96IcaCiP19!}E#&S6gHe)6ut^~kB!)Wbv#ExFKQgwk;xLs3yM)PeuK4NXkM zjhJ@9&}hCiBjZ4O`=g5S`Ie)O&+|r>4h}(uZ%2Oopa{e$@snZW=5BChKdhanj13XT zSnbu$wi)^Y&2Ynd?S12{z$JIAb4`tT>K6bRu>eF-H zDa)E;&U$b_wDqfmX<0A>4dctN99ex+ga%J{+nwLzrVez7k!;bK@pA zPOZv7%xq@EIf_II^B2zoBgiP&9HKU5-c3pvpPxnKKNS2fO(|}mAQQaWHS8E<@K})h z>1Kscrsz7KgK1n!isi{>+^>?9<4fnpU>UPioU45b*VFA*aHhEQzsXsjDzh+`;bCJR zo$VPe{kb?8)UfH{SbI{NBi2H1K41w$#?}jD#QV&EY4A&;7jfi(+%NoQ{JrNNznV zFE&OfcrbGCg}Grf)@|`}I9g+3nDTx6I6EsI#q7iG3?4B91}_Cg;xskBEPBc?5;e4g z<1^0}V@}43ya;q);Jb6@7f1Mh?Ci^ef+=A{6ViFebTq%5Say;mh^0xYSM(B?_lzi| zc%Q%(Id4hbT|4qon@W}Fkl7lR7zmc?*5a{UtolVL)8iqFC%=4cMX$-!6@T8#NMQal z2fx3+m6*A-)yscaPyHzgJ+d)_l9FL?G2<0T{9 zueAR$&rA+R?EHvK9QDyGt5dwHu80U?emv@{G92|m3Vwe3;S8oBHrGwM4p50BLt?X0*{P4;@Wn`|d2NPPLt6gb%8xy!_F0?b*w&at|kA5(Rf) zE~<|!Qnyz7wET6yS~zUZn7(FD%D6cidW+ZHBMW)?)d;%iAeq^sA}n4)$Z6G+Wl1Lm zhS~UV$qWUI<)ě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 - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - mediator - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/mediator/src/main/java/com/iluwatar/mediator/Action.java b/mediator/src/main/java/com/iluwatar/mediator/Action.java deleted file mode 100644 index 4deb0388dab5..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Action.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Action enumeration. - * - */ -public enum Action { - - HUNT("hunted a rabbit", "arrives for dinner"), TALE("tells a tale", "comes to listen"), GOLD( - "found gold", "takes his share of the gold"), ENEMY("spotted enemies", "runs for cover"), NONE( - "", ""); - - private String title; - private String description; - - Action(String title, String description) { - this.title = title; - this.description = description; - } - - public String getDescription() { - return description; - } - - public String toString() { - return title; - } -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/App.java b/mediator/src/main/java/com/iluwatar/mediator/App.java deleted file mode 100644 index 09433da26d42..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/App.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * The Mediator pattern defines an object that encapsulates how a set of objects interact. This - * pattern is considered to be a behavioral pattern due to the way it can alter the program's - * running behavior. - *

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

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

    - * In this example the mediator encapsulates how a set of objects ({@link PartyMember}) interact. - * Instead of referring to each other directly they use the mediator ({@link Party}) interface. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - // create party and members - Party party = new PartyImpl(); - Hobbit hobbit = new Hobbit(); - Wizard wizard = new Wizard(); - Rogue rogue = new Rogue(); - Hunter hunter = new Hunter(); - - // add party members - party.addMember(hobbit); - party.addMember(wizard); - party.addMember(rogue); - party.addMember(hunter); - - // perform actions -> the other party members - // are notified by the party - hobbit.act(Action.ENEMY); - wizard.act(Action.TALE); - rogue.act(Action.GOLD); - hunter.act(Action.HUNT); - } -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java b/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java deleted file mode 100644 index 654048d55df6..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Hobbit party member. - * - */ -public class Hobbit extends PartyMemberBase { - - @Override - public String toString() { - return "Hobbit"; - } - -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/Hunter.java b/mediator/src/main/java/com/iluwatar/mediator/Hunter.java deleted file mode 100644 index 23988bd58939..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Hunter.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Hunter party member. - * - */ -public class Hunter extends PartyMemberBase { - - @Override - public String toString() { - return "Hunter"; - } -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/Party.java b/mediator/src/main/java/com/iluwatar/mediator/Party.java deleted file mode 100644 index d68e027913fb..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Party.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Party interface. - * - */ -public interface Party { - - void addMember(PartyMember member); - - void act(PartyMember actor, Action action); - -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java b/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java deleted file mode 100644 index d30ee3ba41a6..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * Party implementation. - * - */ -public class PartyImpl implements Party { - - private final List members; - - public PartyImpl() { - members = new ArrayList<>(); - } - - @Override - public void act(PartyMember actor, Action action) { - for (PartyMember member : members) { - if (!member.equals(actor)) { - member.partyAction(action); - } - } - } - - @Override - public void addMember(PartyMember member) { - members.add(member); - member.joinedParty(this); - } -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java b/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java deleted file mode 100644 index 09f64c215981..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Interface for party members interacting with {@link Party}. - * - */ -public interface PartyMember { - - void joinedParty(Party party); - - void partyAction(Action action); - - void act(Action action); -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java b/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java deleted file mode 100644 index 4c60a3b43b64..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Abstract base class for party members. - * - */ -public abstract class PartyMemberBase implements PartyMember { - - private static final Logger LOGGER = LoggerFactory.getLogger(PartyMemberBase.class); - - protected Party party; - - @Override - public void joinedParty(Party party) { - LOGGER.info("{} joins the party", this); - this.party = party; - } - - @Override - public void partyAction(Action action) { - LOGGER.info("{} {}", this, action.getDescription()); - } - - @Override - public void act(Action action) { - if (party != null) { - LOGGER.info("{} {}", this, action); - party.act(this, action); - } - } - - @Override - public abstract String toString(); - -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/Rogue.java b/mediator/src/main/java/com/iluwatar/mediator/Rogue.java deleted file mode 100644 index e0b6c7847791..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Rogue.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Rogue party member. - * - */ -public class Rogue extends PartyMemberBase { - - @Override - public String toString() { - return "Rogue"; - } - -} diff --git a/mediator/src/main/java/com/iluwatar/mediator/Wizard.java b/mediator/src/main/java/com/iluwatar/mediator/Wizard.java deleted file mode 100644 index fb0833e57cca..000000000000 --- a/mediator/src/main/java/com/iluwatar/mediator/Wizard.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -/** - * - * Wizard party member. - * - */ -public class Wizard extends PartyMemberBase { - - @Override - public String toString() { - return "Wizard"; - } - -} diff --git a/mediator/src/test/java/com/iluwatar/mediator/AppTest.java b/mediator/src/test/java/com/iluwatar/mediator/AppTest.java deleted file mode 100644 index d92b8969bd00..000000000000 --- a/mediator/src/test/java/com/iluwatar/mediator/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java deleted file mode 100644 index bb3c51474ea8..000000000000 --- a/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mediator; - -import org.junit.Test; - -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:00 PM - * - * @author Jeroen Meulemeester - */ -public class PartyImplTest { - - /** - * Verify if a member is notified when it's joining a party. Generate an action and see if the - * other member gets it. Also check members don't get their own actions. - */ - @Test - public void testPartyAction() { - final PartyMember partyMember1 = mock(PartyMember.class); - final PartyMember partyMember2 = mock(PartyMember.class); - - final PartyImpl party = new PartyImpl(); - party.addMember(partyMember1); - party.addMember(partyMember2); - - verify(partyMember1).joinedParty(party); - verify(partyMember2).joinedParty(party); - - party.act(partyMember1, Action.GOLD); - verifyZeroInteractions(partyMember1); - verify(partyMember2).partyAction(Action.GOLD); - - verifyNoMoreInteractions(partyMember1, partyMember2); - - } - -} diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java deleted file mode 100644 index 4d578c33331d..000000000000 --- a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.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; - -/** - * Date: 12/19/15 - 10:13 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class PartyMemberTest { - - @Parameterized.Parameters - public static Collection[]> data() { - return Arrays.asList( - new Supplier[]{Hobbit::new}, - new Supplier[]{Hunter::new}, - new Supplier[]{Rogue::new}, - new Supplier[]{Wizard::new} - ); - } - - /** - * The factory, used to create a new instance of the tested party member - */ - private final Supplier memberSupplier; - - /** - * Create a new test instance, using the given {@link PartyMember} factory - * - * @param memberSupplier The party member factory - */ - 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 - */ - @Test - public void testPartyAction() { - final PartyMember member = this.memberSupplier.get(); - - for (final Action action : Action.values()) { - member.partyAction(action); - assertEquals(member.toString() + " " + action.getDescription(), appender.getLastMessage()); - } - - assertEquals(Action.values().length, appender.getLogSize()); - } - - /** - * Verify if a member action triggers the expected interactions with the party class - */ - @Test - public void testAct() { - final PartyMember member = this.memberSupplier.get(); - - member.act(Action.GOLD); - assertEquals(0, appender.getLogSize()); - - final Party party = mock(Party.class); - member.joinedParty(party); - assertEquals(member.toString() + " joins the party", appender.getLastMessage()); - - for (final Action action : Action.values()) { - member.act(action); - assertEquals(member.toString() + " " + action.toString(), appender.getLastMessage()); - verify(party).act(member, action); - } - - assertEquals(Action.values().length + 1, appender.getLogSize()); - } - - /** - * Verify if {@link PartyMember#toString()} generate the expected output - */ - @Test - public void testToString() throws Exception { - final PartyMember member = this.memberSupplier.get(); - final Class memberClass = member.getClass(); - 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/memento/README.md b/memento/README.md deleted file mode 100644 index f4384932980f..000000000000 --- a/memento/README.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: pattern -title: Memento -folder: memento -permalink: /patterns/memento/ -pumlid: DSgn4OCm30NGLM00h3xR2AC3SvRiaxx2-g59zugtDgiz3qdlomNC-10vF-Lik7BF4A_388PIXrBh-J3OwUOlRuT4EssR38XRa7Ay81Lz_o11_RkaQvcf_GS0 -categories: Behavioral -tags: - - Java - - Gang Of Four - - Difficulty-Intermediate ---- - -## Also known as -Token - -## Intent -Without violating encapsulation, capture and externalize an -object's internal state so that the object can be restored to this state later. - -![alt text](./etc/memento.png "Memento") - -## Applicability -Use the Memento pattern when - -* a snapshot of an object's state must be saved so that it can be restored to that state later, and -* a direct interface to obtaining the state would expose implementation details and break the object's encapsulation - -## Real world examples - -* [java.util.Date](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/memento/etc/memento.png b/memento/etc/memento.png deleted file mode 100644 index dcfe7a749b049beaaa38eeae61eaad6a58e294ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22492 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�ImvFUJpP% z1|4clzm290Pknk1*et?&TlbbUy@f&No4Q!sm^;n8(#NH< zyw#W~Kmc*BC>JR{b_>S%^Sig_squJDCN2G;U)jKdC^K0HRzur=I9)}GiK;>Bf5xec zK)g0SeLFXbs`Vs?l%}k6Sf7Jx#$|~mWxr;E zn#qHeHiPHUrts_SK4C_)4MBH<`0_lq`!B{`|FJ*&hXCYCu{uohrV&$Ma+RU0_W8Jg zkn2L$YM&&L^{bW7>4p&fc%tYU0%V@Mv=UJ)aJZ?&1Ijz2Mz+k9NyN$mKrr6cTvU{S zjqZaBZCUF@XRn{b*0sC{Fy^`@TYjFldytm>ACO>+)qIT|9OL8}I!**2EE!xwjDii^ z5;n-WsHzyEwrmx&XtnMKnSm|^eq}2FnP%xY_m{h0Ela_cg{N%TGQ$ z8HTO^Jd0zzi5g>~190uGg)!cF;G - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/memento/etc/memento.urm.puml b/memento/etc/memento.urm.puml deleted file mode 100644 index 319227ad242c..000000000000 --- a/memento/etc/memento.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.memento { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Star { - - ageYears : int - - massTons : int - - type : StarType - + Star(startType : StarType, startAge : int, startMass : int) - ~ getMemento() : StarMemento - ~ setMemento(memento : StarMemento) - + timePasses() - + toString() : String - } - -class StarMementoInternal { - - ageYears : int - - massTons : int - - type : StarType - - StarMementoInternal() - + getAgeYears() : int - + getMassTons() : int - + getType() : StarType - + setAgeYears(ageYears : int) - + setMassTons(massTons : int) - + setType(type : StarType) - } - interface StarMemento { - } - enum StarType { - + DEAD {static} - + RED_GIANT {static} - + SUN {static} - + SUPERNOVA {static} - + UNDEFINED {static} - + WHITE_DWARF {static} - - title : String - + toString() : String - + valueOf(name : String) : StarType {static} - + values() : StarType[] {static} - } -} -StarMementoInternal --> "-type" StarType -Star --> "-type" StarType -StarMementoInternal ..+ Star -StarMementoInternal ..|> StarMemento -@enduml \ No newline at end of file diff --git a/memento/pom.xml b/memento/pom.xml deleted file mode 100644 index 858b75544bbd..000000000000 --- a/memento/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - memento - - - junit - junit - test - - - diff --git a/memento/src/main/java/com/iluwatar/memento/App.java b/memento/src/main/java/com/iluwatar/memento/App.java deleted file mode 100644 index c20ad4654baf..000000000000 --- a/memento/src/main/java/com/iluwatar/memento/App.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Stack; - -/** - * - * The Memento pattern is a software design pattern that provides the ability to restore an object - * to its previous state (undo via rollback). - *

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

    - * In this example the object ({@link Star}) gives out a "memento" ({@link StarMemento}) that - * contains the state of the object. Later on the memento can be set back to the object restoring - * the state. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - Stack states = new Stack<>(); - - Star star = new Star(StarType.SUN, 10000000, 500000); - LOGGER.info(star.toString()); - states.add(star.getMemento()); - star.timePasses(); - LOGGER.info(star.toString()); - states.add(star.getMemento()); - star.timePasses(); - LOGGER.info(star.toString()); - states.add(star.getMemento()); - star.timePasses(); - LOGGER.info(star.toString()); - states.add(star.getMemento()); - star.timePasses(); - LOGGER.info(star.toString()); - while (states.size() > 0) { - star.setMemento(states.pop()); - LOGGER.info(star.toString()); - } - } -} diff --git a/memento/src/main/java/com/iluwatar/memento/Star.java b/memento/src/main/java/com/iluwatar/memento/Star.java deleted file mode 100644 index aac1e75fc301..000000000000 --- a/memento/src/main/java/com/iluwatar/memento/Star.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -/** - * - * Star uses "mementos" to store and restore state. - * - */ -public class Star { - - private StarType type; - private int ageYears; - private int massTons; - - /** - * Constructor - */ - public Star(StarType startType, int startAge, int startMass) { - this.type = startType; - this.ageYears = startAge; - this.massTons = startMass; - } - - /** - * Makes time pass for the star - */ - public void timePasses() { - ageYears *= 2; - massTons *= 8; - switch (type) { - case RED_GIANT: - type = StarType.WHITE_DWARF; - break; - case SUN: - type = StarType.RED_GIANT; - break; - case SUPERNOVA: - type = StarType.DEAD; - break; - case WHITE_DWARF: - type = StarType.SUPERNOVA; - break; - case DEAD: - ageYears *= 2; - massTons = 0; - break; - default: - break; - } - } - - StarMemento getMemento() { - - StarMementoInternal state = new StarMementoInternal(); - state.setAgeYears(ageYears); - state.setMassTons(massTons); - state.setType(type); - return state; - - } - - void setMemento(StarMemento memento) { - - StarMementoInternal state = (StarMementoInternal) memento; - this.type = state.getType(); - this.ageYears = state.getAgeYears(); - this.massTons = state.getMassTons(); - - } - - @Override - public String toString() { - return String.format("%s age: %d years mass: %d tons", type.toString(), ageYears, massTons); - } - - /** - * - * StarMemento implementation - * - */ - private static class StarMementoInternal implements StarMemento { - - private StarType type; - private int ageYears; - private int massTons; - - public StarType getType() { - return type; - } - - public void setType(StarType type) { - this.type = type; - } - - public int getAgeYears() { - return ageYears; - } - - public void setAgeYears(int ageYears) { - this.ageYears = ageYears; - } - - public int getMassTons() { - return massTons; - } - - public void setMassTons(int massTons) { - this.massTons = massTons; - } - } -} diff --git a/memento/src/main/java/com/iluwatar/memento/StarMemento.java b/memento/src/main/java/com/iluwatar/memento/StarMemento.java deleted file mode 100644 index 94e6da186d29..000000000000 --- a/memento/src/main/java/com/iluwatar/memento/StarMemento.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -/** - * - * External interface to memento. - * - */ -public interface StarMemento { - -} diff --git a/memento/src/main/java/com/iluwatar/memento/StarType.java b/memento/src/main/java/com/iluwatar/memento/StarType.java deleted file mode 100644 index 414cccc465e7..000000000000 --- a/memento/src/main/java/com/iluwatar/memento/StarType.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -/** - * - * StarType enumeration - * - */ -public enum StarType { - - SUN("sun"), RED_GIANT("red giant"), WHITE_DWARF("white dwarf"), SUPERNOVA("supernova"), DEAD( - "dead star"), UNDEFINED(""); - - private String title; - - StarType(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/memento/src/test/java/com/iluwatar/memento/AppTest.java b/memento/src/test/java/com/iluwatar/memento/AppTest.java deleted file mode 100644 index b9875712297a..000000000000 --- a/memento/src/test/java/com/iluwatar/memento/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/memento/src/test/java/com/iluwatar/memento/StarTest.java b/memento/src/test/java/com/iluwatar/memento/StarTest.java deleted file mode 100644 index 2a7efc70f51c..000000000000 --- a/memento/src/test/java/com/iluwatar/memento/StarTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.memento; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/20/15 - 10:08 AM - * - * @author Jeroen Meulemeester - */ -public class StarTest { - - /** - * Verify the stages of a dying sun, without going back in time - */ - @Test - public void testTimePasses() { - final Star star = new Star(StarType.SUN, 1, 2); - assertEquals("sun age: 1 years mass: 2 tons", star.toString()); - - star.timePasses(); - assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); - - star.timePasses(); - assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); - - star.timePasses(); - assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); - - star.timePasses(); - assertEquals("dead star age: 16 years mass: 8192 tons", star.toString()); - - star.timePasses(); - assertEquals("dead star age: 64 years mass: 0 tons", star.toString()); - - star.timePasses(); - assertEquals("dead star age: 256 years mass: 0 tons", star.toString()); - } - - /** - * Verify some stage of a dying sun, but go back in time to test the memento - */ - @Test - public void testSetMemento() { - final Star star = new Star(StarType.SUN, 1, 2); - final StarMemento firstMemento = star.getMemento(); - assertEquals("sun age: 1 years mass: 2 tons", star.toString()); - - star.timePasses(); - final StarMemento secondMemento = star.getMemento(); - assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); - - star.timePasses(); - final StarMemento thirdMemento = star.getMemento(); - assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); - - star.timePasses(); - assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); - - star.setMemento(thirdMemento); - assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); - - star.timePasses(); - assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); - - star.setMemento(secondMemento); - assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); - - star.setMemento(firstMemento); - assertEquals("sun age: 1 years mass: 2 tons", star.toString()); - - } - -} diff --git a/message-channel/.gitignore b/message-channel/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/message-channel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/message-channel/README.md b/message-channel/README.md deleted file mode 100644 index 09361dd4a65f..000000000000 --- a/message-channel/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Message Channel -folder: message-channel -permalink: /patterns/message-channel/ -categories: Integration -tags: - - Java - - EIP - - Apache Camel™ ---- - -## Intent -When two applications communicate using a messaging system they do it by using logical addresses -of the system, so called Message Channels. - -![alt text](./etc/message-channel.png "Message Channel") - -## Applicability -Use the Message Channel pattern when - -* two or more applications need to communicate using a messaging system - -## Real world examples - -* [akka-camel](http://doc.akka.io/docs/akka/snapshot/scala/camel.html) diff --git a/message-channel/etc/message-channel.png b/message-channel/etc/message-channel.png deleted file mode 100644 index 7db473281affe66670f2a7e7488ad26de87107e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47216 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 diff --git a/message-channel/etc/message-channel.ucls b/message-channel/etc/message-channel.ucls deleted file mode 100644 index 3ef0ed4bc8fd..000000000000 --- a/message-channel/etc/message-channel.ucls +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/message-channel/etc/message-channel.urm.puml b/message-channel/etc/message-channel.urm.puml deleted file mode 100644 index 852f190b46d0..000000000000 --- a/message-channel/etc/message-channel.urm.puml +++ /dev/null @@ -1,9 +0,0 @@ -@startuml -package com.iluwatar.message.channel { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/message-channel/pom.xml b/message-channel/pom.xml deleted file mode 100644 index 091c35f85908..000000000000 --- a/message-channel/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - message-channel - - - org.apache.camel - camel-core - - - org.apache.camel - camel-stream - - - junit - junit - test - - - 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 deleted file mode 100644 index d2974e20bbff..000000000000 --- a/message-channel/src/main/java/com/iluwatar/message/channel/App.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.message.channel; - -import org.apache.camel.CamelContext; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.impl.DefaultCamelContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * When two applications communicate with each other using a messaging system they first need to - * establish a communication channel that will carry the data. Message Channel decouples Message - * producers and consumers. - *

    - * The sending application doesn't necessarily know what particular application will end up - * retrieving it, but it can be assured that the application that retrieves the information is - * interested in that information. This is because the messaging system has different Message - * Channels for different types of information the applications want to communicate. When an - * application sends information, it doesn't randomly add the information to any channel available; - * it adds it to a channel whose specific purpose is to communicate that sort of information. - * Likewise, an application that wants to receive particular information doesn't pull info off some - * random channel; it selects what channel to get information from based on what type of information - * it wants. - *

    - * In this example we use Apache Camel to establish two different Message Channels. The first one - * reads from standard input and delivers messages to Direct endpoint. The second Message Channel is - * established from the Direct component to console output. No actual messages are sent, only the - * established routes are printed to standard output. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) throws Exception { - CamelContext context = new DefaultCamelContext(); - - context.addRoutes(new RouteBuilder() { - - @Override - public void configure() throws Exception { - from("stream:in").to("direct:greetings"); - from("direct:greetings").to("stream:out"); - } - }); - - context.start(); - context.getRoutes().stream().forEach(r -> LOGGER.info(r.toString())); - context.stop(); - } -} diff --git a/message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java b/message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java deleted file mode 100644 index e41977a0008b..000000000000 --- a/message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.message.channel; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/model-view-controller/README.md b/model-view-controller/README.md deleted file mode 100644 index 9907b98bddc2..000000000000 --- a/model-view-controller/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Model-View-Controller -folder: model-view-controller -permalink: /patterns/model-view-controller/ -pumlid: ROl13SCm201NQGUm-NSRQgE42h258Lw_wR-_qvtkoTOaEwNBuuoOwmNWkEl1SUOx5taR5cHHsr1WoOs13X-yi7HQV5YP645k2nJN3Q2ZavIBQPVVwqFajXJjVwdfMcUgV040 -categories: Presentation Tier -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Separate the user interface into three interconnected components: -the model, the view and the controller. Let the model manage the data, the view -display the data and the controller mediate updating the data and redrawing the -display. - -![alt text](./etc/model-view-controller.png "Model-View-Controller") - -## Applicability -Use the Model-View-Controller pattern when - -* you want to clearly separate the domain data from its user interface representation - -## Credits - -* [Trygve Reenskaug - Model-view-controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) -* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420) diff --git a/model-view-controller/etc/model-view-controller.png b/model-view-controller/etc/model-view-controller.png deleted file mode 100644 index 90071bfc134579083c83d5c4130b6bd249723aa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18130 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 diff --git a/model-view-controller/etc/model-view-controller.ucls b/model-view-controller/etc/model-view-controller.ucls deleted file mode 100644 index 80e05a7302a5..000000000000 --- a/model-view-controller/etc/model-view-controller.ucls +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/model-view-controller/etc/model-view-controller.urm.puml b/model-view-controller/etc/model-view-controller.urm.puml deleted file mode 100644 index 92ec1e949d83..000000000000 --- a/model-view-controller/etc/model-view-controller.urm.puml +++ /dev/null @@ -1,70 +0,0 @@ -@startuml -package com.iluwatar.model.view.controller { - class App { - + App() - + main(args : String[]) {static} - } - enum Fatigue { - + ALERT {static} - + SLEEPING {static} - + TIRED {static} - - title : String - + toString() : String - + valueOf(name : String) : Fatigue {static} - + values() : Fatigue[] {static} - } - class GiantController { - - giant : GiantModel - - view : GiantView - + GiantController(giant : GiantModel, view : GiantView) - + getFatigue() : Fatigue - + getHealth() : Health - + getNourishment() : Nourishment - + setFatigue(fatigue : Fatigue) - + setHealth(health : Health) - + setNourishment(nourishment : Nourishment) - + updateView() - } - class GiantModel { - - fatigue : Fatigue - - health : Health - - nourishment : Nourishment - ~ GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment) - + getFatigue() : Fatigue - + getHealth() : Health - + getNourishment() : Nourishment - + setFatigue(fatigue : Fatigue) - + setHealth(health : Health) - + setNourishment(nourishment : Nourishment) - + toString() : String - } - class GiantView { - - LOGGER : Logger {static} - + GiantView() - + displayGiant(giant : GiantModel) - } - enum Health { - + DEAD {static} - + HEALTHY {static} - + WOUNDED {static} - - title : String - + toString() : String - + valueOf(name : String) : Health {static} - + values() : Health[] {static} - } - enum Nourishment { - + HUNGRY {static} - + SATURATED {static} - + STARVING {static} - - title : String - + toString() : String - + valueOf(name : String) : Nourishment {static} - + values() : Nourishment[] {static} - } -} -GiantModel --> "-nourishment" Nourishment -GiantController --> "-giant" GiantModel -GiantModel --> "-fatigue" Fatigue -GiantModel --> "-health" Health -GiantController --> "-view" GiantView -@enduml \ No newline at end of file diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml deleted file mode 100644 index 385953d0af38..000000000000 --- a/model-view-controller/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - model-view-controller - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java deleted file mode 100644 index a2f8d7a6ebde..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * Model-View-Controller is a pattern for implementing user interfaces. It divides the application - * into three interconnected parts namely the model, the view and the controller. - *

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

    - * In this example we have a giant ({@link GiantModel}) with statuses for health, fatigue and - * nourishment. {@link GiantView} can display the giant with its current status. - * {@link GiantController} receives input affecting the model and delegates redrawing the giant to - * the view. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - // create model, view and controller - GiantModel giant = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); - GiantView view = new GiantView(); - GiantController controller = new GiantController(giant, view); - // initial display - controller.updateView(); - // controller receives some interactions that affect the giant - controller.setHealth(Health.WOUNDED); - controller.setNourishment(Nourishment.HUNGRY); - controller.setFatigue(Fatigue.TIRED); - // redisplay - controller.updateView(); - } -} diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java deleted file mode 100644 index 8c9ec44668d8..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * Fatigue enumeration - * - */ -public enum Fatigue { - - ALERT("alert"), TIRED("tired"), SLEEPING("sleeping"); - - private String title; - - Fatigue(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java deleted file mode 100644 index 2d2d7f311e82..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * GiantController can update the giant data and redraw it using the view. - * - */ -public class GiantController { - - private GiantModel giant; - private GiantView view; - - public GiantController(GiantModel giant, GiantView view) { - this.giant = giant; - this.view = view; - } - - public Health getHealth() { - return giant.getHealth(); - } - - public void setHealth(Health health) { - this.giant.setHealth(health); - } - - public Fatigue getFatigue() { - return giant.getFatigue(); - } - - public void setFatigue(Fatigue fatigue) { - this.giant.setFatigue(fatigue); - } - - public Nourishment getNourishment() { - return giant.getNourishment(); - } - - public void setNourishment(Nourishment nourishment) { - this.giant.setNourishment(nourishment); - } - - public void updateView() { - this.view.displayGiant(giant); - } -} diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java deleted file mode 100644 index 96ccfa233475..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * GiantModel contains the giant data - * - */ -public class GiantModel { - - private Health health; - private Fatigue fatigue; - private Nourishment nourishment; - - GiantModel(Health health, Fatigue fatigue, Nourishment nourishment) { - this.health = health; - this.fatigue = fatigue; - this.nourishment = nourishment; - } - - public Health getHealth() { - return health; - } - - public void setHealth(Health health) { - this.health = health; - } - - public Fatigue getFatigue() { - return fatigue; - } - - public void setFatigue(Fatigue fatigue) { - this.fatigue = fatigue; - } - - public Nourishment getNourishment() { - return nourishment; - } - - public void setNourishment(Nourishment nourishment) { - this.nourishment = nourishment; - } - - @Override - public String toString() { - return String.format("The giant looks %s, %s and %s.", health, fatigue, nourishment); - } -} 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 deleted file mode 100644 index 36beadf709d2..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * GiantView displays the giant - * - */ -public class GiantView { - - private static final Logger LOGGER = LoggerFactory.getLogger(GiantView.class); - - public void displayGiant(GiantModel giant) { - LOGGER.info(giant.toString()); - } -} diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java deleted file mode 100644 index 0adcaf99ba88..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * Health enumeration - * - */ -public enum Health { - - HEALTHY("healthy"), WOUNDED("wounded"), DEAD("dead"); - - private String title; - - Health(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java deleted file mode 100644 index 1f3e2a20fe74..000000000000 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -/** - * - * Nourishment enumeration - * - */ -public enum Nourishment { - - SATURATED("saturated"), HUNGRY("hungry"), STARVING("starving"); - - private String title; - - Nourishment(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/AppTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/AppTest.java deleted file mode 100644 index 66062faf5285..000000000000 --- a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java deleted file mode 100644 index ab9b3e0a4d0f..000000000000 --- a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -import org.junit.Test; - -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/20/15 - 2:19 PM - * - * @author Jeroen Meulemeester - */ -public class GiantControllerTest { - - /** - * Verify if the controller passes the health level through to the model and vice versa - */ - @Test - public void testSetHealth() { - final GiantModel model = mock(GiantModel.class); - final GiantView view = mock(GiantView.class); - final GiantController controller = new GiantController(model, view); - - verifyZeroInteractions(model, view); - - for (final Health health : Health.values()) { - controller.setHealth(health); - verify(model).setHealth(health); - verifyZeroInteractions(view); - } - - controller.getHealth(); - verify(model).getHealth(); - - verifyNoMoreInteractions(model, view); - } - - /** - * Verify if the controller passes the fatigue level through to the model and vice versa - */ - @Test - public void testSetFatigue() { - final GiantModel model = mock(GiantModel.class); - final GiantView view = mock(GiantView.class); - final GiantController controller = new GiantController(model, view); - - verifyZeroInteractions(model, view); - - for (final Fatigue fatigue : Fatigue.values()) { - controller.setFatigue(fatigue); - verify(model).setFatigue(fatigue); - verifyZeroInteractions(view); - } - - controller.getFatigue(); - verify(model).getFatigue(); - - verifyNoMoreInteractions(model, view); - } - - /** - * Verify if the controller passes the nourishment level through to the model and vice versa - */ - @Test - public void testSetNourishment() { - final GiantModel model = mock(GiantModel.class); - final GiantView view = mock(GiantView.class); - final GiantController controller = new GiantController(model, view); - - verifyZeroInteractions(model, view); - - for (final Nourishment nourishment : Nourishment.values()) { - controller.setNourishment(nourishment); - verify(model).setNourishment(nourishment); - verifyZeroInteractions(view); - } - - controller.getNourishment(); - verify(model).getNourishment(); - - verifyNoMoreInteractions(model, view); - } - - @Test - public void testUpdateView() { - final GiantModel model = mock(GiantModel.class); - final GiantView view = mock(GiantView.class); - final GiantController controller = new GiantController(model, view); - - verifyZeroInteractions(model, view); - - controller.updateView(); - verify(view).displayGiant(model); - - verifyNoMoreInteractions(model, view); - } - -} \ No newline at end of file diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java deleted file mode 100644 index ecf713a61189..000000000000 --- a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/20/15 - 2:10 PM - * - * @author Jeroen Meulemeester - */ -public class GiantModelTest { - - /** - * Verify if the health value is set properly though the constructor and setter - */ - @Test - public void testSetHealth() { - final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); - assertEquals(Health.HEALTHY, model.getHealth()); - for (final Health health : Health.values()) { - model.setHealth(health); - assertEquals(health, model.getHealth()); - assertEquals("The giant looks " + health.toString() + ", alert and saturated.", model.toString()); - } - } - - /** - * Verify if the fatigue level is set properly though the constructor and setter - */ - @Test - public void testSetFatigue() { - final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); - assertEquals(Fatigue.ALERT, model.getFatigue()); - for (final Fatigue fatigue : Fatigue.values()) { - model.setFatigue(fatigue); - assertEquals(fatigue, model.getFatigue()); - assertEquals("The giant looks healthy, " + fatigue.toString() + " and saturated.", model.toString()); - } - } - - /** - * Verify if the nourishment level is set properly though the constructor and setter - */ - @Test - public void testSetNourishment() { - final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); - assertEquals(Nourishment.SATURATED, model.getNourishment()); - for (final Nourishment nourishment : Nourishment.values()) { - model.setNourishment(nourishment); - assertEquals(nourishment, model.getNourishment()); - assertEquals("The giant looks healthy, alert and " + nourishment.toString() + ".", model.toString()); - } - } - -} 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 deleted file mode 100644 index ec0aabd15214..000000000000 --- a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.controller; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import java.util.LinkedList; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -/** - * Date: 12/20/15 - 2:04 PM - * - * @author Jeroen Meulemeester - */ -public class GiantViewTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(GiantView.class); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * Verify if the {@link GiantView} does what it has to do: Print the {@link GiantModel} to the - * standard out stream, nothing more, nothing less. - */ - @Test - public void testDisplayGiant() { - final GiantView view = new GiantView(); - - final GiantModel model = mock(GiantModel.class); - view.displayGiant(model); - - assertEquals(model.toString(), appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - - /** - * Logging Appender Implementation - */ - 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/model-view-presenter/README.md b/model-view-presenter/README.md deleted file mode 100644 index 04a1fa559521..000000000000 --- a/model-view-presenter/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: pattern -title: Model-View-Presenter -folder: model-view-presenter -permalink: /patterns/model-view-presenter/ -pumlid: ROlR3SGW3C1MkGu0-RzjKeXQJWcWFChwPO3xispvQBrmL0hbp-q-xGkWkFBL_8upZBICxjGzbo7GE1OwAlpmmLJ9sjNJH7VIRY1e6q169KvFevMcakrtI_BoD-HGoJE4Nm00 -categories: Presentation Tier -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Apply a "Separation of Concerns" principle in a way that allows -developers to build and test user interfaces. - -![alt text](./etc/model-view-presenter_1.png "Model-View-Presenter") - -## Applicability -Use the Model-View-Presenter in any of the following -situations - -* when you want to improve the "Separation of Concerns" principle in presentation logic -* when a user interface development and testing is necessary. - -## Real world examples - -* [MVP4J](https://github.com/amineoualialami/mvp4j) diff --git a/model-view-presenter/etc/data/test.txt b/model-view-presenter/etc/data/test.txt deleted file mode 100644 index 3f3607972b58..000000000000 --- a/model-view-presenter/etc/data/test.txt +++ /dev/null @@ -1,25 +0,0 @@ -==== - The MIT License - Copyright (c) 2014-2016 Ilkka Seppälä - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -==== - -Test line 1 -Test line 2 \ No newline at end of file diff --git a/model-view-presenter/etc/model-view-presenter.png b/model-view-presenter/etc/model-view-presenter.png deleted file mode 100644 index 71e18c4318e5203e901e5fcbde24a574161c3baf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41786 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 diff --git a/model-view-presenter/etc/model-view-presenter.ucls b/model-view-presenter/etc/model-view-presenter.ucls deleted file mode 100644 index 70e905d3f537..000000000000 --- a/model-view-presenter/etc/model-view-presenter.ucls +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/model-view-presenter/etc/model-view-presenter.urm.puml b/model-view-presenter/etc/model-view-presenter.urm.puml deleted file mode 100644 index 188b3fb4de2d..000000000000 --- a/model-view-presenter/etc/model-view-presenter.urm.puml +++ /dev/null @@ -1,87 +0,0 @@ -@startuml -package com.iluwatar.model.view.presenter { - class App { - + App() - + main(args : String[]) {static} - } - class FileLoader { - - fileName : String - - loaded : boolean - + FileLoader() - + fileExists() : boolean - + getFileName() : String - + isLoaded() : boolean - + loadData() : String - + setFileName(fileName : String) - } - class FileSelectorJFrame { - - area : JTextArea - - cancel : JButton - - contents : JLabel - - fileName : String - - info : JLabel - - input : JTextField - - ok : JButton - - panel : JPanel - - presenter : FileSelectorPresenter - - serialVersionUID : long {static} - + FileSelectorJFrame() - + actionPerformed(e : ActionEvent) - + close() - + displayData(data : String) - + getFileName() : String - + getPresenter() : FileSelectorPresenter - + isOpened() : boolean - + open() - + setFileName(name : String) - + setPresenter(presenter : FileSelectorPresenter) - + showMessage(message : String) - } - class FileSelectorPresenter { - - loader : FileLoader - - view : FileSelectorView - + FileSelectorPresenter(view : FileSelectorView) - + cancelled() - + confirmed() - + fileNameChanged() - + setLoader(loader : FileLoader) - + start() - } - class FileSelectorStub { - - dataDisplayed : boolean - - name : String - - numOfMessageSent : int - - opened : boolean - - presenter : FileSelectorPresenter - + FileSelectorStub() - + close() - + dataDisplayed() : boolean - + displayData(data : String) - + getFileName() : String - + getMessagesSent() : int - + getPresenter() : FileSelectorPresenter - + isOpened() : boolean - + open() - + setFileName(name : String) - + setPresenter(presenter : FileSelectorPresenter) - + showMessage(message : String) - } - interface FileSelectorView { - + close() {abstract} - + displayData(String) {abstract} - + getFileName() : String {abstract} - + getPresenter() : FileSelectorPresenter {abstract} - + isOpened() : boolean {abstract} - + open() {abstract} - + setFileName(String) {abstract} - + setPresenter(FileSelectorPresenter) {abstract} - + showMessage(String) {abstract} - } -} -FileSelectorStub --> "-presenter" FileSelectorPresenter -FileSelectorJFrame --> "-presenter" FileSelectorPresenter -FileSelectorPresenter --> "-loader" FileLoader -FileSelectorPresenter --> "-view" FileSelectorView -FileSelectorJFrame ..|> FileSelectorView -FileSelectorStub ..|> FileSelectorView -@enduml \ No newline at end of file diff --git a/model-view-presenter/etc/model-view-presenter_1.png b/model-view-presenter/etc/model-view-presenter_1.png deleted file mode 100644 index 6ede7bbe2fae36d8946903c1fc5f9103ff2773ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103398 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 diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml deleted file mode 100644 index 5c91846bf758..000000000000 --- a/model-view-presenter/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - model-view-presenter - model-view-presenter - http://maven.apache.org - - - junit - junit - test - - - net.java.dev.swing-layout - swing-layout - 1.0.2 - - - diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java deleted file mode 100644 index 26f16bcec177..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -/** - * - * The Model-View-Presenter(MVP) architectural pattern, helps us achieve what is called - * "The separation of concerns" principle. This is accomplished by separating the application's - * logic (Model), GUIs (View), and finally the way that the user's actions update the application's - * logic (Presenter). - *

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

    - * Finally, please notice the wiring between the Presenter and the View and between the Presenter - * and the Model. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - FileLoader loader = new FileLoader(); - FileSelectorJFrame jFrame = new FileSelectorJFrame(); - FileSelectorPresenter presenter = new FileSelectorPresenter(jFrame); - presenter.setLoader(loader); - presenter.start(); - } -} diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java deleted file mode 100644 index 5952cf5f17bd..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.Serializable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Every instance of this class represents the Model component in the Model-View-Presenter - * architectural pattern. - *

    - * It is responsible for reading and loading the contents of a given file. - */ -public class FileLoader implements Serializable { - - /** - * Generated serial version UID - */ - private static final long serialVersionUID = -4745803872902019069L; - - private static final Logger LOGGER = LoggerFactory.getLogger(FileLoader.class); - - /** - * Indicates if the file is loaded or not. - */ - private boolean loaded; - - /** - * The name of the file that we want to load. - */ - private String fileName; - - /** - * Loads the data of the file specified. - */ - public String loadData() { - String dataFileName = this.fileName; - try (BufferedReader br = new BufferedReader(new FileReader(new File(dataFileName)))) { - StringBuilder sb = new StringBuilder(); - String line; - - while ((line = br.readLine()) != null) { - sb.append(line).append('\n'); - } - - this.loaded = true; - - return sb.toString(); - } catch (Exception e) { - LOGGER.error("File {} does not exist", dataFileName); - } - - return null; - } - - /** - * Sets the path of the file to be loaded, to the given value. - * - * @param fileName The path of the file to be loaded. - */ - public void setFileName(String fileName) { - this.fileName = fileName; - } - - /** - * @return fileName The path of the file to be loaded. - */ - public String getFileName() { - return this.fileName; - } - - /** - * @return True, if the file given exists, false otherwise. - */ - public boolean fileExists() { - return new File(this.fileName).exists(); - } - - /** - * @return True, if the file is loaded, false otherwise. - */ - public boolean isLoaded() { - return this.loaded; - } -} diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java deleted file mode 100644 index b39db04a89a7..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java +++ /dev/null @@ -1,218 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -/** - * This class is the GUI implementation of the View component in the Model-View-Presenter pattern. - */ -public class FileSelectorJFrame extends JFrame implements FileSelectorView, ActionListener { - - /** - * Default serial version ID. - */ - private static final long serialVersionUID = 1L; - - /** - * The "OK" button for loading the file. - */ - private JButton ok; - - /** - * The cancel button. - */ - private JButton cancel; - - /** - * The information label. - */ - private JLabel info; - - /** - * The contents label. - */ - private JLabel contents; - - /** - * The text field for giving the name of the file that we want to open. - */ - private JTextField input; - - /** - * A text area that will keep the contents of the file opened. - */ - private JTextArea area; - - /** - * The panel that will hold our widgets. - */ - private JPanel panel; - - /** - * The Presenter component that the frame will interact with - */ - private FileSelectorPresenter presenter; - - /** - * The name of the file that we want to read it's contents. - */ - private String fileName; - - /** - * Constructor. - */ - public FileSelectorJFrame() { - super("File Loader"); - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.setLayout(null); - this.setBounds(100, 100, 500, 200); - - /* - * Add the panel. - */ - this.panel = new JPanel(); - panel.setLayout(null); - this.add(panel); - panel.setBounds(0, 0, 500, 200); - panel.setBackground(Color.LIGHT_GRAY); - - /* - * Add the info label. - */ - this.info = new JLabel("File Name :"); - this.panel.add(info); - info.setBounds(30, 10, 100, 30); - - /* - * Add the contents label. - */ - this.contents = new JLabel("File contents :"); - this.panel.add(contents); - this.contents.setBounds(30, 100, 120, 30); - - /* - * Add the text field. - */ - this.input = new JTextField(100); - this.panel.add(input); - this.input.setBounds(150, 15, 200, 20); - - /* - * Add the text area. - */ - this.area = new JTextArea(100, 100); - JScrollPane pane = new JScrollPane(area); - pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - this.panel.add(pane); - this.area.setEditable(false); - pane.setBounds(150, 100, 250, 80); - - /* - * Add the OK button. - */ - this.ok = new JButton("OK"); - this.panel.add(ok); - this.ok.setBounds(250, 50, 100, 25); - this.ok.addActionListener(this); - - /* - * Add the cancel button. - */ - this.cancel = new JButton("Cancel"); - this.panel.add(this.cancel); - this.cancel.setBounds(380, 50, 100, 25); - this.cancel.addActionListener(this); - - this.presenter = null; - this.fileName = null; - } - - @Override - public void actionPerformed(ActionEvent e) { - if (this.ok.equals(e.getSource())) { - this.fileName = this.input.getText(); - presenter.fileNameChanged(); - presenter.confirmed(); - } else if (this.cancel.equals(e.getSource())) { - presenter.cancelled(); - } - } - - @Override - public void open() { - this.setVisible(true); - } - - @Override - public void close() { - this.dispose(); - } - - @Override - public boolean isOpened() { - return this.isVisible(); - } - - @Override - public void setPresenter(FileSelectorPresenter presenter) { - this.presenter = presenter; - } - - @Override - public FileSelectorPresenter getPresenter() { - return this.presenter; - } - - @Override - public void setFileName(String name) { - this.fileName = name; - } - - @Override - public String getFileName() { - return this.fileName; - } - - @Override - public void showMessage(String message) { - JOptionPane.showMessageDialog(null, message); - } - - @Override - public void displayData(String data) { - this.area.setText(data); - } -} diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java deleted file mode 100644 index 233b1dcf73c5..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import java.io.Serializable; - -/** - * Every instance of this class represents the Presenter component in the Model-View-Presenter - * architectural pattern. - *

    - * It is responsible for reacting to the user's actions and update the View component. - */ -public class FileSelectorPresenter implements Serializable { - - /** - * Generated serial version UID - */ - private static final long serialVersionUID = 1210314339075855074L; - - /** - * The View component that the presenter interacts with. - */ - private FileSelectorView view; - - /** - * The Model component that the presenter interacts with. - */ - private FileLoader loader; - - /** - * Constructor - * - * @param view The view component that the presenter will interact with. - */ - public FileSelectorPresenter(FileSelectorView view) { - this.view = view; - } - - /** - * Sets the {@link FileLoader} object, to the value given as parameter. - * - * @param loader The new {@link FileLoader} object(the Model component). - */ - public void setLoader(FileLoader loader) { - this.loader = loader; - } - - /** - * Starts the presenter. - */ - public void start() { - view.setPresenter(this); - view.open(); - } - - /** - * An "event" that fires when the name of the file to be loaded changes. - */ - public void fileNameChanged() { - loader.setFileName(view.getFileName()); - } - - /** - * Ok button handler - */ - public void confirmed() { - if (loader.getFileName() == null || loader.getFileName().equals("")) { - view.showMessage("Please give the name of the file first!"); - return; - } - - if (loader.fileExists()) { - String data = loader.loadData(); - view.displayData(data); - } else { - view.showMessage("The file specified does not exist."); - } - } - - /** - * Cancels the file loading process. - */ - public void cancelled() { - view.close(); - } -} diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java deleted file mode 100644 index e4510eabee10..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -/** - * Every instance of this class represents the Stub component in the Model-View-Presenter - * architectural pattern. - *

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

    - * Since we can not test the GUI directly, the MVP pattern provides this functionality through the - * View's dummy implementation, the Stub. - */ -public class FileSelectorStub implements FileSelectorView { - - /** - * Indicates whether or not the view is opened. - */ - private boolean opened; - - /** - * The presenter Component. - */ - private FileSelectorPresenter presenter; - - /** - * The current name of the file. - */ - private String name; - - /** - * Indicates the number of messages that were "displayed" to the user. - */ - private int numOfMessageSent; - - /** - * Indicates if the data of the file where displayed or not. - */ - private boolean dataDisplayed; - - /** - * Constructor - */ - public FileSelectorStub() { - this.opened = false; - this.presenter = null; - this.name = ""; - this.numOfMessageSent = 0; - this.dataDisplayed = false; - } - - @Override - public void open() { - this.opened = true; - } - - @Override - public void setPresenter(FileSelectorPresenter presenter) { - this.presenter = presenter; - } - - @Override - public boolean isOpened() { - return this.opened; - } - - @Override - public FileSelectorPresenter getPresenter() { - return this.presenter; - } - - @Override - public String getFileName() { - return this.name; - } - - @Override - public void setFileName(String name) { - this.name = name; - } - - @Override - public void showMessage(String message) { - this.numOfMessageSent++; - } - - @Override - public void close() { - this.opened = false; - } - - @Override - public void displayData(String data) { - this.dataDisplayed = true; - } - - /** - * Returns the number of messages that were displayed to the user. - */ - public int getMessagesSent() { - return this.numOfMessageSent; - } - - /** - * @return True if the data where displayed, false otherwise. - */ - public boolean dataDisplayed() { - return this.dataDisplayed; - } -} diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java deleted file mode 100644 index e6ab93f66bed..000000000000 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import java.io.Serializable; - -/** - * This interface represents the View component in the Model-View-Presenter pattern. It can be - * implemented by either the GUI components, or by the Stub. - */ -public interface FileSelectorView extends Serializable { - - /** - * Opens the view. - */ - void open(); - - /** - * Closes the view. - */ - void close(); - - /** - * @return True, if the view is opened, false otherwise. - */ - boolean isOpened(); - - /** - * Sets the presenter component, to the one given as parameter. - * - * @param presenter The new presenter component. - */ - void setPresenter(FileSelectorPresenter presenter); - - /** - * @return The presenter Component. - */ - FileSelectorPresenter getPresenter(); - - /** - * Sets the file's name, to the value given as parameter. - * - * @param name The new name of the file. - */ - void setFileName(String name); - - /** - * @return The name of the file. - */ - String getFileName(); - - /** - * Displays a message to the users. - * - * @param message The message to be displayed. - */ - void showMessage(String message); - - /** - * Displays the data to the view. - * - * @param data The data to be written. - */ - void displayData(String data); -} diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java deleted file mode 100644 index 83639c0b204e..000000000000 --- a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } - -} diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java deleted file mode 100644 index 8e9a558a7538..000000000000 --- a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import org.junit.Test; - -import static org.junit.Assert.assertNull; - -/** - * Date: 12/21/15 - 12:12 PM - * - * @author Jeroen Meulemeester - */ -public class FileLoaderTest { - - @Test - public void testLoadData() throws Exception { - final FileLoader fileLoader = new FileLoader(); - fileLoader.setFileName("non-existing-file"); - assertNull(fileLoader.loadData()); - } - -} \ No newline at end of file diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java deleted file mode 100644 index 057d4dcdc48f..000000000000 --- a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.model.view.presenter; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -/** - * This test case is responsible for testing our application by taking advantage of the - * Model-View-Controller architectural pattern. - */ -public class FileSelectorPresenterTest { - - /** - * The Presenter component. - */ - private FileSelectorPresenter presenter; - - /** - * The View component, implemented this time as a Stub!!! - */ - private FileSelectorStub stub; - - /** - * The Model component. - */ - private FileLoader loader; - - /** - * Initializes the components of the test case. - */ - @Before - public void setUp() { - this.stub = new FileSelectorStub(); - this.loader = new FileLoader(); - presenter = new FileSelectorPresenter(this.stub); - presenter.setLoader(loader); - } - - /** - * Tests if the Presenter was successfully connected with the View. - */ - @Test - public void wiring() { - presenter.start(); - - assertNotNull(stub.getPresenter()); - assertTrue(stub.isOpened()); - } - - /** - * Tests if the name of the file changes. - */ - @Test - public void updateFileNameToLoader() { - String expectedFile = "Stamatis"; - stub.setFileName(expectedFile); - - presenter.start(); - presenter.fileNameChanged(); - - assertEquals(expectedFile, loader.getFileName()); - } - - /** - * Tests if we receive a confirmation when we attempt to open a file that it's name is null or an - * empty string. - */ - @Test - public void fileConfirmationWhenNameIsNull() { - stub.setFileName(null); - - presenter.start(); - presenter.fileNameChanged(); - presenter.confirmed(); - - assertFalse(loader.isLoaded()); - assertEquals(1, stub.getMessagesSent()); - } - - /** - * Tests if we receive a confirmation when we attempt to open a file that it doesn't exist. - */ - @Test - public void fileConfirmationWhenFileDoesNotExist() { - stub.setFileName("RandomName.txt"); - - presenter.start(); - presenter.fileNameChanged(); - presenter.confirmed(); - - assertFalse(loader.isLoaded()); - assertEquals(1, stub.getMessagesSent()); - } - - /** - * Tests if we can open the file, when it exists. - */ - @Test - public void fileConfirmationWhenFileExists() { - stub.setFileName("etc/data/test.txt"); - presenter.start(); - presenter.fileNameChanged(); - presenter.confirmed(); - - assertTrue(loader.isLoaded()); - assertTrue(stub.dataDisplayed()); - } - - /** - * Tests if the view closes after cancellation. - */ - @Test - public void cancellation() { - presenter.start(); - presenter.cancelled(); - - assertFalse(stub.isOpened()); - } -} diff --git a/module/README.md b/module/README.md deleted file mode 100644 index 24bd3f54358c..000000000000 --- a/module/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: pattern -title: Module -folder: module -permalink: /patterns/module/ -pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0 -categories: Creational Pattern -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -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 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. - -## Credits - -* [Module](https://en.wikipedia.org/wiki/Module_pattern) diff --git a/module/error.txt b/module/error.txt deleted file mode 100644 index ee28c3c1cf7e..000000000000 --- a/module/error.txt +++ /dev/null @@ -1,23 +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. -==== - diff --git a/module/etc/module.png b/module/etc/module.png deleted file mode 100644 index a26807d290c0d2aced42c5e5d48cf0780e9c4d2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18027 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�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 b&*xx@wCm+^Q{eyCf+Z;`E0Qa$`}Y3>Bi8;O diff --git a/module/etc/module.ucls b/module/etc/module.ucls deleted file mode 100644 index d2519b856ae5..000000000000 --- a/module/etc/module.ucls +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/module/etc/module.urm.puml b/module/etc/module.urm.puml deleted file mode 100644 index 233691cf7be7..000000000000 --- a/module/etc/module.urm.puml +++ /dev/null @@ -1,43 +0,0 @@ -@startuml -package com.iluwatar.module { - class App { - + consoleLoggerModule : ConsoleLoggerModule {static} - + fileLoggerModule : FileLoggerModule {static} - - App() - + execute(args : String[]) {static} - + main(args : String[]) {static} - + prepare() {static} - + unprepare() {static} - } - class ConsoleLoggerModule { - - LOGGER : Logger {static} - + error : PrintStream - + output : PrintStream - - singleton : ConsoleLoggerModule {static} - - ConsoleLoggerModule() - + getSingleton() : ConsoleLoggerModule {static} - + prepare() : ConsoleLoggerModule - + printErrorString(value : String) - + printString(value : String) - + unprepare() - } - class FileLoggerModule { - - ERROR_FILE : String {static} - - LOGGER : Logger {static} - - OUTPUT_FILE : String {static} - + error : PrintStream - + output : PrintStream - - singleton : FileLoggerModule {static} - - FileLoggerModule() - + getSingleton() : FileLoggerModule {static} - + prepare() : FileLoggerModule - + printErrorString(value : String) - + printString(value : String) - + unprepare() - } -} -FileLoggerModule --> "-singleton" FileLoggerModule -App --> "-consoleLoggerModule" ConsoleLoggerModule -ConsoleLoggerModule --> "-singleton" ConsoleLoggerModule -App --> "-fileLoggerModule" FileLoggerModule -@enduml \ No newline at end of file diff --git a/module/output.txt b/module/output.txt deleted file mode 100644 index ee28c3c1cf7e..000000000000 --- a/module/output.txt +++ /dev/null @@ -1,23 +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. -==== - diff --git a/module/pom.xml b/module/pom.xml deleted file mode 100644 index 1d45a77a50a2..000000000000 --- a/module/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.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 deleted file mode 100644 index 1c117722fda1..000000000000 --- a/module/src/main/java/com/iluwatar/module/App.java +++ /dev/null @@ -1,92 +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.module; - -import java.io.FileNotFoundException; - -/** - * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages - * the creation and organization of other elements, and groups them as the structural pattern does. - * An object that applies this pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with static members with - * cleaner, more concise syntax and semantics. - *

    - * The below example demonstrates a use case for testing two different modules: File Logger and - * Console Logger - * - */ -public final class App { - - public static FileLoggerModule fileLoggerModule; - public static ConsoleLoggerModule consoleLoggerModule; - - /** - * 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 { - - /* Create new singleton objects and prepare their modules */ - fileLoggerModule = FileLoggerModule.getSingleton().prepare(); - consoleLoggerModule = ConsoleLoggerModule.getSingleton().prepare(); - } - - /** - * Following method performs the finalization - */ - public static void unprepare() { - - /* Close all resources */ - fileLoggerModule.unprepare(); - consoleLoggerModule.unprepare(); - } - - /** - * 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 console */ - consoleLoggerModule.printString("Message"); - consoleLoggerModule.printErrorString("Error"); - } - - /** - * 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() {} -} diff --git a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java deleted file mode 100644 index 0efdd90338d1..000000000000 --- a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java +++ /dev/null @@ -1,106 +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.module; - -import java.io.PrintStream; - -import org.apache.log4j.Logger; - -/** - * The ConsoleLoggerModule is responsible for showing logs on System Console - *

    - * The below example demonstrates a Console logger module, which can print simple and error messages - * in two designated formats - */ -public final class ConsoleLoggerModule { - - private static final Logger LOGGER = Logger.getLogger(ConsoleLoggerModule.class); - - private static ConsoleLoggerModule singleton = null; - - public PrintStream output = null; - public PrintStream error = null; - - private ConsoleLoggerModule() {} - - /** - * 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(); - } - - return ConsoleLoggerModule.singleton; - } - - /** - * Following method performs the initialization - */ - public ConsoleLoggerModule prepare() { - - LOGGER.debug("ConsoleLoggerModule::prepare();"); - - this.output = new PrintStream(System.out); - this.error = new PrintStream(System.err); - - return this; - } - - /** - * Following method performs the finalization - */ - public 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();"); - } - - /** - * Used to print a message - * - * @param value will be printed on console - */ - public void printString(final String value) { - this.output.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 deleted file mode 100644 index e80444dabb86..000000000000 --- a/module/src/main/java/com/iluwatar/module/FileLoggerModule.java +++ /dev/null @@ -1,114 +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.module; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; - -import org.apache.log4j.Logger; - -/** - * The FileLoggerModule is responsible for showing logs on File System - *

    - * The below example demonstrates a File logger module, which can print simple and error messages in - * two designated files - */ -public final class FileLoggerModule { - - private static final Logger LOGGER = Logger.getLogger(FileLoggerModule.class); - - private static FileLoggerModule singleton = null; - - private static final String OUTPUT_FILE = "output.txt"; - private static final String ERROR_FILE = "error.txt"; - - public PrintStream output = null; - public PrintStream error = null; - - private FileLoggerModule() {} - - /** - * 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(); - } - - return FileLoggerModule.singleton; - } - - /** - * Following method performs the initialization - * - * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) - */ - public FileLoggerModule prepare() throws FileNotFoundException { - - LOGGER.debug("FileLoggerModule::prepare();"); - - this.output = new PrintStream(new FileOutputStream(OUTPUT_FILE)); - this.error = new PrintStream(new FileOutputStream(ERROR_FILE)); - - return this; - } - - /** - * Following method performs the finalization - */ - public void unprepare() { - - if (this.output != null) { - - this.output.flush(); - this.output.close(); - } - - if (this.error != null) { - - this.error.flush(); - this.error.close(); - } - - LOGGER.debug("FileLoggerModule::unprepare();"); - } - - /** - * Used to print a message - * - * @param value will be printed in file - */ - public void printString(final String value) { - this.output.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/main/resources/log4j.xml b/module/src/main/resources/log4j.xml deleted file mode 100644 index b591c17e1665..000000000000 --- a/module/src/main/resources/log4j.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - \ 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 deleted file mode 100644 index 5df6ab0f3870..000000000000 --- a/module/src/test/java/com/iluwatar/module/AppTest.java +++ /dev/null @@ -1,37 +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.module; - -import java.io.FileNotFoundException; - -import com.iluwatar.module.App; - -import org.junit.Test; - -/** - * Tests that Module 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/FileLoggerModuleTest.java b/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java deleted file mode 100644 index 7274aab14e5a..000000000000 --- a/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java +++ /dev/null @@ -1,182 +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.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 testFileMessage() 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 testNoFileMessage() 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 testFileErrorMessage() 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 testNoFileErrorMessage() 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/monad/README.md b/monad/README.md deleted file mode 100644 index bf6ee58b891e..000000000000 --- a/monad/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: pattern -title: Monad -folder: monad -permalink: /patterns/monad/ -pumlid: 9SR13SCm20NGLPe1OkxTXjWeSMMm1Pza_LRgExsjMntP97syBc35cyZvAMV7bKU6U9q6CPGwbVh8Xy5E7xvvRnBzj7qn86v1ol4BwJHk9AZ_bNGjAtLy0G00 -categories: Other -tags: - - Java - - Difficulty-Expert - - Functional ---- - -## Intent - -Monad pattern based on monad from linear algebra represents the way of chaining operations -together step by step. Binding functions can be described as passing one's output to another's input -basing on the 'same type' contract. Formally, monad consists of a type constructor M and two -operations: -bind - that takes monadic object and a function from plain object to monadic value and returns monadic value -return - that takes plain type object and returns this object wrapped in a monadic value. - -![alt text](./etc/monad.png "Monad") - -## Applicability - -Use the Monad in any of the following situations - -* when you want to chain operations easily -* when you want to apply each function regardless of the result of any of them - -## Credits - -* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU) -* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads) -* [Monad on Wikipedia](https://en.wikipedia.org/wiki/Monad_(functional_programming)) \ No newline at end of file diff --git a/monad/etc/monad.png b/monad/etc/monad.png deleted file mode 100644 index f82e7a3e45ccd594685571d1e9ed30299fcef93f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32962 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 U?!x_Rm{+kR#bj@0i0C}|Klp&`K>z>% diff --git a/monad/etc/monad.ucls b/monad/etc/monad.ucls deleted file mode 100644 index 9c98df7c6331..000000000000 --- a/monad/etc/monad.ucls +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/monad/etc/monad.urm.puml b/monad/etc/monad.urm.puml deleted file mode 100644 index c9dcc8db664f..000000000000 --- a/monad/etc/monad.urm.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml -package com.iluwatar.monad { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - enum Sex { - + FEMALE {static} - + MALE {static} - + valueOf(name : String) : Sex {static} - + values() : Sex[] {static} - } - class User { - - age : int - - email : String - - name : String - - sex : Sex - + User(name : String, age : int, sex : Sex, email : String) - + getAge() : int - + getEmail() : String - + getName() : String - + getSex() : Sex - } - class Validator { - - exceptions : List - - t : T - - Validator(t : T) - + get() : T - + of(t : T) : Validator {static} - + validate(projection : Function, validation : Predicate, message : String) : Validator - + validate(validation : Predicate, message : String) : Validator - } -} -User --> "-sex" Sex -@enduml \ No newline at end of file diff --git a/monad/pom.xml b/monad/pom.xml deleted file mode 100644 index 26cb21b979a9..000000000000 --- a/monad/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - monad - - - junit - junit - test - - - - diff --git a/monad/src/main/java/com/iluwatar/monad/App.java b/monad/src/main/java/com/iluwatar/monad/App.java deleted file mode 100644 index 9b1ed5096ac4..000000000000 --- a/monad/src/main/java/com/iluwatar/monad/App.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * The Monad pattern defines a monad structure, that enables chaining operations - * in pipelines and processing data step by step. - * Formally, monad consists of a type constructor M and two operations: - *
    bind - that takes monadic object and a function from plain object to the - * monadic value and returns monadic value. - *
    return - that takes plain type object and returns this object wrapped in a monadic value. - *

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

    As a validation result {@link Validator#get()} it either returns valid object {@link Validator#t} - * or throws a list of exceptions {@link Validator#exceptions} collected during validation. - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point. - * - * @param args @param args command line args - */ - public static void main(String[] args) { - User user = new User("user", 24, Sex.FEMALE, "foobar.com"); - 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/monad/src/main/java/com/iluwatar/monad/Sex.java b/monad/src/main/java/com/iluwatar/monad/Sex.java deleted file mode 100644 index 6c6d6eff62ff..000000000000 --- a/monad/src/main/java/com/iluwatar/monad/Sex.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monad; - -/** - * Enumeration of Types of Sex - */ -public enum Sex { - MALE, FEMALE -} diff --git a/monad/src/main/java/com/iluwatar/monad/User.java b/monad/src/main/java/com/iluwatar/monad/User.java deleted file mode 100644 index 406407fea0c4..000000000000 --- a/monad/src/main/java/com/iluwatar/monad/User.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monad; - -/** - * User Definition - */ -public class User { - - private String name; - private int age; - private Sex sex; - private String email; - - /** - * @param name - name - * @param age - age - * @param sex - sex - * @param email - email address - */ - public User(String name, int age, Sex sex, String email) { - this.name = name; - this.age = age; - this.sex = sex; - this.email = email; - } - - public String getName() { - return name; - } - - public int getAge() { - return age; - } - - public Sex getSex() { - return sex; - } - - public String getEmail() { - return email; - } -} diff --git a/monad/src/main/java/com/iluwatar/monad/Validator.java b/monad/src/main/java/com/iluwatar/monad/Validator.java deleted file mode 100644 index 13e87b7f51bc..000000000000 --- a/monad/src/main/java/com/iluwatar/monad/Validator.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monad; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Class representing Monad design pattern. Monad is a way of chaining operations on the - * given object together step by step. In Validator each step results in either success or - * failure indicator, giving a way of receiving each of them easily and finally getting - * validated object or list of exceptions. - * - * @param Placeholder for an object. - */ -public class Validator { - /** - * Object that is validated - */ - private final T t; - - /** - * List of exception thrown during validation. - */ - private final List exceptions = new ArrayList<>(); - - /** - * Creates a monadic value of given object. - * @param t object to be validated - */ - private Validator(T t) { - this.t = t; - } - - /** - * Creates validator against given object - * - * @param t object to be validated - * @param object's type - * @return new instance of a validator - */ - public static Validator of(T t) { - return new Validator<>(Objects.requireNonNull(t)); - } - - /** - * @param validation one argument boolean-valued function that - * represents one step of validation. Adds exception to main validation exception - * list when single step validation ends with failure. - * @param message error message when object is invalid - * @return this - */ - public Validator validate(Predicate validation, String message) { - if (!validation.test(t)) { - exceptions.add(new IllegalStateException(message)); - } - return this; - } - - /** - * Extension for the {@link Validator#validate(Function, Predicate, String)} method, - * dedicated for objects, that need to be projected before requested validation. - * - * @param projection function that gets an objects, and returns projection representing - * element to be validated. - * @param validation see {@link Validator#validate(Function, Predicate, String)} - * @param message see {@link Validator#validate(Function, Predicate, String)} - * @param see {@link Validator#validate(Function, Predicate, String)} - * @return this - */ - public Validator validate(Function projection, Predicate validation, - String message) { - return validate(projection.andThen(validation::test)::apply, message); - } - - /** - * Receives validated object or throws exception when invalid. - * - * @return object that was validated - * @throws IllegalStateException when any validation step results with failure - */ - public T get() throws IllegalStateException { - if (exceptions.isEmpty()) { - return t; - } - IllegalStateException e = new IllegalStateException(); - exceptions.forEach(e::addSuppressed); - throw e; - } -} diff --git a/monad/src/test/java/com/iluwatar/monad/AppTest.java b/monad/src/test/java/com/iluwatar/monad/AppTest.java deleted file mode 100644 index 69464ff87d44..000000000000 --- a/monad/src/test/java/com/iluwatar/monad/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monad; - -import org.junit.Test; - -/** - * Application Test - */ -public class AppTest { - - @Test - public void testMain() { - String[] args = {}; - App.main(args); - } - -} diff --git a/monad/src/test/java/com/iluwatar/monad/MonadTest.java b/monad/src/test/java/com/iluwatar/monad/MonadTest.java deleted file mode 100644 index a34243978864..000000000000 --- a/monad/src/test/java/com/iluwatar/monad/MonadTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monad; - - -import junit.framework.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.Objects; - -/** - * Test for Monad Pattern - */ -public class MonadTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void testForInvalidName() { - thrown.expect(IllegalStateException.class); - User tom = new User(null, 21, Sex.MALE, "tom@foo.bar"); - Validator.of(tom).validate(User::getName, Objects::nonNull, "name cannot be null").get(); - } - - @Test - public void testForInvalidAge() { - thrown.expect(IllegalStateException.class); - User john = new User("John", 17, Sex.MALE, "john@qwe.bar"); - Validator.of(john).validate(User::getName, Objects::nonNull, "name cannot be null") - .validate(User::getAge, age -> age > 21, "user is underaged") - .get(); - } - - @Test - public void testForValid() { - User sarah = new User("Sarah", 42, Sex.FEMALE, "sarah@det.org"); - User validated = Validator.of(sarah).validate(User::getName, Objects::nonNull, "name cannot be null") - .validate(User::getAge, age -> age > 21, "user is underaged") - .validate(User::getSex, sex -> sex == Sex.FEMALE, "user is not female") - .validate(User::getEmail, email -> email.contains("@"), "email does not contain @ sign") - .get(); - Assert.assertSame(validated, sarah); - } -} diff --git a/monostate/README.md b/monostate/README.md deleted file mode 100644 index 8c47b5da4d2e..000000000000 --- a/monostate/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: pattern -title: MonoState -folder: monostate -permalink: /patterns/monostate/ -pumlid: HSV14OGm20NGLjO23FVj1YEZsGaa0nzjVxrvUszfLdlkaju_9p3ZI-HybwFXp2r3l0w364eTIgtdpM2d7r-yxXBji7Ko86v1ol60TDW8C8G4zLr9rp9J-ny0 -categories: Creational -tags: - - Java - - Difficulty-Beginner ---- - -## Also known as -Borg - -## Intent -Enforces a behaviour like sharing the same state amongst all instances. - -![alt text](./etc/monostate.png "MonoState") - -## Applicability -Use the Monostate pattern when - -* The same state must be shared across all instances of a class. -* Typically this pattern might be used everywhere a Singleton might be used. Singleton usage however is not transparent, Monostate usage is. -* Monostate has one major advantage over singleton. The subclasses might decorate the shared state as they wish and hence can provide dynamically different behaviour than the base class. - -## Typical Use Case - -* the logging class -* managing a connection to a database -* file manager - -## Real world examples - -Yet to see this. diff --git a/monostate/etc/MonoState.ucls b/monostate/etc/MonoState.ucls deleted file mode 100644 index 76b48ad0fa2a..000000000000 --- a/monostate/etc/MonoState.ucls +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/monostate/etc/monostate.png b/monostate/etc/monostate.png deleted file mode 100644 index 273fa95459d4d0853c58bfa25cb6e1117fd48032..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16526 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 lB1^Ap5DW=7cfNYWCnbDHap(Cm_ {static} - + LoadBalancer() - + addServer(server : Server) - + getLastServedId() : int {static} - + getNoOfServers() : int - + serverRequest(request : Request) - } - class Request { - + value : String - + Request(value : String) - } - class Server { - - LOGGER : Logger {static} - + host : String - + id : int - + port : int - + Server(host : String, port : int, id : int) - + getHost() : String - + getPort() : int - + serve(request : Request) - } -} -LoadBalancer --> "-servers" Server -@enduml \ No newline at end of file diff --git a/monostate/pom.xml b/monostate/pom.xml deleted file mode 100644 index c4dc213da287..000000000000 --- a/monostate/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - monostate - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/monostate/src/main/java/com/iluwatar/monostate/App.java b/monostate/src/main/java/com/iluwatar/monostate/App.java deleted file mode 100644 index e84bb43ad623..000000000000 --- a/monostate/src/main/java/com/iluwatar/monostate/App.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monostate; - - - -/** - * - * The MonoState pattern ensures that all instances of the class will have the same state. This can - * be used a direct replacement of the Singleton pattern. - * - *

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

    - * . - * - */ -public class App { - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - LoadBalancer loadBalancer1 = new LoadBalancer(); - LoadBalancer loadBalancer2 = new LoadBalancer(); - loadBalancer1.serverRequest(new Request("Hello")); - loadBalancer2.serverRequest(new Request("Hello World")); - } - -} diff --git a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java deleted file mode 100644 index e440dfba22d6..000000000000 --- a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monostate; - -import java.util.ArrayList; -import java.util.List; - -/** - * The LoadBalancer class. This implements the MonoState pattern. It holds a series of servers. Upon - * receiving a new Request, it delegates the call to the servers in a Round Robin Fashion. Since all - * instances of the class share the same state, all instances will delegate to the same server on - * receiving a new Request. - * - */ - -public class LoadBalancer { - private static List servers = new ArrayList<>(); - private static int id; - private static int lastServedId; - - static { - servers.add(new Server("localhost", 8081, ++id)); - servers.add(new Server("localhost", 8080, ++id)); - servers.add(new Server("localhost", 8082, ++id)); - servers.add(new Server("localhost", 8083, ++id)); - servers.add(new Server("localhost", 8084, ++id)); - } - - /** - * Add new server - */ - public final void addServer(Server server) { - synchronized (servers) { - servers.add(server); - } - - } - - public final int getNoOfServers() { - return servers.size(); - } - - public static int getLastServedId() { - return lastServedId; - } - - /** - * Handle request - */ - public void serverRequest(Request request) { - if (lastServedId >= servers.size()) { - lastServedId = 0; - } - Server server = servers.get(lastServedId++); - server.serve(request); - } - - - -} diff --git a/monostate/src/main/java/com/iluwatar/monostate/Request.java b/monostate/src/main/java/com/iluwatar/monostate/Request.java deleted file mode 100644 index 36b8e11a192b..000000000000 --- a/monostate/src/main/java/com/iluwatar/monostate/Request.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monostate; - -/** - * - * The Request class. A {@link Server} can handle an instance of a Request. - * - */ - -public class Request { - public final String value; - - public Request(String value) { - this.value = value; - } -} diff --git a/monostate/src/main/java/com/iluwatar/monostate/Server.java b/monostate/src/main/java/com/iluwatar/monostate/Server.java deleted file mode 100644 index 6b98d11e165a..000000000000 --- a/monostate/src/main/java/com/iluwatar/monostate/Server.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * in a simplistic Round Robin fashion. - * - */ -public class Server { - - private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); - - public final String host; - public final int port; - public final int id; - - /** - * Constructor - */ - public Server(String host, int port, int id) { - this.host = host; - this.port = port; - this.id = id; - } - - public String getHost() { - return host; - } - - public int getPort() { - return port; - } - - public void serve(Request request) { - LOGGER.info("Server ID {} associated to host : {} and port {}. Processed request with value {}", - id, host, port, request.value); - } -} diff --git a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java deleted file mode 100644 index 3e88b3bf2874..000000000000 --- a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monostate; - -import org.junit.Test; - -/** - * Application Test Entry - */ -public class AppTest { - - @Test - public void testMain() { - String[] args = {}; - App.main(args); - } - -} diff --git a/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java b/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java deleted file mode 100644 index 96b4830c78d7..000000000000 --- a/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.monostate; - -import org.junit.Assert; -import org.junit.Test; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - -/** - * Date: 12/21/15 - 12:26 PM - * - * @author Jeroen Meulemeester - */ -public class LoadBalancerTest { - - @Test - public void testSameStateAmongstAllInstances() { - final LoadBalancer firstBalancer = new LoadBalancer(); - final LoadBalancer secondBalancer = new LoadBalancer(); - firstBalancer.addServer(new Server("localhost", 8085, 6)); - // Both should have the same number of servers. - Assert.assertTrue(firstBalancer.getNoOfServers() == secondBalancer.getNoOfServers()); - // Both Should have the same LastServedId - Assert.assertTrue(firstBalancer.getLastServedId() == secondBalancer.getLastServedId()); - } - - @Test - public void testServe() { - final Server server = mock(Server.class); - when(server.getHost()).thenReturn("testhost"); - when(server.getPort()).thenReturn(1234); - doNothing().when(server).serve(any(Request.class)); - - final LoadBalancer loadBalancer = new LoadBalancer(); - loadBalancer.addServer(server); - - verifyZeroInteractions(server); - - final Request request = new Request("test"); - for (int i = 0; i < loadBalancer.getNoOfServers() * 2; i++) { - loadBalancer.serverRequest(request); - } - - verify(server, times(2)).serve(request); - verifyNoMoreInteractions(server); - - } - -} diff --git a/multiton/README.md b/multiton/README.md deleted file mode 100644 index a1154e7bb945..000000000000 --- a/multiton/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: pattern -title: Multiton -folder: multiton -permalink: /patterns/multiton/ -pumlid: FST14i8m20NGg-W16lRUXgPCYnD81Zxs-hfozzvJlOywf68yBc3bYoZuRgVYghrIea-7E5gVHZhgPd3Gcp-y7P9w-hOOaF0au_o1h0OKqqdG_saLrbRP-080 -categories: Creational -tags: - - Java - - Difficulty-Beginner ---- - -## Also known as -Registry - -## Intent -Ensure a class only has limited number of instances, and provide a -global point of access to them. - -![alt text](./etc/multiton.png "Multiton") - -## Applicability -Use the Multiton pattern when - -* there must be specific number of instances of a class, and they must be accessible to clients from a well-known access point diff --git a/multiton/etc/multiton.png b/multiton/etc/multiton.png deleted file mode 100644 index 91106463d2b23ab568fe2634c9742a378e16942f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10637 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 QKeN0gC#5Kf5ZCki4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/multiton/etc/multiton.urm.puml b/multiton/etc/multiton.urm.puml deleted file mode 100644 index 63a74b1f1f74..000000000000 --- a/multiton/etc/multiton.urm.puml +++ /dev/null @@ -1,30 +0,0 @@ -@startuml -package com.iluwatar.multiton { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Nazgul { - - name : NazgulName - - nazguls : Map {static} - - Nazgul(name : NazgulName) - + getInstance(name : NazgulName) : Nazgul {static} - + getName() : NazgulName - } - enum NazgulName { - + ADUNAPHEL {static} - + AKHORAHIL {static} - + DWAR {static} - + HOARMURATH {static} - + JI_INDUR {static} - + KHAMUL {static} - + MURAZOR {static} - + REN {static} - + UVATHA {static} - + valueOf(name : String) : NazgulName {static} - + values() : NazgulName[] {static} - } -} -Nazgul --> "-name" NazgulName -@enduml \ No newline at end of file diff --git a/multiton/pom.xml b/multiton/pom.xml deleted file mode 100644 index af75e5ebecf1..000000000000 --- a/multiton/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - multiton - - - junit - junit - test - - - diff --git a/multiton/src/main/java/com/iluwatar/multiton/App.java b/multiton/src/main/java/com/iluwatar/multiton/App.java deleted file mode 100644 index 28b89e6ab4ac..000000000000 --- a/multiton/src/main/java/com/iluwatar/multiton/App.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.multiton; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Whereas Singleton design pattern introduces single globally accessible object the Multiton - * pattern defines many globally accessible objects. The client asks for the correct instance from - * the Multiton by passing an enumeration as parameter. - *

    - * In this example {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using - * {@link NazgulName}. The {@link Nazgul}s are statically initialized and stored in concurrent hash - * map. - * - */ -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) { - 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/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java b/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java deleted file mode 100644 index bfb068b7a14a..000000000000 --- a/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.multiton; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * - * Nazgul is a Multiton class. Nazgul instances can be queried using {@link #getInstance} method. - * - */ -public final class Nazgul { - - private static Map nazguls; - - private NazgulName name; - - static { - nazguls = new ConcurrentHashMap<>(); - nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL)); - nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR)); - nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR)); - nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR)); - nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL)); - nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH)); - nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL)); - nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN)); - nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA)); - } - - private Nazgul(NazgulName name) { - this.name = name; - } - - public static Nazgul getInstance(NazgulName name) { - return nazguls.get(name); - } - - public NazgulName getName() { - return name; - } -} diff --git a/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java b/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java deleted file mode 100644 index 97d664e3c8d3..000000000000 --- a/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.multiton; - -/** - * - * Each Nazgul has different {@link NazgulName}. - * - */ -public enum NazgulName { - - KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA; - -} diff --git a/multiton/src/test/java/com/iluwatar/multiton/AppTest.java b/multiton/src/test/java/com/iluwatar/multiton/AppTest.java deleted file mode 100644 index 370a2665b3f3..000000000000 --- a/multiton/src/test/java/com/iluwatar/multiton/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.multiton; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java b/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java deleted file mode 100644 index ad10a9eb0eb0..000000000000 --- a/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.multiton; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; - -/** - * Date: 12/22/15 - 22:28 AM - * - * @author Jeroen Meulemeester - */ -public class NazgulTest { - - /** - * Verify if {@link Nazgul#getInstance(NazgulName)} returns the correct Nazgul multiton instance - */ - @Test - public void testGetInstance() { - for (final NazgulName name : NazgulName.values()) { - final Nazgul nazgul = Nazgul.getInstance(name); - assertNotNull(nazgul); - assertSame(nazgul, Nazgul.getInstance(name)); - assertEquals(name, nazgul.getName()); - } - } - -} diff --git a/mute-idiom/README.md b/mute-idiom/README.md deleted file mode 100644 index 5c3dbf10b9af..000000000000 --- a/mute-idiom/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Mute Idiom -folder: mute-idiom -permalink: /patterns/mute-idiom/ -pumlid: JSf13iCm20NHgxG7iDdtDjH62PKX5luarq-MtSsJvgtUHdR96AyTcEj357pLJR7dDvT4EnpYgEqmqf4NWuD-V7BfidJpCXcGy4N6wmcoX1Jj-lo2ziUQONMcZHi0 -categories: Other -tags: - - Java - - Difficulty-Beginner - - Idiom ---- - -## Intent -Provide a template to suppress any exceptions that either are declared but cannot occur or should only be logged; -while executing some business logic. The template removes the need to write repeated `try-catch` blocks. - - -![alt text](./etc/mute-idiom.png "Mute Idiom") - -## Applicability -Use this idiom when - -* an API declares some exception but can never throw that exception eg. ByteArrayOutputStream bulk write method. -* you need to suppress some exception just by logging it, such as closing a resource. - -## Credits - -* [JOOQ: Mute Design Pattern](http://blog.jooq.org/2016/02/18/the-mute-design-pattern/) diff --git a/mute-idiom/etc/mute-idiom.png b/mute-idiom/etc/mute-idiom.png deleted file mode 100644 index 203bdafc4e6873916f3d3c85f375eeba29622ca6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18505 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 W?6hzCios6=-H{ZN6D=0j^Zp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mute-idiom/etc/mute-idiom.urm.puml b/mute-idiom/etc/mute-idiom.urm.puml deleted file mode 100644 index 32d036bc8144..000000000000 --- a/mute-idiom/etc/mute-idiom.urm.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml -package com.iluwatar.mute { - class App { - - LOGGER : Logger {static} - + App() - - acquireResource() : Resource {static} - - closeResource(resource : Resource) {static} - + main(args : String[]) {static} - - useOfLoggedMute() {static} - - useOfMute() {static} - - utilizeResource(resource : Resource) {static} - } - interface CheckedRunnable { - + run() {abstract} - } - class Mute { - - Mute() - + loggedMute(runnable : CheckedRunnable) {static} - + mute(runnable : CheckedRunnable) {static} - } - interface Resource { - } -} -@enduml \ No newline at end of file diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml deleted file mode 100644 index 41d660c738ce..000000000000 --- a/mute-idiom/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - mute-idiom - - - junit - junit - test - - - diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java deleted file mode 100644 index c35559dcd97f..000000000000 --- a/mute-idiom/src/main/java/com/iluwatar/mute/App.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.mute; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.sql.SQLException; - -/** - * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in - * situation when all we can do to handle the exception is to log it. - * This pattern should not be used everywhere. It is very important to logically handle the - * exceptions in a system, but some situations like the ones described above require this pattern, - * so that we don't need to repeat - *

    - * 
    - *   try {
    - *     // code that may throwing exception we need to ignore or may never be thrown
    - *   } catch (Exception ex) {
    - *     // ignore by logging or throw error if unexpected exception occurs
    - *   }
    - * 
    - * 
    every time we need to ignore an exception. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point. - * - * @param args command line args. - * @throws Exception if any exception occurs - */ - public static void main(String[] args) throws Exception { - - useOfLoggedMute(); - - useOfMute(); - } - - /* - * Typically used when the API declares some exception but cannot do so. Usually a - * signature mistake.In this example out is not supposed to throw exception as it is a - * ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected - * exception occurs. - */ - private static void useOfMute() { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Mute.mute(() -> out.write("Hello".getBytes())); - } - - private static void useOfLoggedMute() throws SQLException { - Resource resource = null; - try { - resource = acquireResource(); - utilizeResource(resource); - } finally { - closeResource(resource); - } - } - - /* - * All we can do while failed close of a resource is to log it. - */ - private static void closeResource(Resource resource) { - Mute.loggedMute(() -> resource.close()); - } - - private static void utilizeResource(Resource resource) throws SQLException { - LOGGER.info("Utilizing acquired resource: {}", resource); - } - - private static Resource acquireResource() throws SQLException { - return new Resource() { - - @Override - public void close() throws IOException { - throw new IOException("Error in closing resource: " + this); - } - }; - } -} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java deleted file mode 100644 index 7a37ef03dfe0..000000000000 --- a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.mute; - -/** - * A runnable which may throw exception on execution. - * - */ -@FunctionalInterface -public interface CheckedRunnable { - /** - * Same as {@link Runnable#run()} with a possibility of exception in execution. - * @throws Exception if any exception occurs. - */ - void run() throws Exception; -} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java deleted file mode 100644 index d5d9b802849f..000000000000 --- a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mute; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -/** - * A utility class that allows you to utilize mute idiom. - */ -public final class Mute { - - // The constructor is never meant to be called. - private Mute() {} - - /** - * Executes the runnable and throws the exception occurred within a {@link AssertionError}. - * This method should be utilized to mute the operations that are guaranteed not to throw an exception. - * For instance {@link ByteArrayOutputStream#write(byte[])} declares in it's signature that it can throw - * an {@link IOException}, but in reality it cannot. This is because the bulk write method is not overridden - * in {@link ByteArrayOutputStream}. - * - * @param runnable a runnable that should never throw an exception on execution. - */ - public static void mute(CheckedRunnable runnable) { - try { - runnable.run(); - } catch (Exception e) { - throw new AssertionError(e); - } - } - - /** - * Executes the runnable and logs the exception occurred on {@link System#err}. - * This method should be utilized to mute the operations about which most you can do is log. - * For instance while closing a connection to database, or cleaning up a resource, - * all you can do is log the exception occurred. - * - * @param runnable a runnable that may throw an exception on execution. - */ - public static void loggedMute(CheckedRunnable runnable) { - try { - runnable.run(); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java deleted file mode 100644 index 11bb3a6ec875..000000000000 --- a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.mute; - -import java.io.Closeable; - -/** - * Represents any resource that the application might acquire and that must be closed - * after it is utilized. Example of such resources can be a database connection, open - * files, sockets. - */ -public interface Resource extends Closeable { - -} diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java deleted file mode 100644 index 8534ff2ad193..000000000000 --- a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.mute; - -import org.junit.Test; - -/** - * Tests that Mute idiom example runs without errors. - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - App.main(null); - } -} diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java deleted file mode 100644 index 7e1d2e1afb4e..000000000000 --- a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.mute; - -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Test for the mute-idiom pattern - */ -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(); - - @Test - public void muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { - Mute.mute(() -> methodNotThrowingAnyException()); - } - - @Test - public void muteShouldRethrowUnexpectedExceptionAsAssertionError() throws Exception { - exception.expect(AssertionError.class); - exception.expectMessage(MESSAGE); - - Mute.mute(() -> methodThrowingException()); - } - - @Test - public void loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { - Mute.loggedMute(() -> methodNotThrowingAnyException()); - } - - @Test - public void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - System.setErr(new PrintStream(stream)); - - Mute.loggedMute(() -> methodThrowingException()); - - assertTrue(new String(stream.toByteArray()).contains(MESSAGE)); - } - - - private void methodNotThrowingAnyException() { - LOGGER.info("Executed successfully"); - } - - private void methodThrowingException() throws Exception { - throw new Exception(MESSAGE); - } -} diff --git a/mutex/README.md b/mutex/README.md deleted file mode 100644 index 78cda9060de9..000000000000 --- a/mutex/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: Mutex -folder: mutex -permalink: /patterns/mutex/ -pumlid: 9SR13OCm30NGLSe0n7UsCS62LB69x6zWV2hrdTxKhFRS9Br_3c34GkHybxtXo3L3l9u6CPHwAhMUDuETldpnl4cqtUR1WBW5ASSlf0bvI53_A-bQHcf_0G00 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate ---- - -## Also known as -Mutual Exclusion Lock -Binary Semaphore - -## Intent -Create a lock which only allows a single thread to access a resource at any one instant. - -![alt text](./etc/mutex.png "Mutex") - -## Applicability -Use a Mutex when - -* you need to prevent two threads accessing a critical section at the same time -* concurrent access to a resource could lead to a race condition - -## Credits - -* [Lock (computer science)] (http://en.wikipedia.org/wiki/Lock_(computer_science)) -* [Semaphores] (http://tutorials.jenkov.com/java-concurrency/semaphores.html) diff --git a/mutex/etc/mutex.png b/mutex/etc/mutex.png deleted file mode 100644 index 3b7c966f87dffab72c65a77c2578c801086f7d9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12737 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 VGkgbka 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 RF7OUbSwT&{Qq~OqKL9K>lx6?` diff --git a/mutex/etc/mutex.urm.puml b/mutex/etc/mutex.urm.puml deleted file mode 100644 index 08cf43b90795..000000000000 --- a/mutex/etc/mutex.urm.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -package com.iluwatar.mutex { - class App { - + App() - + main(args : String[]) {static} - } - class Jar { - - beans : int - - lock : Lock - + Jar(beans : int, lock : Lock) - + takeBean() : boolean - } - interface Lock { - + acquire() {abstract} - + release() {abstract} - } - class Mutex { - - owner : Object - + Mutex() - + acquire() - + getOwner() : Object - + release() - } -} -Jar --> "-lock" Lock -Mutex ..|> Lock -@enduml \ No newline at end of file diff --git a/mutex/pom.xml b/mutex/pom.xml deleted file mode 100644 index ff938604b48b..000000000000 --- a/mutex/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - mutex - - - junit - junit - test - - - diff --git a/mutex/src/main/java/com/iluwatar/mutex/App.java b/mutex/src/main/java/com/iluwatar/mutex/App.java deleted file mode 100644 index e31e8f4bc799..000000000000 --- a/mutex/src/main/java/com/iluwatar/mutex/App.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -/** - * A Mutex prevents multiple threads from accessing a resource simultaneously. - *

    - * In this example we have two thieves who are taking beans from a jar. - * Only one thief can take a bean at a time. This is ensured by a Mutex lock - * which must be acquired in order to access the jar. Each thief attempts to - * acquire the lock, take a bean and then release the lock. If the lock has - * already been acquired, the thief will be prevented from continuing (blocked) - * until the lock has been released. The thieves stop taking beans once there - * are no beans left to take. - */ -public class App { - - /** - * main method - */ - public static void main(String[] args) { - Mutex mutex = new Mutex(); - Jar jar = new Jar(1000, mutex); - Thief peter = new Thief("Peter", jar); - Thief john = new Thief("John", jar); - peter.start(); - john.start(); - } - -} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Jar.java b/mutex/src/main/java/com/iluwatar/mutex/Jar.java deleted file mode 100644 index 17e6f4c1e150..000000000000 --- a/mutex/src/main/java/com/iluwatar/mutex/Jar.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -/** - * A Jar has a resource of beans which can only be accessed by a single Thief - * (thread) at any one time. A Mutex lock is used to prevent more than one Thief - * taking a bean simultaneously. - */ -public class Jar { - - /** - * The lock which must be acquired to access the beans resource. - */ - private final Lock lock; - - /** - * The resource within the jar. - */ - private int beans; - - public Jar(int beans, Lock lock) { - this.beans = beans; - this.lock = lock; - } - - /** - * Method for a thief to take a bean. - */ - public boolean takeBean() { - boolean success = false; - try { - lock.acquire(); - success = beans > 0; - if (success) { - beans = beans - 1; - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - lock.release(); - } - - return success; - } - -} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Lock.java b/mutex/src/main/java/com/iluwatar/mutex/Lock.java deleted file mode 100644 index 91c8adde7377..000000000000 --- a/mutex/src/main/java/com/iluwatar/mutex/Lock.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -/** - * Lock is an interface for a lock which can be acquired and released. - */ -public interface Lock { - - void acquire() throws InterruptedException; - - void release(); - -} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java deleted file mode 100644 index b3b21d059b89..000000000000 --- a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -/** - * Mutex is an implementation of a mutual exclusion lock. - */ -public class Mutex implements Lock { - - /** - * The current owner of the lock. - */ - private Object owner; - - /** - * Returns the current owner of the Mutex, or null if available - */ - public Object getOwner() { - return owner; - } - - /** - * Method called by a thread to acquire the lock. If the lock has already - * been acquired this will wait until the lock has been released to - * re-attempt the acquire. - */ - @Override - public synchronized void acquire() throws InterruptedException { - while (owner != null) { - wait(); - } - - owner = Thread.currentThread(); - } - - /** - * Method called by a thread to release the lock. - */ - @Override - public synchronized void release() { - if (Thread.currentThread() == owner) { - owner = null; - notify(); - } - } - -} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java deleted file mode 100644 index d8520a2a6cce..000000000000 --- a/mutex/src/main/java/com/iluwatar/mutex/Thief.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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. - */ - private final String name; - - /** - * The jar - */ - private final Jar jar; - - public Thief(String name, Jar jar) { - this.name = name; - this.jar = jar; - } - - /** - * In the run method the thief repeatedly tries to take a bean until none - * are left. - */ - @Override - public void run() { - int beans = 0; - - while (jar.takeBean()) { - beans = beans + 1; - LOGGER.info("{} took a bean.", name); - } - - LOGGER.info("{} took {} beans.", name, beans); - } - -} diff --git a/mutex/src/test/java/com/iluwatar/mutex/AppTest.java b/mutex/src/test/java/com/iluwatar/mutex/AppTest.java deleted file mode 100644 index 530db835d966..000000000000 --- a/mutex/src/test/java/com/iluwatar/mutex/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -import org.junit.Test; -import java.io.IOException; - -/** - * Application Test Entrypoint - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/mutex/src/test/java/com/iluwatar/mutex/JarTest.java b/mutex/src/test/java/com/iluwatar/mutex/JarTest.java deleted file mode 100644 index b9e0c52cabc1..000000000000 --- a/mutex/src/test/java/com/iluwatar/mutex/JarTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * Test case for taking beans from a Jar - */ -public class JarTest { - - @Test - public void testTakeBeans() { - Mutex mutex = new Mutex(); - Jar jar = new Jar(10, mutex); - for (int i = 0; i < 10; i++) { - assertTrue(jar.takeBean()); - } - assertFalse(jar.takeBean()); - } - -} \ No newline at end of file diff --git a/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java b/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java deleted file mode 100644 index 93649002f7dc..000000000000 --- a/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.mutex; - -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * Test case for acquiring and releasing a Mutex - */ -public class MutexTest { - - @Test - public void acquireReleaseTest() { - Mutex mutex = new Mutex(); - assertNull(mutex.getOwner()); - try { - mutex.acquire(); - assertEquals(mutex.getOwner(), Thread.currentThread()); - } catch (InterruptedException e) { - fail(e.toString()); - } - mutex.release(); - assertNull(mutex.getOwner()); - } - -} \ No newline at end of file diff --git a/naked-objects/.gitattributes b/naked-objects/.gitattributes deleted file mode 100644 index b1eafb6929e5..000000000000 --- a/naked-objects/.gitattributes +++ /dev/null @@ -1,51 +0,0 @@ -# -# -# text files are normalized (convert crlf => lf) -# binary files are not normalized (binary is a macro for -text -diff) -# -# - - -# Unless otherwise stated, assume text - -* text=auto - - -*.java text diff=java -*.html text diff=html -*.xhtml text diff=html -*.xml text -*.txt text - - -*.jar binary -*.so binary -*.dll binary - -# images -*.jpg binary -*.jpeg binary -*.png binary -*.pdn binary -*.pdn binary - - -*.cs text diff=csharp - -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain - diff --git a/naked-objects/.gitignore b/naked-objects/.gitignore deleted file mode 100644 index 0558e54afab7..000000000000 --- a/naked-objects/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -*~ -*.swp -*.class -bin/ -target/ -target-ide/ -logs/ -.settings/ -.project -.classpath -.idea -*.iml - -JArchitectOut/ -*.jdproj - -neo4j_DB/ - -# log files -datanucleus.log -isis.log -i18n-po.log -hs_err_pid*.log - -# Package Files # -*.jar -*.war -*.ear - -dependency-reduced-pom.xml -pom.xml.tag -pom.xml.next -pom.xml.releaseBackup -pom.xml.versionsBackup - -.clover/ -*.jdproj -JArchitectOut/ - - -rebel.xml -/translations.pot diff --git a/naked-objects/README b/naked-objects/README deleted file mode 100644 index c3e69373574e..000000000000 --- a/naked-objects/README +++ /dev/null @@ -1 +0,0 @@ -This is an Apache Isis application created with the SimpleApp archetype. The usage instructions can be found at http://isis.apache.org/guides/ug.html#_ug_getting-started_simpleapp-archetype \ No newline at end of file diff --git a/naked-objects/README.md b/naked-objects/README.md deleted file mode 100644 index eb1c083b14e2..000000000000 --- a/naked-objects/README.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: pattern -title: Naked Objects -folder: naked-objects -permalink: /patterns/naked-objects/ -categories: Architectural -tags: - - Java - - Difficulty-Expert ---- - -## Intent -The Naked Objects architectural pattern is well suited for rapid -prototyping. Using the pattern, you only need to write the domain objects, -everything else is autogenerated by the framework. - -![alt text](./etc/naked-objects.png "Naked Objects") - -## Applicability -Use the Naked Objects pattern when - -* you are prototyping and need fast development cycle -* an autogenerated user interface is good enough -* you want to automatically publish the domain as REST services - -## Real world examples - -* [Apache Isis](https://isis.apache.org/) - -## Credits - -* [Richard Pawson - Naked Objects](http://downloads.nakedobjects.net/resources/Pawson%20thesis.pdf) diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml deleted file mode 100644 index 5a6f4e7baf59..000000000000 --- a/naked-objects/dom/pom.xml +++ /dev/null @@ -1,186 +0,0 @@ - - - - 4.0.0 - - - com.iluwatar - naked-objects - 1.18.0-SNAPSHOT - - - naked-objects-dom - - - - - src/main/resources - - - src/main/java - - ** - - - **/*.java - - - - - - - - org.apache.isis.core - isis-core-applib - - - - org.apache.isis.core - isis-core-unittestsupport - test - - - - - org.objenesis - objenesis - test - - - - org.assertj - assertj-core - test - - - - - - - enhance - - true - - - 4.0.1 - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.datanucleus - datanucleus-maven-plugin - [${datanucleus-maven-plugin.version},) - - enhance - - - - - - - - - - - - - - - org.datanucleus - datanucleus-maven-plugin - ${datanucleus-maven-plugin.version} - - false - ${basedir}/log4j.properties - true - ${basedir}/datanucleus.properties - - - - process-classes - - enhance - - - - - - - - - org.datanucleus - datanucleus-core - - - org.datanucleus - datanucleus-jodatime - - - org.datanucleus - datanucleus-api-jdo - - - - - isis-validate - - - - - - org.apache.isis.tool - isis-maven-plugin - 1.9.0-SNAPSHOT - - ../webapp/src/main/webapp/WEB-INF - - - - org.apache.isis.example.application - simpleapp-dom - 1.9.0-SNAPSHOT - - - - com.google.guava - guava - 16.0.1 - - - - - test - - validate - - - - - - - - - - diff --git a/naked-objects/dom/src/main/java/META-INF/persistence.xml b/naked-objects/dom/src/main/java/META-INF/persistence.xml deleted file mode 100644 index 8824aa1ace92..000000000000 --- a/naked-objects/dom/src/main/java/META-INF/persistence.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - diff --git a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java deleted file mode 100644 index 30469ba8e736..000000000000 --- a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java +++ /dev/null @@ -1,48 +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. - */ -package domainapp.dom.app.homepage; - -import org.apache.isis.applib.DomainObjectContainer; -import org.apache.isis.applib.annotation.Action; -import org.apache.isis.applib.annotation.DomainService; -import org.apache.isis.applib.annotation.HomePage; -import org.apache.isis.applib.annotation.NatureOfService; -import org.apache.isis.applib.annotation.SemanticsOf; - -/** - * HomePage Domain Service - * @see HomePageViewModel linked view to HomePage - */ -@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY) -public class HomePageService { - - // endregion - - // region > injected services - - @javax.inject.Inject - DomainObjectContainer container; - - // endregion - - // region > homePage (action) - - @Action(semantics = SemanticsOf.SAFE) - @HomePage - public HomePageViewModel homePage() { - return container.injectServicesInto(new HomePageViewModel()); - } - -} diff --git a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.java b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.java deleted file mode 100644 index dfb499f0f876..000000000000 --- a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.java +++ /dev/null @@ -1,54 +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. - */ -package domainapp.dom.app.homepage; - -import java.util.List; - -import org.apache.isis.applib.annotation.ViewModel; - -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.dom.modules.simple.SimpleObjects; - -/** - * Model linked to the HomePage - * The underlying layout is specified by json - * @see HomePageService - Service Linked to the HomePage - */ -@ViewModel -public class HomePageViewModel { - - // endregion - - // region > injected services - - @javax.inject.Inject - SimpleObjects simpleObjects; - - // endregion - - // region > title - public String title() { - return getObjects().size() + " objects"; - } - - // endregion - - // region > object (collection) - @org.apache.isis.applib.annotation.HomePage - public List getObjects() { - return simpleObjects.listAll(); - } - -} diff --git a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.layout.json b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.layout.json deleted file mode 100644 index 34f78e0c3e7a..000000000000 --- a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.layout.json +++ /dev/null @@ -1,43 +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. - */ -{ - "columns": [ - { - "span": 0, - "memberGroups": {} - }, - { - "span": 0, - "memberGroups": {} - }, - { - "span": 0, - "memberGroups": {} - }, - { - "span": 12, - "collections": { - "objects": { - "collectionLayout": { - "render": "EAGERLY" - } - } - } - } - ], - "actions": {} -} \ No newline at end of file diff --git a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.png b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageViewModel.png deleted file mode 100644 index cb03785f714e60f93499a4e9136339aab1b07a23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 456 zcmV;(0XP1MP)Uv68@LBPf$L12Bj6Fx+;`w0%>S7_6hH-Efc;Qu4qPN4Zh@QV`Z4et z&l>{J6t{XQi0S}M@wcG9mvN#hKuTQiSVOj^AgTeB#O)QNAgTbA#I+DLw761Ee2iU$ zUEH@F070*G$UFQbqEAEAG0Sp!QKy(6(74L#*g;kt{wZwZt7(i`t zH-rGD5_dreKw)B$s%*F4@otyc=z3kswdh;`3X3gZD)EvND*-6Y^we6R8eLDWc(u7r z8_t29f;X`fn!7A@L9Wgj@RYfE8oq!^@5dnIJTZWZo;coYD@>yQ$VuCvN~N9w!L9*l zJ3ag*fQ2pg*nthe#({t1z}Os6qb0lG0l0Lup^jLkB;0k>xC8XXyp{uYe$&1%&`Rsykl*L6`8At^Ozg0000= 0 ")}) -@javax.jdo.annotations.Unique(name = "SimpleObject_name_UNQ", members = {"name"}) -@DomainObject -@DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT, cssClassFa = "fa-flag") -public class SimpleObject implements Comparable { - - // endregion - - // region > name (property) - - private String name; - - // region > identificatiom - public TranslatableString title() { - return TranslatableString.tr("Object: {name}", "name", getName()); - } - - @javax.jdo.annotations.Column(allowsNull = "false", length = 40) - @Title(sequence = "1") - @Property(editing = Editing.DISABLED) - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - // endregion - - // region > updateName (action) - - /** - * Event used to update the Name in the Domain - */ - public static class UpdateNameDomainEvent extends ActionDomainEvent { - public UpdateNameDomainEvent(final SimpleObject source, final Identifier identifier, - final Object... arguments) { - super(source, identifier, arguments); - } - } - - @Action(domainEvent = UpdateNameDomainEvent.class) - public SimpleObject updateName( - @Parameter(maxLength = 40) @ParameterLayout(named = "New name") final String name) { - setName(name); - return this; - } - - public String default0UpdateName() { - return getName(); - } - - public TranslatableString validateUpdateName(final String name) { - return name.contains("!") ? TranslatableString.tr("Exclamation mark is not allowed") : null; - } - - // endregion - - // region > version (derived property) - public Long getVersionSequence() { - return (Long) JDOHelper.getVersion(this); - } - - // endregion - - // region > compareTo - - @Override - public int compareTo(final SimpleObject other) { - return ObjectContracts.compare(this, other, "name"); - } - - // endregion - - // region > injected services - - @javax.inject.Inject - @SuppressWarnings("unused") - private DomainObjectContainer container; - - // endregion - - -} diff --git a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.layout.json b/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.layout.json deleted file mode 100644 index 3d5e23f7c0db..000000000000 --- a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.layout.json +++ /dev/null @@ -1,56 +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. - */ -{ - "columns": [ - { - "span": 6, - "memberGroups": { - "General": { - "members": { - "name": { - "actions": { - "updateName": { - "actionLayout": { - "position": "BOTTOM" - } - } - } - }, - "versionSequence": { - "propertyLayout": { - "name": "version" - } - } - } - } - } - }, - { - "span": 0, - "memberGroups": {} - }, - { - "span": 0, - "memberGroups": {} - }, - { - "span": 6, - "collections": {} - } - ], - "actions": {} -} \ No newline at end of file diff --git a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.png b/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObject.png deleted file mode 100644 index 0bd6f575646cc5b68b3d86c59c61876f84351722..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 653 zcmV;80&@L{P)TeaDl*`3}}y6WnFwrAe! z*FQ5ik$<+yNc=5be-qtj41skKxl`Z`5xI|$7()QSH3j7}B$_Qsz(;SOAr+zoEc#DH zpVJgHs}LdJqd!psN6}h{5b)72De$X^gj8rHkVb#31b7dr&`KbU{zD1Oi%3X?J_1CH zv@0Tl+`9@$?k#%j0O<~n~zr^w+?>@8L3-7 zLx9a*227AQjp|H9N~4$2e4u+S4%l-Ffs{EBA|Z^)xiKHGU&qCiB$eQhLQ;y&l=LY8 z%pUG3i3n(E4d53J98$9sn8Eh1NMykQPP-r_L1o*ti>g67chbmhvs@cOf+DjbVgphV zF%SMMA`~g};>SvJfPx_%%jy{+k%E)+v~@cv@Z?ewtJ=dult9HtbtLjEc&-N0&3*Aq zQ~4@P{A{UqRNp9O=6^Lj;BF5aKdpH|SsPH3E!Ns@?8)Ei=G; n?H);Ya24xV-yDd5Hm&&vexQ+2Y+_lE00000NkvXXu0mjfQKuRg diff --git a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java b/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java deleted file mode 100644 index 249fbb1f07cb..000000000000 --- a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java +++ /dev/null @@ -1,98 +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. - */ -package domainapp.dom.modules.simple; - -import java.util.List; - -import org.apache.isis.applib.DomainObjectContainer; -import org.apache.isis.applib.Identifier; -import org.apache.isis.applib.annotation.Action; -import org.apache.isis.applib.annotation.ActionLayout; -import org.apache.isis.applib.annotation.BookmarkPolicy; -import org.apache.isis.applib.annotation.DomainService; -import org.apache.isis.applib.annotation.DomainServiceLayout; -import org.apache.isis.applib.annotation.MemberOrder; -import org.apache.isis.applib.annotation.ParameterLayout; -import org.apache.isis.applib.annotation.SemanticsOf; -import org.apache.isis.applib.query.QueryDefault; -import org.apache.isis.applib.services.eventbus.ActionDomainEvent; -import org.apache.isis.applib.services.i18n.TranslatableString; - -/** - * Domain Service for Simple Objects - */ -@DomainService(repositoryFor = SimpleObject.class) -@DomainServiceLayout(menuOrder = "10") -public class SimpleObjects { - // endregion - - // region > injected services - - @javax.inject.Inject - DomainObjectContainer container; - - // endregion - - // region > title - public TranslatableString title() { - return TranslatableString.tr("Simple Objects"); - } - - // endregion - - // region > listAll (action) - @Action(semantics = SemanticsOf.SAFE) - @ActionLayout(bookmarking = BookmarkPolicy.AS_ROOT) - @MemberOrder(sequence = "1") - public List listAll() { - return container.allInstances(SimpleObject.class); - } - - // endregion - - // region > findByName (action) - @Action(semantics = SemanticsOf.SAFE) - @ActionLayout(bookmarking = BookmarkPolicy.AS_ROOT) - @MemberOrder(sequence = "2") - public List findByName(@ParameterLayout(named = "Name") final String name) { - return container.allMatches(new QueryDefault<>(SimpleObject.class, "findByName", "name", name)); - } - - // endregion - - /** - * Create Domain Event on SimpleObjects - */ - // region > create (action) - public static class CreateDomainEvent extends ActionDomainEvent { - public CreateDomainEvent(final SimpleObjects source, final Identifier identifier, - final Object... arguments) { - super(source, identifier, arguments); - } - } - - /** - * Create simple object - */ - @Action(domainEvent = CreateDomainEvent.class) - @MemberOrder(sequence = "3") - public SimpleObject create(@ParameterLayout(named = "Name") final String name) { - final SimpleObject obj = container.newTransientInstance(SimpleObject.class); - obj.setName(name); - container.persistIfNotAlready(obj); - return obj; - } - -} diff --git a/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectTest.java b/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectTest.java deleted file mode 100644 index d80d0786a1ea..000000000000 --- a/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectTest.java +++ /dev/null @@ -1,53 +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. - */ -package domainapp.dom.modules.simple; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Before; -import org.junit.Test; - -/** - * Test for SimpleObject - */ -public class SimpleObjectTest { - - SimpleObject simpleObject; - - @Before - public void setUp() throws Exception { - simpleObject = new SimpleObject(); - } - - /** - * Test for Names for SimpleObjects - */ - public static class Name extends SimpleObjectTest { - - @Test - public void happyCase() throws Exception { - // given - String name = "Foobar"; - assertThat(simpleObject.getName()).isNull(); - - // when - simpleObject.setName(name); - - // then - assertThat(simpleObject.getName()).isEqualTo(name); - } - } - -} diff --git a/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectsTest.java b/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectsTest.java deleted file mode 100644 index 91fe3d7159a5..000000000000 --- a/naked-objects/dom/src/test/java/domainapp/dom/modules/simple/SimpleObjectsTest.java +++ /dev/null @@ -1,108 +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. - */ -package domainapp.dom.modules.simple; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.google.common.collect.Lists; -import java.util.List; -import org.apache.isis.applib.DomainObjectContainer; -import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2; -import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode; -import org.jmock.Expectations; -import org.jmock.Sequence; -import org.jmock.auto.Mock; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -/** - * Test for SimpleObjects - */ -public class SimpleObjectsTest { - - @Rule - public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES); - - @Mock - DomainObjectContainer mockContainer; - - SimpleObjects simpleObjects; - - @Before - public void setUp() throws Exception { - simpleObjects = new SimpleObjects(); - simpleObjects.container = mockContainer; - } - - /** - * Test Creation of Simple Objects - */ - public static class Create extends SimpleObjectsTest { - - @Test - public void happyCase() throws Exception { - - // given - final SimpleObject simpleObject = new SimpleObject(); - - final Sequence seq = context.sequence("create"); - context.checking(new Expectations() { - { - oneOf(mockContainer).newTransientInstance(SimpleObject.class); - inSequence(seq); - will(returnValue(simpleObject)); - - oneOf(mockContainer).persistIfNotAlready(simpleObject); - inSequence(seq); - } - }); - - // when - final SimpleObject obj = simpleObjects.create("Foobar"); - - // then - assertThat(obj).isEqualTo(simpleObject); - assertThat(obj.getName()).isEqualTo("Foobar"); - } - - } - - /** - * Test Listing of Simple Objects - */ - public static class ListAll extends SimpleObjectsTest { - - @Test - public void happyCase() throws Exception { - - // given - final List all = Lists.newArrayList(); - - context.checking(new Expectations() { - { - oneOf(mockContainer).allInstances(SimpleObject.class); - will(returnValue(all)); - } - }); - - // when - final List list = simpleObjects.listAll(); - - // then - assertThat(list).isEqualTo(all); - } - } -} diff --git a/naked-objects/etc/naked-objects-dom.urm.puml b/naked-objects/etc/naked-objects-dom.urm.puml deleted file mode 100644 index 4623640991e2..000000000000 --- a/naked-objects/etc/naked-objects-dom.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - name : String - + SimpleObject() - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - + getName() : String - + getVersionSequence() : Long - + setName(name : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/etc/naked-objects-fixture.urm.puml b/naked-objects/etc/naked-objects-fixture.urm.puml deleted file mode 100644 index 04b3b1350cd7..000000000000 --- a/naked-objects/etc/naked-objects-fixture.urm.puml +++ /dev/null @@ -1,93 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - dnFieldFlags : byte[] {static} - - dnFieldNames : String[] {static} - - dnFieldTypes : Class[] {static} - # dnFlags : byte - - dnInheritedFieldCount : int {static} - - dnPersistableSuperclass : Class {static} - # dnStateManager : StateManager - - name : String - + SimpleObject() - + ___dn$loadClass(className : String) : Class {static} - - __dnFieldFlagsInit() : byte[] {static} - - __dnFieldNamesInit() : String[] {static} - - __dnFieldTypesInit() : Class[] {static} - # __dnGetInheritedFieldCount() : int {static} - - __dnPersistableSuperclassInit() : Class {static} - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - # dnCopyField(obj : SimpleObject, index : int) - + dnCopyFields(obj : Object, indices : int[]) - + dnCopyKeyFieldsFromObjectId(fc : ObjectIdFieldConsumer, oid : Object) - # dnCopyKeyFieldsFromObjectId(oid : Object) - + dnCopyKeyFieldsToObjectId(fs : ObjectIdFieldSupplier, oid : Object) - + dnCopyKeyFieldsToObjectId(oid : Object) - + dnGetExecutionContext() : ExecutionContextReference - # dnGetManagedFieldCount() : int {static} - + dnGetObjectId() : Object - + dnGetTransactionalObjectId() : Object - + dnGetVersion() : Object - + dnGetname() : String - + dnIsDeleted() : boolean - + dnIsDetached() : boolean - + dnIsDirty() : boolean - + dnIsNew() : boolean - + dnIsPersistent() : boolean - + dnIsTransactional() : boolean - + dnMakeDirty(fieldName : String) - + dnNewInstance(sm : StateManager) : Persistable - + dnNewInstance(sm : StateManager, obj : Object) : Persistable - + dnNewObjectIdInstance() : Object - + dnNewObjectIdInstance(key : Object) : Object - # dnPreSerialize() - + dnProvideField(index : int) - + dnProvideFields(indices : int[]) - + dnReplaceField(index : int) - + dnReplaceFields(indices : int[]) - + dnReplaceFlags() - + dnReplaceStateManager(sm : StateManager) - + dnSetname(name : String) - - dnSuperClone() : Object - + getName() : String - + getVersionSequence() : Long - + setName(val : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -package domainapp.fixture { - class DomainAppFixturesProvider { - + DomainAppFixturesProvider() - + getSpecification() : FixtureScriptsSpecification - } -} -Builder ..+ FixtureScriptsSpecification -DropDownPolicy ..+ FixtureScriptsSpecification -MultipleExecutionStrategy ..+ FixtureScripts -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/etc/naked-objects-integtests.urm.puml b/naked-objects/etc/naked-objects-integtests.urm.puml deleted file mode 100644 index 04b3b1350cd7..000000000000 --- a/naked-objects/etc/naked-objects-integtests.urm.puml +++ /dev/null @@ -1,93 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - dnFieldFlags : byte[] {static} - - dnFieldNames : String[] {static} - - dnFieldTypes : Class[] {static} - # dnFlags : byte - - dnInheritedFieldCount : int {static} - - dnPersistableSuperclass : Class {static} - # dnStateManager : StateManager - - name : String - + SimpleObject() - + ___dn$loadClass(className : String) : Class {static} - - __dnFieldFlagsInit() : byte[] {static} - - __dnFieldNamesInit() : String[] {static} - - __dnFieldTypesInit() : Class[] {static} - # __dnGetInheritedFieldCount() : int {static} - - __dnPersistableSuperclassInit() : Class {static} - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - # dnCopyField(obj : SimpleObject, index : int) - + dnCopyFields(obj : Object, indices : int[]) - + dnCopyKeyFieldsFromObjectId(fc : ObjectIdFieldConsumer, oid : Object) - # dnCopyKeyFieldsFromObjectId(oid : Object) - + dnCopyKeyFieldsToObjectId(fs : ObjectIdFieldSupplier, oid : Object) - + dnCopyKeyFieldsToObjectId(oid : Object) - + dnGetExecutionContext() : ExecutionContextReference - # dnGetManagedFieldCount() : int {static} - + dnGetObjectId() : Object - + dnGetTransactionalObjectId() : Object - + dnGetVersion() : Object - + dnGetname() : String - + dnIsDeleted() : boolean - + dnIsDetached() : boolean - + dnIsDirty() : boolean - + dnIsNew() : boolean - + dnIsPersistent() : boolean - + dnIsTransactional() : boolean - + dnMakeDirty(fieldName : String) - + dnNewInstance(sm : StateManager) : Persistable - + dnNewInstance(sm : StateManager, obj : Object) : Persistable - + dnNewObjectIdInstance() : Object - + dnNewObjectIdInstance(key : Object) : Object - # dnPreSerialize() - + dnProvideField(index : int) - + dnProvideFields(indices : int[]) - + dnReplaceField(index : int) - + dnReplaceFields(indices : int[]) - + dnReplaceFlags() - + dnReplaceStateManager(sm : StateManager) - + dnSetname(name : String) - - dnSuperClone() : Object - + getName() : String - + getVersionSequence() : Long - + setName(val : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -package domainapp.fixture { - class DomainAppFixturesProvider { - + DomainAppFixturesProvider() - + getSpecification() : FixtureScriptsSpecification - } -} -Builder ..+ FixtureScriptsSpecification -DropDownPolicy ..+ FixtureScriptsSpecification -MultipleExecutionStrategy ..+ FixtureScripts -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/etc/naked-objects.png b/naked-objects/etc/naked-objects.png deleted file mode 100644 index eda8439a2896339adc829e61b5cde85ca7d1af4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75022 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°gp zwY&kNA6fg>1ZNnJbZ{vc0U*yHNcd;fk6nCT{c$tIUI+W1M34py2zH3VVN7l!Ap&aL z+lS0?r?l4^={6P9yPD1{b!XlO625%)nV^M$Naa2>;C4z<`^L84*wO|4i3WCQ%$81% zOgvQ+{B*!b7Qht&P=tcsDhN&{gLm(Kz>E-`sk0J2yM4hw!3rF#Q-m5I`2P+?_wxb7 zh<|qAuL9$rDOi!8L2^Y9d~qdZ!C(Wr&+Gg21iu?nfL~u9RKH*A>D_DQ;#Cxr>?a6l z#Q%Fru{XN*KdcD>fYp`ScD9Oart}kkJV!|c2DNW!PU_`*RR!-en2<~Fr0}lLo`e?%9a7aZl~pJd$H#0ajzObUwQ_#KlGA zXL`e~utYL&U)gZ~>@|qAC21fP+?KRd5X?LTL$V2R1UGP3pclVl(s(?3kLKMwe=e5$ z+?@z}9JWj3Fl)}3?_8=*O^?#mOPOo<#P!|?1q5LkY-ZS3J%?D}JU{z55uDV??68Cf z+*+3q{b$E}+^BuOC?qn;0kZTGb%+YN#$>4AOz>CS`e*x}?yhHuj&uc&4#$Pgt_796 zu6nxV(fB0e_ZgR5BFzb#6ir{7PHyex;%}%zgl;xlKLOY#Y@#2ldjUR~r4SgfC z;I|u|UCqb*yuz2`+}`IAWOz;MKei*CLeE5>GOy#*p;n|Q1XoLVrZKG`u1@8{(vxm_ zk{EUMO=+*VdxMOiA)1xfd2Sb#)q>62$EJNycEKEfr1aU!VcRZdnvP$}u$T04(>On6 z_3$}E*Ne@jtMV!kB8EuQLh@t*+v{<$CmXRez$ZW3CW%)v0EEG=GaT>;Y2fVg=+6nF zK%-#0Jxc5GzszYrABR0z3=%^%La}RRw;A9cax7H$E*2QOf(SBzVov(y*rPyTcR@uZJ|g zJ6SIU-t>&uRDBt>blO#~mbxp}lp`u1u_$;HL#o}h^$|(qx}b3D?B=^@BoOR#b{gl2 zq4Qw)Xdw#Nstce0Y$253Jdmz(a%@gHZBiwa+s)?@+!J_N-do^88pKj`z^hSorg;&2 zYi(vq{;Ra0Bb8|C%H{j9v180;#AA&a%!mZbqA1dB!8F<_8GvRh?Gc*cG!C8^D)-_k zKjNLeIgiUrOYvNjnPOUnmXhfJ){kn)gdW~Ko5!6Mj>cr61}u^=3gmyI{I{D=eXjfC zX1qo_T=f$6BZ&HiZi{k?-*_GGf_~bHk)Ddk;$8H#@iN~6_UQ&YSG|n}^4S_mUid8y zyBWQ6=hXGPw`QvLEh;=9{aShZ@$Ugq?5}Ga=*BY*(e#h8112`e`?f9-eI&i^}{Kwex|Z zc~0v!VTGi;8nyb3~3u8da)B&;zq0KfY9M@oj^6DQ}>cbi}Ns%i`9Q%>< z;`{>x0tv&EbhxcwYH#{ltn{kepU9I|_RkG`w|wHV&8p+pOZf5#KR(vWmDji$i*Qg5 z2vTu4*kpj|&F*jYdnc}JO~y4JTzySF-*L)&d>ED1czHXDrTLir?&o~+@hH(14Q3&W z;;M9@HKnhGfZO}G$Z>$xS?uMhXB^OzEB4x#N{{VWV#B*|?gWFW;NrCll9s$Gg2iTY zcC+JQ8H>`9{XH|Fg zo~OnRVNL=>2k_X#vD&jxw%Fi}OH9qKih-JG0?VE1aO?A4z(_jz^#UmFzZ)O2P`o-nUU-{OD2%t!HCT3H^MoAQfA~lavC2cUkKL z29KRobYIAg0#MIyh`yK zt+V^Ot3W!x)Tkg&dU0sB-D-kCqWHCow9IPi`Vclag$%-vvYv*`DmfV6`NF6{!|fJm zE#R)neAa(MI``~gx3W3?p_V};MiB{XGg3NS)#z6H3Ff|vNZZT7nP;Iq1j}!0PnnSh zlPH1Du8%R2OE{2f z!8*vlBF?L($An0Uxemr!pKU%4okR{YuSWyWA#zU4`V_sIHo|;nU5k$jue5nfu{vQy z_<0mu2Jbg#>icH)$LeA3(`gOd7gtTA3YVwL^?inM-aM{h>f1N!O<8w|NmK={h-`(Wv#LK5Zk=Mjo9g7+hgEKcv)C(7v*xcz0}u76 zeYfO4AsIHRC#vgeFMkS@`sDn9G=>I}yH;WNi+|~ConFB6l^n3ho3~2PH7kmmRCCj3 z_zuH-k5-{G=wcL39sy)f;sK023TO+tDR)yB0}mK&seM1@lD@BLcV_lWweZVB;)$a% zztrd<&RSRQj}cGOpsOXs_?gF_fK(TL~#sUZ|O?fA$oeU)5fgd_Ae{ zXyLOzHT_Q)kb}Sg_vlsr`;t3t#W)kqaWLFi8(jN*~gM3f>+`Jt5OkccnHFx*N};_|w~W~Bb7&XEBS30Z;n66^ew(keAfWQ*ojsa_YFPl3_YC%bC=%Ze zHX7fa0YeX%0f>N!!J=c@Y*-%=S1bsuU_cVimzC=ug2a&f1xt-DZWYD9s-eG2l?iqF zEAu4;zzD?AA{Jmp(mL_K=#qOfr={4z7YDJvDUU;>Z`d{__R7&wrw19FMCBih-zSDJ zF*|tI;#z7#!%7Jf2c&cwUagZ_gG_w|V^(^U_IZlm;kh^I zi{CmPaEw)x?#sqD<-d35nKXiQ=-qYBVfyV0w%e0}E}s@$G2&LeSir^Wc>YX}{3Nlu z5Gl6RJfUv&cT-P9UATK@^vE@i>24^Gbn6pT^P4Y5tL)v{h6fS{zb3ui!;#lmw7hiR z^o>bV_A8-p@{siq#Ug>oKMEq*{%N39`;wDS7$QRjlR-Ga0)~>(pKaa`+jt z(wK}dvLd0*y7U%b@O-_RC3#yYB6b@Cs{r$A!udnop=|5%3@uWsP^s@O4;8BKFYHq%Mz3a9EO+w+ja^*7;d5 zTJ@Z3yYHm|m2cHUh3 zN=x7vQkUJXMoXvj>J;W2@P#){wuVg@-}6t|k^aGz()Z?dpS9#?bKJDbbI*@~;fm$t z1uQDrK|MZ=3fCVUT_> zTjf+7J)Q_U+&;&|a_4%ZIj5e7^f}bA1G7KLB7sMZC^b+cM9^W+zHy`WgZPgp1RN6K zk$QgOyua$iJqsji>3?ES6k)4tjw&L=4>7J5gG?+u@6gHK1%GbTFSf2?U&^Vjis=J2 z@X0{updgxiQ&R!K;{AIKH0~91NB9ND;J7|8wym$?VMtq^rcq#$4~cR?WY{HO+d-La z-Q@4H<6i0unt49)N=pi*aQ3slle~X3rRUa;nzMK8r_|7)Fr|hVr0~0G3jEh+WE+fz zDO9;+MHywm+Lg&y^tPPhyWS%~(ffE9UX^^&^mx7#buP<{l6U@YkYn3~_=9&0Mn3h_ zytF@q^3Aa=b}1k`NYlj9bDAUXr%zfWr|b8u%OX7HepqHlKh{#UaT;>!c`sX8LpaPt zGFWAANRdMa`PDk9AZr?*#a!g^jID%mnqx*ZT`&6Nkrl73qnDv%F+Au88&pYhKxMlj>Haqw z!b_`*U@;bs-N<)#Qb%xl2?G<_VQdb5vEI!B7xrQC*dcd$moJlV&G z;1DAI=C0%9wmLRpN-c${#&Yy@PC7b>mPyjAi;EKnoXKMvc^$^()o3WqkNzeW_-^yr zgtv%X*S}69WOGNp>L`e;)HR6$?0QVo^1v`%K{QE+Hii%TY)&Oi;d-FBNy z^H};5BoJTY)_B#?>aqQF^#vnSqG%%X5OXK^o_IKM5`%JWZogAQdAMfUp-Q+eKUiLXvVvH5Q=07~ss`H#dMiY58 zjO2-KKmpCEZQxq&+ZqGmYO_ycJHnI zL9pnNw1(eNRy@wnV_O1&1czLBC@C|f!hPvfA!u+bs)aWB7Ih9UR>{6=o-6+w5dv}l z&kONZS;mc^dV`{ms)A5yAW$fSK*jw7@y5G|l9T~LjM{N21mbA5CpSv0(8auh6IVGB z$$Q|TsEiQrU!LSXaHbkZ__0Fkog*dps`$QWIiW(lM%~po1q%S%cO8HB>gZ%II*Wh{sKqXWu3Nd|EP#!1SqlV9dP6Gjz>yCmZk0nMPm|1 zsmi%kNgfa_*Og!t5bPL&sE3%0?gd2t3;ydU6T>u`P^9#XN~8f1nKJY%@#Jg*w77Q{ z&liyI-5;eAT9l_^iSba0rvr`y_YZ0;19_q>x7e?surC1exD;(TE=oys?3 zA*b#a(RDelKj&;tPd8P?PSBG-nvXZ7lR{-<0dg!+JBW6-<xcZS9%2kSzMQA|G-($u?3b}xY#njP9uR$cTkdn0rKxmcFp?ty~#N6 z?RHO0r{7ZR6ItfuRIxw9Rb=IlP3eiVI!@jm{a@a`h1* za@U-#{wNlB2`=Hkdz>$s(F`dtnw{%Vdi`Dl!sAzYBuyH3MNKo4pDLmAmWkpg&_r=- z0>kf8RaAH_gGs41JHjdFmE&HA&4Nd;JEvX=q{UxboTPqT!m?B{2B$EM-f8e&xt|HO+HYy392n!wE zQTwdoKk7Q1YA8hPZQ|W-&z%jNtixe7uRAW0qeM93dr*~?7Mi% zfD$@I1%&g%kUO|f;{h~sII_9B)cM29Qe9U!SwmA7voRAR6f3_ia_7kiP3D6{K})^j z`1X@)cNep^>)HWsO%<7h{w}PJ>-T0q#w=Ie?b0q*(myLRDzSIaD+?<>M)_|3Z7wf4 z7G zn_Pj!x@+7G_Ogvp(OL#|Y|iOz^5!d1^bwmvkT=&UW@vM0A=lG5g1RXQkGJVQYh+o_ zM4ZHu ze-`79*4NFzEtp)%#4x$0p4ghf3=hdeu4EmD+CDsf?f_a$FSK4P%l*UPifplZpTSK8 z;~AOW=!$lFr^Zvdb&%@I|A`Zp?1%ldwAEQ|9O;z+JcBV7tqG*+?l2%9x0pWERkK~r z{)RD03!^M*@V-E!aD|*VLuKlYGFM=`sOj>e3?uRi-B!+%QB(4nwo1Wq1p_Px1Le3P zzutdF8lX8!MZ;1+knWv~27Zynr3LbuIY$3lc{&OD>fQeGvO)bFky6w07atD+UY@e* zXJt^^06n^BsR8%btW0Qz4GE2*9V61Wu>M+PyY^D6#^xS6vpeBgM^8uX!*K@4hN5a^ zSJagzFJ6ajz6)Qu-e@0#b>Ta*F3W9ZLRtDr1}0=auXaWh5$+eUoA>;qHCp;NoF~QA zs6O!O8TjeDq+=&syM(AnfZ1)nC)-7lA53I|c?u6g)Ow6G-f^R){}^nPLD&et;F^ZS z9?@qIi4>R{eb@RZe;c8ohEQ|Oa<_o^mFezu+Q(%r@G8oG#bA|hyvWvTJZNjQM{#U@ z<3mn^ZhtPOCh}5;*DljpQOb+&XQI={VpEG^@dU?8D{fp#TEqtJKZCV@$3z-w+PGhk z=hMA&J_^uR)IiAXvxx)>6WH%yr6t8TvnamiDdT_B6HQ*RmK9(V`c6c zc7C+{M9UplGJc7??XA*zP6LgC%$FY@bn+gq?%Ag0Uk~())<}T8mVF%8M2kXU z*N_86e`P&+{VVbZ3NMnP_ERUFQ`UI%J*%8pfVBI=`~CDmMQo3pKHAbk9=+CY+3{Tt z_jk+nY0 zb*wIw;xFbl=r7SLKYq;Ip3HA{O3IZqV9>mxX@0_Hpee|8l5l!_fNkMWh9~kD=HX^U zQl3+_G@G~_4HiG!J*>}vGveV#i&gho4IT6B;ZeA8!W_sIR)hl|E)8#D9MAnYPV0*m z2WORXVQYi5H^pqyj=RmPPY7$6p{2V~)smv9o=e3t0Jg-?H}>MMq07c`u^xyGVu1pz z{IAXXwJUeaj`#HAa+BDt4>Y~(Ty}Z)VlR%g=igRWiy9y)N55HolS`94nEEPp;yz|s z6jC(XU(MyME6yHVKYlRodjI%iNo(Q23U2|#C4~ns)SPW<;RVY$RxFEcj7B&TMH8~R zpPTuE(Q%p7c(%Y2D~;^Ab?JD`M{vbbj^m7QGLjlLFg4u@m3HU@1S!i_tD2=B0+d`a z7(%aIHrIw{Q)qx-Q@s0PP7DEc%b&B(BP9J{>Je6WeX;(Po{yC2oJl-c&b(`&H+E~0 z(-}2TBiLEc20}NtT|rHs{ZcZh$KhJ&Q;_immpWzH`rLlIUXgg3(t1m2KUy;!$&j}S zNd~Y=M|b`bL_L}?nH$_1+%BC}BehF+ra`JPEoXl%W_wJ$2G*9X79t}VLG_?Qv2C81dhOL;)e5i1JhN5uM|W z2NaD5&eG%F)wP+9I2d8%f_5S7vjk*f6Hg<6^q^d-4Zo-!VSs?qWg5bD_9JyJBMWI^?@^$4 z#=7_TybAB92UQ%SR?~Esyr|WG^a+Y;2-4@Jbay;=6e^As$%Y=Nc0S{1pVp-ZuTYfS zIc0#&mbQrkSn`CHMQpRsI;{-#8g=S2|6*}MqwjB8?ATLZDIcvKld|%+p@B;$zey57 zjT0W4A$`XO5JaCyLC7u_LLH%lV;C*tFGz31=Wpy@Nzq_ojLc~^HMsw^4w-wM1Q@#} z9E_3QQO?WFVMhQTshxfP8lw`4b_rU^69WyJ$IR~{|qup;af zy27~0)`9&LS5ST%leROMV8@jF?V3|?*w@X-#F2IgD>P+tBVzRNYTlEIZl{oj(W|E+ zGUCbzQA^CyfLrGekg`tCfTFd`Bh>lWZeZ5Y&9Y*HDwf{IQNRwZ-RFlntcQE0XuEt> zgfAyoJ3Tino*5$HiCp=Kp7d8n%4_Wglx}731MJa7k-w7fXP{fy=wpX zcOlOkw1xjl`KWGVdvR5-IwEKQur(lAV(F+;(_>)g#re`hAdoojE~$dGO8n&+UOcI* z1cEa2w&F$$xe*K#jLwO%jZs3c)oUvT8dvyWPpUCxlca?CMNho zU%7CUFLBWL_TC-h2<=ZCLYr^Q&Gl=9K_?|plv~Z8`SI4keG)r1|5ek{dSuh+C=G@s z={)Ps7i$UL7B!_=Hc(S{Xc3}0qR!c~-*)_7-AikS=`6)vZFmXi&z)3V`HRWo|ZBuF*R^Girq=kLP=@KWjTHT{~H6=pNUrlu?Y$xa` zJC7Oi>oRw~;ye5xyB7(7o!-2IyI~f(Xm#Ik{UTfQboGuh!qEsV((4Foa?or!!5*ob zwq|#0UUQAuHsNUeUPQ&uX?2HE=ySeE7c*hXbQIu zCo5;#8BHYj8<`^?vm2LNoU^ZR!^;)Nx)oI@Cs$_)2^c*D=lfUchi@b=ng* z^A1Rh#F+csIE@5Cmh+xQ*wuyb%+V3l>-!q`eWVc;|BeLWf$;S$7~9Mc6c zX|Td=eF3)ie$WzzDIwq{wNs$ASU;Yu*r91`Jn3ZYBDBfL)AOB~3Q1rz!PvAg?EDLi z-c0hd@E-XM8wk5!ZbrEZd%fhXS@BzzNq5mMC-S}gsO3cPxB(EWLVPV4;28^)jf^Wu zLQS+KNfP}`v+Sa$Ti08PzSqkF{5lB3%Ojw!yi#~QCDrt@+~WA76KpE{eb0*fP7lp* zc@=n=1QG8zDSloao9eitlLRxfYuV$CLJ+#J7CyS5ehY=ggWR@zHDXOnw;M=?WXy{B zmb>0`rTN^YFHP3p`nxNlpiz8hmqslAsBgd7jsb{G1pa;ENEBZQwA~>!YJ=WoJ6UEd zzLBY=&LWB{%oOig4obq1pD3t;DW0t0tM2IlRCs@8Q_bfrZ-wGwoG-_S1^CwV9R9X0 zS4)4|_^bYws6_8q1P>EJCky3j`TQT%rlUyTX<|do8k2<&-@LG^73c69X$Xu*I%4+Q zbg%-o4Ccv_aprH-gg3^m+nYE=5OSX}>LA08^uqa*+H72=)R^!1hr9deAT@<8SI+tVF@-+#cE#UP(jE8wRoPO zwKNimYz*WKp7Nkq#Lci>b&f%JRqBC*&XYGO*;mFa0A0=t2=(WN|8iwDKl!G-Cau+<_;rqZ`Bi?`iJ z13Bll6l;o$k~l+|yB}&>JPo#~xP8_V7T2=E!-+=mlU>nU5YsX{1<9~@N;%c-CiN#v z&hsWsr!^s>+BHtvsrvk8u{AP_)iKO7Y0a_5pV%KSVBO8#>K8&jC{1HFvdnIObbN7N z5ri(gec}f6Zp1t)V^c&Q7B^&`VC*`U7EF18Sm;{|NCe-GRsLu_kO5SqCIpUo;gw-F zJ*TQE71uOXC8f?ziqXt1Y#W1D50xyFyF`Drf%g2R4W|afW^6pWTyR2*hLsbfI#Bhl zh6TK4Gl_iR7j;#Lj94VFUY#2LB(HI-&W1LxexI0~HrN~U%~SLkmKLk#i;#TTYiR&q zln5=|wXc!g7gsStEedc+i>fNvv_Jq8HMhxUh(OHOfG?T|!%LvSXQo#Q+x3^l;`vrs zwbkiznkEUMZ`>AtA^v9lC5ZlW!S=;tJYVA4ji&V|VB{-8F!skWW?#<_!9BL}1c6n%sMqNC0HT{#!h3(hj!0KmV_b4F5Ov zusL|UsHv#2JK=X>)q=}j?d<9_i5T@B%a^lX9%=`SqyD$O!X~>+jI@i_I~QivPep%l zf!8Ab$d#jFfI6-aZx>sRZ9B^&{r41#yijAil>T?xU!U~F^V32wZ?G|JrPHQ~Dxb{Y zI5fYSH5s#da~9)WM31)fo=U>*i}evy=z-+Mtbb2LDQHSJIKrJ47a{A#A%MWc%zPKdFI(gdkPvq0zWDJ!qL?*-_ z?H|Bq(|o7}csFj_QF2t*)VCTN<}%;pkLiqP=4~Bt`0y64i+PHjOI}{1bM27XNCST` zx&;&D-KM{eQ;AtAKDZ0~{;!4oX?*kgJ$q+|DxL@?bA$95M@8{;9B?^JU)#Ij&5tJn zJ+mOW{_uQ&rkbI0!x3Uip#SnH0${%D6+Uk<>21C_O-pfKyuFW<4pPBXuFhXK%asu- z*_oX5LUZ1?XMfToDJNG_zfB#VmaoRvT_p=*A?$nj*;~EppeFH4$DE@<{X1kHzIFK8pkb&7hH=o?H%Fv{_!I^^m%6S z&TodWkZ<37_P7hl2oYC>^sh#H8itrSF;%ld)%|+$Kg`Xzxm);*y?}~+d*dZjU*;%) zYTm8&`1*c}ctNCSGgpU9!tRb(Pv15wYNS_NIJLt4b(@c-5>x$(wsXeT9u6yys+Vf> z?{>Dft!uq*eRaYho4_vds{1*2*^K5#QOYbf#e1fM+v{Ym;A!K*0aQ@yQ2r2#mz$QI z%bLifClse0t}pD3YSnxoWxY4RU;mW0`_pAT(3b`8{1inE!P@1V7xy? z2+mnD;`u5ifL2WTMMi$|U`m1~em+7VasSbyfcek_4j`T1#v+;$w&b^uCh{1Q#a|^ch ztxIAOA~KN!Ttv8Xoj;wDhKTd@IW)rmZ}>9DHE5n`zHBI|@pb+uhN2UD$>MK>i78_y zEmjDW9Xp~dF*>MauN#>$wH-$bB`0wo#MbI>hm7kh^liDv)ItsvcU!W%9tylqRR58f z9BVo993s$s853~pglz5`w0%VMgdeJ}T`B4H8~L}tgZe~p4A&Xww|^*@qPpoFBUoIQ z#`X-Ncm>*t8CwI{sVj1y;#5z=6w`y#rLujNBEF;b9CtUPfa>lfU5hVXLDhw=U9Tpa z#ZZLvq;S^zHo+Sg)y3Kpv0-h6kGkHgxHpX%#lYSMLq}?9_fqFy#`sdNI0C z7EgB|WwAE77dkVyNi`bMiGDccS$w--!aaAq@|#3B^;!WeI!2w|1-6_mP+*s6rQSRaeH zlcj!)%?Psij-20Z#^Kkg1H-j4T9rn9j8ky`<-qQ*yH3}sc6)3q3+_<{ys-KLpCJb7 zNZ&(CeeiNuRy_)z?Q=>w>#Rt#h&?I@M@AqL?hs1-v}pZq?^BmUHU{24ft%+H}#9I zl{Pn)lFh)!1kKi8t6ffEx$L2jVhr18Evj~F*>&!nI=NE&Zuif*cPHQ^ z-(GePE2TADZANwfpur(mLZ}=jHHVW`5`TL=3(pZ9Oldc5EJ#v5WrV!VgC!LXcUG+E z6ljeF?!Sa48y=2UpPV(efK`}gjMDl4s;_j`e`3FB&Bw|i%d44c zH8@EW$p6*J^)%=Sxh*C1#G$0V0J_&0RsZh%6&pjKAXXtuGy~s{bWYvG4OYK@%*yt% z$XF-S3gK-f^rA)^E*fH|g^o!M;TSKb*M<@eDI%cO!_u4RDWHzuDi0A*x2I?FFdkoj z2jdez2ndfy>Rgg26{@D-#!^V4?J+qDOM(%e7p9EZRU|&_9RC7 zHxAn8ATIneD#h%%QT^0y?>Mjd>a}C|wRMUKW}=|2=LV0eJ42`*S-#vz2bF{vlQ6mk zrVe)muvPh~&LQK)T2n>)^a$ZBh;=__Jk=!_3%f$Xt*= zh61hBKoOB^6?{z}FxDL0ZAy0Lq<|hyNNmYX#l(>3th7=TU&Rk)esWrW2ZFP`q5`Ls zhJFE;G1{&qXgv4WOLB*l2L82@A2)WhnU2;n2HCqNL$wUA`?|~CDy6;yx2%*S`#(_H z=OqhnQ;6Lan2X~y{$g#6#Q+G|;m66LwKOi;;kL-z;UmZJw7>fIjXQ@iyBNhCxzxFCC7 zOn(>SX>fMrQ?tH4e<}SN{GR7&u$~V$?l|UetJ1Pvv>@LS*Sl?f_UU($Ehe`+pXX(J zi!^C(m-{l91UwW=Wg3b?&&Ta4Asm^12uH)TM{gUkCPOkX4O$aB_U$IHZMYHkbxLH- zf(KJ4n&SK>b99sSBtou+v|Zp`j){kBpJ%q@T6^;y1l}TP|4%Z+9IBgwJC(b?*UwdG z;%>HZDKlFXf#R|M9Zg+Y^8%A_1-m z85^+Di{Wo2YCk^O|50C=!!N%I-`$FKfVCaU5xKeNo?fL&DGCb!SASU@$z48-<`k6Q zU)^X@S0`6p>)_yQUn-~g^GstO!6Il3Pb5HKM7Vb*=7wXK7DtKk>iWYhYr-QL6r8R# z5R2<&&&+BhcPun5J~4kq4e$W3B#BNwDtq}*+H@utA%*`>v32#)b9{aGmpa*D!cyeZ z@kDGHFFSKYoHXuc|9GmX%QE*tqM9!l_UEq#iyfQ06Y`7ql78v~UJx{jfITmC9edpE zOZ&?C?eKS=c)();@)T)+Ol7w@NjR%E$^Xjbj0Yd2VxM8z1z5%y*@z=d#5bN}boK7mp#10Z*dIFlZ^+L@7Y5AM zGM(MGx&Ir`|JTLjdvU@8q6Wz+I#gdYN_V+xT^4#qVsG$f0(i}t6(Q{8&yvA^IU-{Y z-n3?|Ui?(WT~nv1HRJC3bJuP7ar5+^d7ih+bW4kMYL?(=5l&3CN#oDyyxFAI10c(2Xb!5>kRRA_zz*(w)*scXvGsqBPPUDgzj6P(dkoLOgL|*J=A3KRTJy7j1S@Cpq1=wHv#m7f$>83yDHMTN zmb}KX>6EuRsNf{jK5gU|KY2Vd<64ZxX z{WxWY3dmM{JiCC1Q@@HptVn)oC{H5uYzMO!hVBYZp0_FF-|DzT88w#%>r9c46vWtL zpPH23amq>#!lE zA?(^?TOsZ_u$T0#XbLMFILJZ$P}1>?(TydAUaKl2zFuFv9ntGV7a3q>I=K&T4}Dyw$tOUSiwX$^z>td}xq}S8qQksfgT* zs*J&Kn~$AuNauUFhUj638}{`{u+;Fuqa*+OyQY?3 z*iy5w59>#d-!VE&VoDwk=0&}2=M%4g_o-5$Wd0cXHM(Myw9M4e^fGmLel5Oa+zq!i z>-swpJ~U9ZfQA&|Wn>)}ojDOP%ID{i>|Sq;1QGcFNz}agHs+~Xr}at&Ctfd+hC|Yu zI;Nune38%>e-W>68H@{i>^fMl8NOmGx5BnUN!&Xf!P<2m`ssI=vu6) zS&E6MAQ@unDVtPuYYK*MpMY>jNKs;S@mujtyRy-?xGc# zL9Lo6bs@4_j07^OLGz0miO&V!?tiI%&s?oj`UyOWLU|>Bpfws)hf+x<8FHu?7wBDu-a<4%Ktj+bjf zMO|o;*5thq^iZIR6zudJSjn7f2M2hSRqAx$$IAZIv(v6KF5Z$OkB|oi2uyz zSmi2mNY^=O0>U4iJ2cwD$KpL3RM4qF)f{Kr4=bE~Q$YCB|j=UDcD91XnY; zuE+Q92}JfM4G=JO3h7 z5DN%@ZFKT}M^EO;=1MSmQGlz#oQi>;CUv+&O)=jt+(T(gqOSb0Z0?g({Lq1cM*J!& z(%PmkkM^H)b}>V_p74b~T6@C7+dGW1f)Cl-#QpZVxOwP%QJ^&eGcd1!YYt0j>rR0%Sx#wx&yn0()j_Q|ChJG(%59SwshUr43ee)MZ}EH|HuiQf+wVbC zqm83uYvlS9hx_9CawJg~66%rC7xirs%#K!rp*B-OpRa|7KdWd<(C@7g$aJ0lF<&$D zZBuKC;q$&Z{7vqQT0G+)i(R#T`2_)Yl9b5N$0;WICU+5HW5CvW1Y+sYmFTo~moF@r z;Wr!+nrgyoOX1s0H{Td0;XCyG^)iTT^c++FNhSy@K_y{F2V(79$!Zp@63?zUzijh& zMbz(ut53n++WEZG`?2cdm!=$k=OGb_-ffru8#53J5OGJGmb|)G&-^69?8tN2kcT_OGh6nD9EiA5&dAPYO*t z*Ksu@J}W038sx%9W1sL&#a>N5W-rEYk$&NI^qkS>{t|ZM8uo9rCtuPC;EN>xWSV;l zvY7*rGCDUi|)*M+Qwi(b359 zdRq_JxDKA<{PDcQ$ff?3ns?9(nCLI72hyh*ez(x#j$`0-T#nZwS@F#_6*Ek@AQbN$ zyf%xHCABj}q&11GQ}!)1sluo0_M~>3kcVC}1)}Y91w6~{(x(to^QX|9Zn3RnDPT0v z_0Z2IHg#EcQ4ZRlP?ib2puE1fg57BHAIK|TN1S?gBhS-Skwk`*x+lk7-gV{);e?@Y z8a_+}r8Q`CucsqbdR@7Cfz_kvyyzl)e0sZ{*N04(S*l-#b1GbAsj`HV{cpMY4ytE7 z(4A+Zl2BD4De*vxC|PgJgc~&WM&C?}TU}X|G5P|sj`a`ggrLr6X!-oEOI`iPR@tW= zAM!os`OVS|vb($2TY1@UnHw(>goMz`+k>1P-Ji zcl5@nAyo4l9cJ|o_<83_?BtyoZ)QFjkx$i^*}gO(yo;g}M-ptYEol5l!5q;bJu`=7 zURRgi{$MhMwancu(QJlC+^13>ZbouC7Fa4^<`n5R@aqRVQ?5RmL z5YbjeotdMCzbUyf8kl)loxbIk*j%UaeUzf72G~PB+yc(ctujf_Wj#x3#+sqay1=Y9ACTYx1_~oGU8z$)koJN zhcctmMZt|Zy}zttDPyso4X&8=B&;ZZEXPesGNP@-HLpoVv8k+@Fn2;(Z_Mput@a(Kzh4rcwNLE6bV@uL__*D#ZX|m*|o0eY!V4u2n1{S@!X)P#o(fez@9oVJVXBU zHyq*L_Te`u)6bU*b)TZlth;f^`vYBveC-W&6%YUXZrU=dGn-v1`;rnRAeL7A?&jTLk zc2#s+Ojs;_D!CZs)qix?amzK6Xy)k>x0vu9nzHc6KHlIC$d9Ml7v(!b0X2$%4McWx zC(dNRdzqs2!{D9U#a`RZx`YX1!zNJ&^}g~0dvOM(v%H-j#+BExF~M_3KOSsi5Nd(B z_VQ(9dwc%WxpgfzIkzaY^n?1FB!Mzv@>QloydW#u;F@LUt1qY;-;o&MzhZ(NQK!PC z{9aG}Bj-O7%r6x#L+3>ESSPc@9w3^I-!?jz(45OqBb_Tujr4P3Z|W$59@=o=X*z7} zJ&V8HGQoVuKQ|3?9`+xWe@cblA-*2HK0fWuk`yYjV|$ucGHV)p#KL;&->z=}t#tIr zUzs0de@YD-faO@6!0zk|G?h7ZSB<7u7Fo1BKvJg38yx0$$bD2i-;dVA@bax?P5o7BEM9#`KBggy=_`=n$J7x+~9E~mVMbK^$+1b}@ zr~E=7Q$_w}>I(Bk>9xoHR=(C%Z6f$*(aJW?$9P3GydG7tNd`^PaI?4kJuu|6PH0FW zY|v3PO!?T$G*Enk8!1dDg z#i)$e+1s{|>zxw^l<m{Krl4yjC_@s&6SZ9cHx5WF%QmZpG0!|}B${x)Cyy}d5 z$gjebtcZNR|3zbB#*I`s%tpp$^Ei$=ZVwD^6K^5t z#D0|b&pKoR0cVm8sFtH3FU#UtA6as&#;;<6`;%eq>v-$D5@xJK{&~Y%fV#v#WiWe1 z##w47SzTl6H;S?O^3e&L8P)~Wj?XuQB#QU|%L1yFJDS??eOr7-uUy^}egMvR}Bm9jQ3$~g3ex5;o z=_2?)$Wh6EnyZ^%%7M_Wzn}jP4uO4(>B~+u9sqlBFLPP1oCA;qt5rA8J7hl>YkT{< zLR@-=!z2K?_xcUbU^ke$^P8YpVMzBBu}F4+F(PXp5U&^Rrom>V2R!=-SO&`St-4Z7 z5v@TXKs~U4jcg>-$`3f-ycs8kj|>2a1aAen+}N%l^>8+~ z$7Du+OARoThW5~1EZ{D<$!V%ox%wNz>|X(Z4$S7O;|HSofT?v%6qUDlYw)#fM}5ypQyq2U^iuLF0eD({ zMEVbR-~w2~ZeVyZe@%x)#jWa?{r=2kl9^8*mu;vFo%wdtaG^U6CHI&* zA4S4v1Vl05CDq8>%2(V~e+m{7Orf6>FSy<8hpFuyoPq{wJ6zz?vSz6o;6V7@@YGY& z0b012J==4Vhh_Dwfh1y2Iyzb(ZmbKj%3h){!^D0uLNb=C|DjJ4;(sVG5a_kMf$Lqe zRgKdi`LXTi4lMAti3*nwcZR0Ql+`sbgGzW+5o zvQIJX0vW&yV#`v10#XlW!Uh0z7R*=HN544EPAP5QN2y5;00cTD(D}{wpYtG(WB>nG zW#Jpg!~aJ|v3n8%y?`CiurzZ29{dOJ&dhac?9A!u!VT0}^t6`+=l}x~7?2-P{3I7< z-SbSDLb2ih17Y^h_*cn_s{h}3$RsA6wm2`9vUkN>{CJK4Z)XQIl#o*brdS8b9 z;$!;kRqu~^R<`_7S{8~jhgNk4)P1lmj_pgER=TEQm0i+DYA;3g?=%a)MH9APgEj3u z-9&b^Z>QZAu=F9i?x=EQ+hu)HTRPZlXQ8P&p_cvh@M*}De1cW%l#33od|ZLXT?M0s z;lfvjNqNV)nQqgaNeAmr&E!ifJIx7Cl4bLA-%`5_xX~*6XUN6Bpru&c`SQg0en^15 zX8MN*tycbux<1ZUVhb?Od9G4t+fV!JYImDLrb2i4u(YD%6yg$NN2i*pU-C42`}u(TH%tb?o{-bja`)V#rp+!Rs+Q?kIYKOkboFxq*k>HMFBF}HXztA-b$=;c6XydF72e$aQ#CZ*|!|7iQfYn?m_gU z@fSk(d~8+2t`tRq7rZStjvtqvkuS-H0{-gCpARK~D#cHc7W<3=?W}lgzgR}o0J3c5 zP4LKt*xDG8#&pNNncSE4i>{ffH|#U-`y(wAI$Wklft7Od-$sY~ZILjrnC|`FlJvGX4r*V=lBy+u5p@j zmZt5FPa?jdBgkC-3}owzpDTFvwya)AK~d_dey+0^_(|>s1I5ec1H9QVKx5}5%Y+}7 zRMnd&k>!D`u%#R(ewA4Hb!^RufFlvfrHQovFT*0*gT-gt*^-|B#nGWDoB!NI{y}f; zMbNC*L9tNhCLE9X4QW%>){Qu4i(*J{U}8T_ItxmfT`PleOmi4L$>O>p*PT1pALE1C z*t^$AG8{#T)03-LhDo`n6Qch^*bS;Uh~@1$3ODNUZL@v*V%1IQ^vm9Q-PHajexA$D z+2SatHhh7(ZMt?1Clb@q_Jj~H`&{TFe3C^LEi=3<3H%ov7|&Y|F~G$#Bv<)7;7zG3 zrSUeEF5;U)S>eB^Qpn64QqI2(QgtNn?=Zb8n}m!is0B?_9M*SVFWkyKmx6f`YiUnoN$SoUHfAr@7{as<_m>X0&Z>mkX;j_^;RVVd zGe)3oNRWUHE1Tu%`boMx^#F>1eMtqJ@ZRBOTy zGTQ#~S7HUZ>qvnd>8PsqxpaDO|b{Ls4inHd#krn zW_QQ;t_0zxTClm-YVZ(Y6Ld2#onY?K!k!`5U&FdSTBSZp%zo{v;T^2j2G<# zS6rqLr0vzIHRt*&b{e(S02VYV=KZll6A9JLF|HIwGd=k=yW#o{@!sVqtZeq-Qx`Y2 z+Cag$gQ)6G`u-sS#_B723RdgBYGYo7KDqpj^_0j1(4ooQ~==8(G1(QBt6`%sZ zFRx{)H2Yb$#jUPF-?mC~7-RdgBrL!DK3vvzYG+{i;%?Iq{9?nTEb!dRdd;kGi-jx1 z*$6EH61F`Wj00OmD3B<|uVG0*#DHN6K(YO9$8RuMC-c;)Yu*RBH1-A&qmjIIP@}7M zqU-~JoPaA60)og`)vkwW==ToWSu{3blFTu!bH(cX+U)4|+7=VQ`W_H~BQ&LUqyPg{lx_5>8QVCfs{qrh}QxFonx!0`>;>gR}^o^U2> z<7b0ON&$W!Z>~HU_IR9q@9pwO}!$8g}1|LWHe>;PZ{#cDK4?JRg7rO%9<6%(mC5)hB*D=!l9t z;x;vZg$7v^&0^$LD%M6<^lC)Yx%xLUp2K6P!E`q-YBNu!`}DFMnBcj3L11xPkE^Ty@vrnq`2J&pu!qsDWJ949j8;aad!;e#>S=+ro zLw|B9JRHyh@vP`uqRf;OJyY>Dw$(L-M@DiwmhYqRDh3}S3R_f$A_?ZG zwb$L8R(~L*c@KL}V`ZheKodDI=EmmRqs$E{B+5Lvp1sTtnYKN`vZHCkkFVlI!S7XR zbvIRye&kz&zB(zagt`1|vh}u72%)2ap|{|XB^zi2zD#tWK?W#94!?8zBF&qZNOa#G zi1xz9)d`n8!Zxzi_BWwF)5P?^AJ-|m8=Cj8Y^yvwO)x!Z@ZJV^WNQYlvZ21r2 z(RXU~hkcBwmFD>cbOkM1!jR~&$Q#yvmV}6hV~%^+ZwuBebD?od>^!OjoKFc|8=(M9vHz^ zoinM1Fgz|Sh1W60R-fO&fqjF{9aWQnV5m(>gk(L^(6J1~a&2X46cD6sfZ)jwLmrb1 zFB`uW3UtsUeKJraCSMyHEaE5_f^OCT&6|F&)VvLXXvsJIZm55TGS?E_Q?tab;`wcp zvDa&b@SaNV)#d2*YWrqLd!LU?G(G5A7v+65SqqCyZW$ZDHx0hrk%0lA$kq( zM1AN_cXX4Umb5noRe48o@?Q>0Ddlzc?8eMy(dt}6H>}>zml&Vm_^Y6NCN=1jZ%gWJ zIIAJIm=&wrNbb}aYRoQ-az|5(TMnWfH9d_^zuZ_P+GY)~E@ht8Gv-#`f8Oblt6DOj zdQf4ZEw^AZiX}w!hRD~_W~r7<-$HxHCC+p%D^s1j7KATmy`cPf+xw#^!(SV|TsA92%`->t@G`bLnI`3DbVGZxZ@VPiHFeZ}R|Au>y-dRE&P* zaLuDdBu8lCPQVB5g4Xf2s7^gouX#zu()>8TvtlVbR&tHuqyOoYEgd9L2p*m^!{Uv& zt8J?mk!!p}-!L^0Xwedr)2)|}pYn(}c_X<3U%*s_0WM}pSrW%~`ZYm%=Y{1#HTvFx zqI%c>f$|;rd*OTGx#DAzg{VVVfo+VgzT#!sF|Hm(^N-h$3^ABZDI|K3yGKl>irBou zMEZYN*ZMouu+|zNMOl(G!vQ=*nw)edu?sH&I78~ULP7t1LR=!~vgR?W^-4x`1{&mmvklChW!t7|6F0ZgI*QlDg!_>w z$SPEP{V_C2chV^QYvQ1Y} zd++oS%8;~KDDX@~*e0q7-CnJ607d+v%{e<~kk`ey^%;A|)3hP~&YXkB@L3nM8Ls$R zT&B9tR<|L`vacz#W#}ws59=tDASfYyd(U<-uH(F)pSK`0nSyA!1iDWd39525!25!N zRDM{07H*WJS4?(l#K?$_ud3{)$&oVr4aehS!t97qU^T#;vM8uIoTh!83*gNIbvxnF zGso`h2s_=|H7Bi;o*NkDSB8y?bIIY`&ika%n(k-*0n)V!bsa2zK`$(opt2#^ujYix z>w|LP70GlAmSr_2wa=0`$=uQb6duCu)WT1DFadT{a9`!22}5r4zZPSF5TH7=j4_$LonA zCggLfn@}=Ca56A@#%U{m)}e*bXj{B!H-!IcMdEwy`nT#l$&;@EMj)Dt!f4Kuv!nAo z)-M36={*)RdCk(d2*uhlKKuhY8_(ZD4R(kY5&HNd8@shs6*tRUEz}qgc+1l?lYJ$s zyqOU{27H>!DjQ9#*$-nUI?k#bbD*=9j*?a5R!anLyR>D#Vfqmp% zy2sAt`>*YdK7$9FmAigKOYl=d3#)Wrw~N3#PZ)5i`$}6hxs?wdM{)L=OY|!8R)VM7 zK`uB$PT0R(770OtB$>^R@GLTxN1AxZ(>I>_9;Y#x>tYmG9dp@Q_f_#a8lPvXxn&2<+_4Hgl<@?=~GlS3inpz+->G7YK(Z@3B!T2Y1N>*KXm-*v)5_ z{mbF9ExU-8u_Zm+9PRc&S$nl1blWw0lNnWqpj*e#oeyn2=JpZ5Ui6Ex!(47@n`xif z?V>ke^C>$%^P^#;X{Y+rr1*_VVK15K_k!TviVBD!r_&&iTy!!X6N<}a$=lkRBCtCa za7DnW7d1COrr7kpaUIQwTQ{!bYB^x`u-*Z@eq)b^|4b_~^`G};)!RF%bWd2~2*d=` ze)d2E8(|SMSNSvj1rn;t)RY36Pbgtv&*JTFh5lm%*>1+B+ipTZUcB9J>Lxrl+xdI= zQDaEBWQv`J`1eknH`3&GmCd9B&=f+|xJEElAIn{4r`&Vy(z{38&6xsF_s$R>S6QQa zo`Z|LObcjDJ6O&slCykXA;;I`R2eYT8D5Cd*}(|m z;tYHDD^vQFUaVrMyyQq@JiEqW{BgYdLUnjWjEp`@0R>$j*87SqWF}zu@#r3{7@!#oJ^F&h6eaKKS9D1#r0hj^jfU)~K zf?rAUkNrE$AXVZLu)fsc;@RB2Z`2NEFRIy$KDStZ<*olW0siAl?b>NNHH;cdw@I3P zHR&AYikzVRb5-&5G&=Wqx2zCzrkh0@ZrMj}{%=_sB^!#)13S4hg@X=Q}^#@WCCR) zq|41tYs~qDNUrV9gBiDhzNgmy)U(m z=9shhN`Ys;Qm~f3Df|m5eVa%;8}r1#{{aS%*kg>3j_?5epESrpPtw&bWuzsp#BpFC zxZPyQe}mhZxGVn;xSfvY4{$q=<$%-EuGhJP9s5&H_S;|WKyv9F{s-MI{q*ay5F+1G zI254Amjhp?b?y)mfT4nI3R&z3C;}z)!VGeU-1r!ZLF-DxAFeu6eKZchT@=4;>ALD* zb;BnhO2A9$y2{9&LO1sDlLsJV$N|~7#@8exV{~%JK?%LcQWV~hzWBG7h2>Mx;jw*H zcdaOn6M8Z3O(|FQ|KYV9^lJ^^>3rs?4wX$y!Zl4x(=V;s6ti%1pG>&Jtnx{Fz!IP( z8feU^-mj2Y-g5U(eyZG)2Cp+yaq$2hrCy0`&`aNr!aLzpAu&$9w2R=&3;@XL`s2W?m|>1uAXbKaEGk}lL{rWxXcN6ZyM@E|QS4iQZS_tZ*foF} zAKJYZHvKbDFZKJ_InKg?4k?DBAo?jcYpT+{G1FA@$wJPuols6mIkV;&zhU`nr7w%u zM%xy8n_PLt4QR-mQ26KYi*0Q6>(hSo-8?(B@BQdlP4p>xp8L5=F^|I4Ao3lJeG^T4 z`TYGS3VX5sKnq)%r@gXiynz_K=-mto?_Wy_KuHGA2uv;ZphvzboRXv#sEB4vJab|tT(lUx4tFot2 zvI5*cJFB%U)CLJSO|jJEhJ|DHT)*?6-HA4fk9%Tiz0@o%R`LGXbv6ekZF$_r{Lqn3 z1pwoi+eHKq63Fu4!nz-PkTm@qw7c1A>-bXSQ8*G|mE-n{)Kz;42cd^p7^ubv2%#y^ zuY)HCNw5iJmmYcwrqFXned6=)UlMbZulPSOG^eDS-${kOE1bVLu?V ziYPMCWg90~@;lD@8!FGkvF6Y&h7nw2o`$-9ld$gKw0D7lVa86Wj?hU54chcfpu+H3 zc~e=?c{VR)>ZQ9HR(c6i69SL|7xD-^R^szY0aB2y#PMF8Q!Y(=2%=SRQIx{u6q{mP zHPDjNOZ5ysH0e!8c&Fqna%lc;$z=y+n8!1q=%5X}vgWOou)-G0p!|TQ%0YOgl%#9N zb3uBTs%3=7n<5$^`=q|jmt!w;5s^}abBZRF=6P6}=S4HQ5nA?UIMEY)jU_;OV4&=m?7WXsRPyK6LJ5!>UE3Crc)&g(3hB zQ1*ifkRMEd&j9M-X_y^f!3o?<;xY%o`RuSq4=5BU)lhP>rZj}snrWrPRI6tKI8hbn zCJ3Pw0||G|A}$`Lqrys|bp5YUnh@q#cAUXuAgCIE#pTXx02x9;< zuz_IRF7`Hllkr>?<(X5v87zSyY?#Y_pNg==?J34WiuZIE8Qb)o#u0o0HHjEoW4D8{ zLa*+MTLN429AroYOaM8q^B3?y3Z(!7@S5p%ctVlf6b!Gbs=yC9lz{xZFAYr)VwT&9TS@3)~hSs>qt7=Zo;TLm1G=Cqj-P% zLWO|=(8D60@ScYP@~_%JTTTvD1jtv}Sl8|of5$YYxqdxHGIVXZeVbJS!2GE=AkPH) z3~t0RMcS7H&5$WS_5-PW`}1`n1h{XP$94G-KtP*ZtNf~N;prRSVtT-Obqp2=UxCI8 zS{LA!&hM$bf?(MD{(1Y)-~@dFM(^gK)&&2U`#)X~>Q(|K$QPFSRed$u1^m zRi5xc8(!T5MF7_$1sDON6tE`aIWzDy4tDYgJ*@B%{}$SHK%Mgo5=ADdS9A5ZK%VOI zC%w|?_WLs;It&%2p>~Om0*@3Ba}a?6&iZeH(34Sha;K@H0&-KyJ@%c8S;yP?&I>EQ z#L_~$r!3^NKQ9{HF19JI$sX6*7$FA1cMU0S=%EMt2wzqJB#3vdz!OHua7j>EPN==w zv(4jS$eVXQ(O@equDDR!Z`;4W)W|J5A*uLp$bTuLlyF zpEzc^vB3>eA|L7UF6a0}ZJ%u|V*d^KAh~3B0Su&M^OPmU{v>)*R5lLaZ6GMApjS!| zg1D?0)rcBgRlUEM{ZJk<I4DNyIR zt}9w*X|h_|p@mz!`QQlmi=&J!`14W8LtCkFfj9D82KsTmYj>z{VQS>8NV4DGWB`lk zpiH^niOGx;NaDiAGf@?Rr;_OSu%`M23{Yi1J*S6xN6T!z;4au1>1rJQFsNeG+>o$z z|2>_-;7Ds_%MmmeC{YtlZYR~D%Pv+17N3VH0TW8UKPsvWxmXN&BA98oqqSc~AV&3w zQt;x|_%r_DmUhOGm3O*REL=+cq!Apn>Q`m=U3~N>NXl2Z92qg_{##V=WG4K@#}^8n zqj-k1TojninNe@QS8cOJHL+&_Lwu*3OIZe<^0ER0=%1MZ`J``X5{lume!gTRFW~jnj$1|?X28`(n+7Rr@V;n&838fLWi+|a!Mr4E=z=G z@PJ+6oLFz#v0{|#Db1n02#6nfJeC9v&4RwOB~k=vaua17%WpY#oskr}ib_f=p?B-u zrY@#Qo`py94}Je1d$y$rc<6d554q(U6xT?wp-XFzzzIekemqD)-Ar(0?&;tC=3uU- zr6Ehq);NHwV>X{-a!=qbf3QwIH0f&wtA1P-L2%`>@$UeQgm;H420kE5_uE}0@gCJ$ zGK(XpO$gm-j3DZ2aFueEZ?;I^{m?b`|M(n=LIDDCvX3Do-a zAC@#)X8{7%s$)$lZTr-9_sKfwVLRIiNkm5PLWBf)I963Sko(_zA!N#0`X(ymvWiDw zWy}ji1a+&T`>Q~Fo(O)C*8KJ@CMK9L@gBIPtHdzcn91 z4`ADWsL2F4UVI3j$7l=7AdTDcLKpTz!-eS!VKZ$EUJs(>M55M9H9D;&;jrQS<%!`n z4b#MA%xTEJe%*asSQV8Zhkz}*FhF*nS1caChY-!jLi1n+m1-FbSA`H{Io6IKt^EKO zflna(Z)=zY1q7pCbfvs~;m6#EN-l)x1pD+7boyh;Y^h2Ew^@=-(MgiNPGZ+LQ0i0F z>;4P?0bBsNs_P>BZk2C>3PRHNb|dCd-ZN@=gcMIi$y(s+CvaKF6S16Q*uudPt)f%h zgZ%QUK7z`S0h zXE^WLVP2fR1N;S~YlixlT+iPDDFQU`^@gk8nY`L$!C>L>(?6`#?NbCYUwTz-Rt-@? z$^+kLcZ9zRmngfvT$}}bY3ZX@6S78?n{`lrw03`DuC_xh44lY+kvEYE1m`4r^met~ zy*P^C(qTKufg(!+7lS=iL4omFauhiN2ua+lh6`@5myW7epr01FHo z%Pw*o2Z-S}e)b?(2~ZIqW# za<_IOU5-#fG57L4raNSG(@u#3=X_|em$K6M22DXh!Ncu19{$Gh{-tW5=cw4$w>z5H zoI0$8#dF)xmLgqOCz&)y@l1Qu0j3*HTyQ zPPtK^iI_w41}$GnMR3YmA0v;q%vexI?eXW8 zaAA(47t_?7JcU*U=g?wm1XZ~8@Vm&@EtCPMI_FQ#+`P_Dw(G95y>`64&d)m%F|ZZ? z!SJ2EOg;uAyqS+LDjwUNtp{?A74uSqbLP$kDmwX=< zG9UT4OYRl}+5p^BuK~FEI$nJxNT@`%7q39*Usfk08dYFtoPqg75YhsP*6luq=5^Mn zePev-LzbJ$z~&VNE>`c$`lna&9k#CW&wxA9NdFoM86 zsHE*(r249YevAVLFF3l}QFU)XpINu8`E2H~8~T`uU1fw%Z6tB0vj}yhI&@E0rpIA@+~TXqqAX7R$KJ8n z(}RuZXi2)|P}Qf;!|&2T#fA1@j{285RwGoHWrR+!kBGT#Enbth1QdxCrw^WjMgoJ? z_r?81L~owgjgM~sWdSJ^A=rbmUC3^$O?`3rG(c$@+uAG2Bx@>k<8v*K@AWMs8{4%d zwhK92*y)Rp`9oY-HEeeJgUemb zI@=!BBfR&6@S3_#bP47UKMzziE|4nOVsYSnTy&7&ecYgRKmITO#&YA|oWDxDCLz;d zr$M%MVwt~d$JdtFFfICnA)Q(emt{r@+T65@>jx$6gxW{1R6V1TeX#rav{qK4n?JvC zEo~h`6Kj(t*IYE>^P_suC}Jrkm76-?R-!Ao-W7FT#IfDkJFCsh6Eu*YfnVs!(nlxdrAM?S=Rn+WhYpAIEN!l7ApKhTKh_HcMk zviTwb$4{Q~Im-zCBw7iy&y>QC26V5BU22d}VlidN>UZGtodwq?jI?Y>qNPwBv-C&u zm+CLn|2dbg$7{PewLAy)%l_zR(3Mb@B)$Pp!|l`bsC>q*S{osfcM6PH(+;!L<&o3k zKi#oP^iue1XqX{^2P71Vs|~!5xU0VB_T-tA5=-^jf_*aGZUSeG^>_Lc=vV2#{3n+p zF!MlJ?fO3bUQ{dB6pVH8P%V}yH|=>VQ*P!Q3(G=En>yX}0VdPGu zcVouQnZ^9EXefbnd}KCqN&(bAiv-?D3FwlRqxMuHv@MM>Xw6pI^jBC_@8qYZXdqwr zre>K;5y3h4dt4t;GdQl8PxN@GJ|~lZW750a|1O>W>RD)gj!f1wxkByyMtk`aJ1?sqbGe(iv$f1U0W<;pmypV@)!Ppe5`e(dZ@CFT~475HEh^*0Q7^;AT zK2OTJ3zaIFVcdbf9TEXR56kj0z<%KK-}Ga}jbAUetTm|wyYfrZf6(Bx5GX`iE zM66}8ThS;2-8}F)Q8(2LABe?lb}wngnCs*`M(D@PedFy_JMy3YKxNT$xxP-hbPSApb5M&$?A zIan}^kK@gIv|{6{pWqj;(@F~`M=WVah+Lzq8%}~LvNvX>-LgjZZI8m z2+?d_dhFRV?%cn`_orG2I_X#J=ZRmqJWe{~LPVPDK!-WNyBp>ftw^3ODhruHbw4bo z5c<|F$Vm_6KDXHS`iM%N#h2T#j7ppScma}LpJQ0H|xga0jNMNKu_(9_B+pHA)yD>o#>_SQ|sWOd|r|Y zej)Or^|_&Wm=#=HoeT~qmUr+?#SPR!zF&ot|6Wf)w42E_w2UG%5TZ{Zm(4)F?K z2HlfJYE6k3UDq;u#9cjDQExmwQw*~ZIm(b|=5+AOXRQz~n;6bLIP`r;t1gv~{X(Sg z=%|5n_3BLpMw`LD=J;b3dDhjtb(PbVa#;0yBiuJdEY}j~82aqNb4KkNf!uM@%rkwc z>^`PV>|ZndH=p$0VBHzQJ5x;0^ZDD9RQAY;?W<-tWz`DW^=!<%0nsVOoSdZ z6}r>54ILWh7gZrl42BA`ak0)#-|Yvt9kl9;rJmg(@;8BQ|Fzh3|~5o%ZS#Y_S!(spgCth34=t)&~W5p zP1QHtFFsdt627SQ_iv^MF4B04KZ+)M54Rr9=!oCN=4>bO^WBhlUM-oTL$bA7Ql9xEO;rdw z>%UdT--GGc`y+O@Uj9;d3*Doj+hA;x<>KtszxVwZ-tMd-v@eM4{cz3dh$B6q7ZgVJ z#Pkk%HToP;6b{qm48Fh+HwI1uxa@o*{-yjsB!NJFvKfhgkp%k&>kY@bC2-U}JBPo; z_u`QaO%AR>7zLi?6Q?sH*F>-iMY3K~h4brI8TnZltB9JEWu! zAP6X((%m5--4fE>-O@-m=iB(a_ul8e?{h!@_>aBL+H=h{<``qnov_M*A^Qe090ZKp zwLHP0IKbB39a*M=`{-j+9o~-G%J#7H3`!8C@C*kT`lA!6^sx{5s=CR-Fpa3Col%^GkDum`npw<^coG1GY=Uw?tJuSz#zp$> zRVLuNY`A;os;^b&pbmm~8tvY}T&aFcjCQ_A9a=FZ+n-802H&B3kBauqX-9Bp)V_Cs zkdpeaXf!_SZwDIl6U$qh6@53IMT49}Yj&1ES%`l0;YdS@%QWwoNB)!W5;bKVCUREF z%`7gJgblQ^7|dh*FD2q)Zzff1kH;7Tl1hKrL(q}`i?9U{bZP#N`?1S*C%98;CX|kV zP7L2<11|U*@soo`zJ*q!--)x()H)%RqP{25#4_FGK}jPm7Vi7%7gAP-T+$;Hbo>UK z(m}di!^9?n>^i?$|4g8VX97Y0es%d2uW-2hMvBl?H%zj8BZmw=kwU7GSagTVz-Ro)g8y7w?wns zju%{!d?=oV@f26rDhDj-)c){vLd?H$s&b%S75IOal3nDCxUetU!&m$} zx@qY)wmtlL_<#l#RpR@pSxMdjV?+Zr4_|dai|P5uIwq^Ni(!1O7KBxu@?FRkgkr;7 z&}&Bx4EQOB!^Nh~&d%WAM@JvR!^4M$hL)NtSrUHa0mQ682+XfGv-OL=D~C%g~Kd!KC6H4yu{Ycz}ON%md2w z_qaF+4GUYWbEK8Y2)|fpaP8Eusjg-)CjtN=4A7d<8hKWEpZS%C&en9S0X3auN-NA< zw~3<&#i}`RU>2b~T(KdS`58sJ$piI$YcK_t#``v9Hp6#l4kTfHxrOyJC2lkNYz^}Dk_VD21GY?FIx|TNJ9F96 z;RS*gEZ^;r*o69!2FIsDn)G;u3d&x$flya{G+zu(iFH>3PVp% zPaB)iTsr;s(9qBnKG*Y_Hy}&zEc_2xrh-Tfh+LkEg>T|5TD9#>GwFSjC%2yWA+h^I zGH!f+<_nGVO;?$dq*zT^p$bT>%-XD})?ly(9p%qHtFOs+Gvl_-;XC0!Z018fTA!iT z>dGTiPg6oBn zGY1$mg%4}{j~Zg27)~jRzd$(8X{~?!o3wkNeTIN&B?~J8!L~10z1dVh379Jt$_Jn#ey0XDXBqo0_Bh=6}kd3m`)o~TMp zS;mJ#kW{~(r2)nJ*>q5t{SOw6&ZJTaa_Of}tB2Z5T>w1)bW)58_3IN7e_JiYh!0hl ztss9v@29#+H=m?z_id&4abBR@{){Tnw$PJ{Dt$*9tycW;RX_)G>|vtE$3W=Aempo2 z^05fCwY6DM0VJHCVNV~2Gt0jrvpagNC?|LNKkw?FVbq)6$t-**-gDjwut*tq)tuOj zn|IWL*jKTF9DCI{Wi9(#h~|V|I=DDAY0f%$^rV#OoNpkTknZ^)BDH^9fs=r=8VJA6 z$;!&QI9T|s48}Y7KeyfDo<{>1Czie-2>l0jSaN1;@KE-G-M$$xo*KiDU=doEi*A%L zLa0DA#SOpG+IkvLlWto*gcraU{a>k(JfKPEq$B|wFM_ju3k}+2H52g;s_SA#tqS~Q zp2)={c-RG$&!0a(e*8G{2~=PaOpY>*;5wigB2B7*-;kbL8x|@Z<}`XzdD+bx6N6%5 z^QzIBJqzvGn_sld(mxm;<3OXouW>0Uew6bKUS-qxOcUyA819MD`K2X8W*p?Zh;g7D zk{~=w_><&r=|IL#oPstLCC9cV97PD#SOlO0kJtlWq?!#EBuRE?f$8OPZoX~^67$;< z9-@45d>)=te)$OZG{qT*p~@D5I+qfVizOdehUh2TrDok7MkJulVYMR|JZz;UB{nuT z!9Q;f78+JZ7MeV`*L?sWkhDq#vTnHWOD*mN%YB?2Z;0?)%Hr#jES}@Bc*%UAS0YUn z{Epmn+`@L!&dM4s!rYl{yx;8XRgKrH*tJ?ytS1dQNXNID->D^ zNvEmxx;ekRybOEF*RkdWySv~{lAnfwH;E9U5@T2Nf}eEB(#8N<&Y8B4Hy+m{JmF&o z=)Z9pT$_lnsZ7g}uWj0rZ)_s)vbxeK+eb-EI4bQbh`0D&27WFIBif< zY5lcB7lF)iq2k-EoO_;^KAHFTSJMur-7a--g3GLrD{+8){PYI_IXK+*AL)+J(8-?JTN3d$rE4{UQZ)2AqUtu0 zt(cW2!iI{ShxkMwsC6Bg)b!8q_>1~D8et;&XX?Wk z@iOiOx$^TO;I#}J%Lz)8?=AhKrZ^kT%p-MG`d3G}>vMS*BC5dqKu&z!$7}nzp zb$3)b*t*rVI@^^zi86l=CFtGRtLOH(nNP9QU}J!SFXH&^j{O6;LL*?_TWs=ha&mHW zb3+M*W4(fW`kD|52$lR1&gDFv`Xqip&;MPnt9nfj<`8;SR36Dr@j(-4>~PV6h#8AU z6_)h7-%=c38kVGedk-$mol|OG$X_6`ayG5>+B@8w?~8uI#K?F9&w|f>& zd8by6!OKPhfoi==R|DuFE3fWLl{~_ay25=A=?f#*(O$KG%C6yYSu~T=0-Nkeo_wUm z-XQU}mgLXkUG1H0H+b72S!4Yi%lyCc%;oEHt7~a?cCq_?CIv>OE~Y;M4HBd7AQE3%hTv#lStm$P4^T$%zU@ZH)_1#DA_$i7SfW7$t!F zCv-s2VI2P*!!#{}Ht#ZB3}48Sw~h2oFqK*tx7>FQI`w%TK1e8EwydZ6uGGVxEjcBM zR|=M^dX$KVME80u7m4%js>*t+v+JOTziAyV0_28T;`Dyw`AtuCY-nFssYh9ub7x67poK8thklmP%yIkUT(#OrskfF z_b1Ja=`q|;g`Jm9Nll4kf}i#1L;ZwiiTACxwzjHDO-;799lHqdOd_~j;m)?2voVwv zwQ#{{u9hLoIscgPGUM6HNX{tv@p!YSu}|TD!r-5v6MZxjv8P+Z+X-I|n41B=!WD9F zRUD-L`RB0*8=7iL!AyURd^ud~A!Di3_>X-VgXVXO+!arWNTRh?S#s1r`w$#ye64Ds z?z^|t=zcn#Y<#sr(p7=p`n?ankuqYh}?20CX_;2a#HW+#&VDHM}MV{ z`?G>P^Z+gASEQ`0W{6^;lTVkCUz^DJ2dodojCHSdu&)`+W znavZK`|`k4=TM|`F)%2)SQU1KCEpgU7=l21#yafFm;RxlhIe?ZPDTMeWW$5AZ~CzN z?SEh=Rg`2VOUis#hI|V!=R>KM56;DXG4{!?iWpqyKgb`PSR2JcwsE8KK1{-h=}7U0 zNj6KY0;07_X~!6{C;pw2nM8v*0c)7fkj6;FhG-F4WB6>fyAfiihaC>I)xxUpBgQ0f zJ(%Zp*-IdifVA_dpIRbPcpQhD3NIAEm8*@P43EA5zg!W}u}fN^ugo8L|41D`x8i98 zT3NIH33ExEMCA9?7#Ae?#pXoAwBk@(39R_6D@%yuT=aV@T4zhzy~UB!Bp&K?+f_oF{It zG7#_Om_ANW4U1jENg1VlA^-?Q9=s#}Y-N~$aCf3YF&j1`7xWNY>*2>+upQcqOMpF+ zuEqGDr9Q+=-vt$<-(wHRM{F);vb(&qyN#6ci9{%2_h ziotCdq2j9 zVJAP;J68m%Ht7gYZbueQ$v!HxELlIU#7q3zRQnSNADWRi>3{I;lGojWO2Qb=esAbp z;57vmQdbCG*Zmjja47+>o@B=gh7U+MNkFA7{jAEOphbC(18LQfRn8!CS?y_5$in<$0TOBo<0zdDc)|?IQsALYb90`VUCJjtXOeBUA zGKb<*B*a#c=m7?`Z@{{8c`Q|V&~0%!94d(`5SH_u8?E-UEqvd*Xe5!1X+AZV<%ci$=*ctN;xiIf zeCQ^(*kX^GAxTUTs(LJDI%@h3juBX=-(SJ*twQy0>^u^Sik1rJf>y5AkrAR%@Bv^P z73A*}%v6C6hFX0ZVB`SZx|}hD-_xmypFHU}<8=lW>_9$b4gKg1j}7L4BfcBOtK%{X z{N91zj)gBJf{!6DNrNiNi7+k_aC+diG%jJ`hmR7gfE@v<9>-X-C9>Hyd%mb3NaM~3 z)vL)9R&jcq>JM(Ur`1PC^4Wn^Yy3Ke9ISy{0h*^+j%y{-2MliQG2_wh*iTB^vuwK5 ztOIv!!t}Cm)>_i^(h{aGNLnV%8+{I8j=vP-CD5m61t}85@`3+CIi_|DfX$oKq)3vm zoM1=$sMkf+N)RbDzm;cC?*yBKsuRdSZ^50xMvE=%xD4*z$LGx75vJDn*b3c3Np8n4 z=9*~YeH7wvV@Z@eLuI=m9m6=<4!%`Qgf-E zW$GP&K1sdPS^(_4G;HLV{BT)t6&YEY2Q9lzn+PZT1H=Bdz}#?KYp`#kv5?V-i1xH? zUhA4FfctRsVxE0BcJ1TEF9 zN6)+3OI)muqA$U{BIEeMneGMayny|J@tmZQ40YU+o9THR-6?Z9H|d7*;j_>?@@^AX z>6jKKl&H;0M_H@I&2i}x=F*(%D5zNNqe<_RuZ4n|)Q?V>eVVvo^tu8GfDgr~B4s1H z+HC0S%k$oyB565m*>ASr3>LJID?*HWZD?=|kI9h%PSe!-%b9W|SnnkM;_##1!n;1b z(yL!l>Tny_`c6~dEX-JVRb9>{WZ-v*;X~lj`@fKqL9G@tz(B!aVqTxerEQ21AP% zUSuRg`DB%vJQDl7r-C&}WybDM_Diq#u~bJa#%ye+wHiQO!?ZvEj7ho8H4@+{T}Vdg z{E5rbKr+@#zcXv({3S6-F9`Z{ki*4+l@G4Y8Hr+YojnNOe;=BJ5|%1>o9f@>M%-fE z4O9;43v8;83UW3mW>;QqV@ar*He(Hn7)Ba1hFnsrC&uWg`eKlw{>k!wpBVt}r}Tz) zvW)Iu3nVJV)tP*f*;P|Q9X_!72s|Asi(|hCAMo1ltibFENx{CD^_X`OZ0bM0Q89HU z*Nwi~qnM2PI1aHnD}q&~^NOx}3b@d)upmkf1t+SwsbuCkaJaboG>SjhjFM!LiS!@} zYKdFqTBJxjNiJ(7j->M1sH$Lkp5uegU8+wli4b&B>5D5TA98I5I%D}WDsa{|2f&x5 z0@ABIPTd@+bQlFjofOL5S1qo`SsZ0v8y<%`*CRu(xbKgCt}eyfr3zln_F$2EX->f@ zT?vw+nyW?%6anij@8@Z*OjzU*hx3B^&J1$e!RfvX$?A~baxv{H)TPI&fVvv@_XKT| zd|>sF)jGml)jN2?2G_%8`xQSPrbb({u8<(R7RM7ReG=H{#;-EiDRS?? z{crNc>(7io$rBf74^e)1ZW=tpqeJ-YV`Uw1qD0E&o#96#V$P<347enkVv{+cw{fV|){Zi)`fIb{5c2sOw$Qm5U z@~|e(Z;oGiX&T1u!o^L?;MW?GOC@5Acdafpyfc>W0o^G} zVWHkr<5t=~gHdeQ(@5j`zCidwym>?wd`}gt2gYr1^1QXz&BSszEh>qq zU?XQT38dAR$_v9P8;<98^Ye{H9*a#fTHP}R@n=0$hwA%b;j$G6ka5aSVE7~KFg}^I+O|xFvV^D=-ou>xlmkq$7rLs(fBzat(C_zew1Vcy>(ea z)()$rZ#vYv>3N=eUV-2zwToW9uXWA)`aXqr9+fjXIy!h`Gr_^ZB_$>IEoYeUHfR=l=Rv(Mxy7uguslg7QreRn{8o_Ac0R_^2EbP6T_P!gh|qM}tuMw!=#=l|Cx*ovrU zLASRp_`^MnI4Ch?1HrKtdGDFfc)kXo)j$1=g-L)FJumz?}=?EVAJT2Rj4+Iqap{ zKRU?2T`GQ=$Z?3)fSC7vdooq%v%%gmLx>M$Np+SfbRRp(v}^3pLrkBD+8bfO6_ZCr zQ%BnLK~eiy4L(5v61OcxOX!GF4DeU}MMZ0rIAi zk&z%2zi+uefc*9DQ&DBJfTO(fayId?okh)~D~(j25ASY|&c|BnFUVJsd@iHO@2+-^ z>~waC5pQpr^u0>&PK{($hHe+Wlz&_nEqF9nj|wgSeJIY8*LUgC3>;4y7Qszdr*fgc zU~8=9hJ(WYl;BtUKdcIGdL}LQEnR=;#*Zf2OE5y$t!iFUD%HJ~2}Y}_hU?a-N}hJ+ z2Z{Hf{~_KdpIHg31M`-3Ufet7wI#jM2aDhC8bK1?`RcBxd4Isv(aUQ=aB+4v5iARu zJY37~O9QblmS6%d$H)LY@)4`Xod5<>{+rg-)n^S2mLP@f>6x6%nfw@dKo`hi0=GRI zw9QU#n|Up_Zccfy<02palXg4#WInok25|(XfrSF>R7FGsv&^Bn(-}#Gt&AsEimFu0 zQ-ij?a+hPvV7DIBkqY3kw;opky$=6Q$$hn6tP!5W+Ye88>j@z&dx_Xf^K}C&Vf|Em zhE&gB;Bw3IIWkzVh)8RVr~Uz_v>Ep!IdhO_^9`_(oPbH zN}1rNt7@r`t}cU~OsBCsdOC4)admve#{@sv0JsYq+o`}dU3-4xpcHxB-Qbrb{kO2wBgieCz! zAjq$2kk;9hs51c7*j!pq$VC{NKr_C-FsKoN9eI6{Q?A&o?CiL8l@H6+{1O^^#n{g0 zdO&)zTm*DnZd)Pzt71dnK^ZQ>hk^rZW?Pr=x2I<1cQUmHMP)1JQCbObf1Xho3MNUx z5Ey|*cnY5G{`-*ybT5LMSBqERTgc1Hla!QnruEa?qyRg{TLF=$M|-8+90%|IDz^xK zLaEfAM=iM!c)U(@tYenJ(( zz$@r30!x?A*~JdaRk+TE#mT$hYs36d4TLlUQ4RPyA7ZAJf+7nQ+Q0zMfD6c=Xy~*d zqzeegKh{?MFm$SEkdkYu1Oeq+^+C|i{rASbt!;rEU&Y6lk3D7ML>^j$}SJ2l8@_p2&o1^^tI(EC>ZKRpg0 zQIC2x{EFF*o-#>MN)tuU-|+m%s&?%`nPkxMv)yAN{Q;9El6vsG-^h00{wK!_kHul&d%9DPueOS2pj~506c(b#! zy=)ZV;#A?|)qs`wg`}b1968KQLtfyQHiTShLdkc{H-&WVxx;I;kM(C{UyuE;rx9v$ z*$v*97Y|GhR;kFRmiYB+vu=i~K_yWMR`h*{w{AnnEVnwZx)O(AWC;gAAmZ97_;-Mt znJjB)0DKd7S}_)TnHGD>Ce`Q zkB~rTeu?x%#pcjS5SNKC>v-U3b}Z*^evFFMV~ea==LBv}ssY6gnTxpB z8Q~0uk7b)akAs4Yj;wO7@psGFM~@DE*0nIG1N2N&uQ+n}y+GX`^iIcCf;js>tQH{c z?|iI%EF{-f2pD$eSr4STziV_aW6qF$Z@sD^Z1$WmuZHr>Bl?5ehZn9-Z312Da$kH? zgJ`;$EBm5!Oy4~&46hVyvEue&XzxPk4o=O4LC-A^?SQ$kdYl_ zC}lcmL>)0*FB6}z_r%@st!u_zY+p}Y+AJ=JW#vn&>jt8Bu=0M@fT%a+>ujplkc1Ar zDqyftT!6Z~yrJTuj`^bTWu?9I=II2H!#6WGnddSyqa}dIPO!I3VUTUqoO65OIHG6a zi{;{xJz_gM#8%zZHq_RH=}LT|_eKVYO3#X}|GF#yadJc`+|*DV_!&b6z-5XOU#S2e z(Dqny#VJoy2Z9;*_hRH=Rtorl6{1pGuOPUE0pY*{FW|Vue|u!7;I(eG<}oC|940Ok zAjqcaGpYIy`0kJ7y6&qC?%iwv1Qc4O=0hN21HG25* z#RLOOuHLvCB_cPKEDvK*G=J!JnB@NYeugN-9Gqu7zj#wi>K=Z5SMk?0l>YT|^fBvf zOga~Y1h4%hkz>JA?jZr6s{}=d+u=QdNakOs7(%D{#-YbgMH#AT$zaz+NUenR@NS+@HU+#9u=Fh z{Ys8kbwl*CNAbHvkNMQw6Fr?kuN)|9f@Ff%$>u=e9Ec#4AlF53`6Tl9h(~8ERiCUn z68j|>#NJS~&K=I*g2ZKu)790k;GM5>Cl+j_q^0)#Em(6KOA2i;0LrpTc8{hb_S;r$A@s)^2>|-ip(cja<%q7X zZh$|y=0J@05^xq@%FE=?QzG$DAe>p?etL9msp)7cvp?EPlEYs=|F|1a;QZ#T?hK+(1$E5wT@Uzy zirA^i=T+`OoWMel6F1Bf9T+=25;C=!gU;FDgUD3Y3Hxo()iG6zrE5?>=GM%xeJH ztJTMM?bHqsNaC6n(>EV+M(T|Q!TUVFFx&j^?Yqxv0Eq-HE-nE9Z;*le>nuF^YZKE# zV?rOIu;uu+9c?YVChdNr35MNy|C?6u`eb5lsdn-u>g9z;%eBtU_RqN7)T@TCtUehG zfR}62yGkLvzInQaL@qevxab}|3m-FY+2DIqZ4ruTWU}7d<&7i1mUY|oq@Nm(BR1|< z)qp1p)9qFuG6ZKzbU{6xrY0vPBqhOn)&=z6{k5vs2Q4tKz2{g!AmoqFs+cfz^%YAAj`yl;yqWiPUz+3wtgr0;tRJi8rNcq`rBz@M(75vIZG@saEWKX20S&zmGopOKQLvqwm{x}QOAx!uZIx*Q+x^Eux*97?Ho zm$+pN6LdaU{scRIyju3$(OnFR=L!YKjhw&tXY`iYxfA%fBsF8E=cpm0Vlo6LjAYT^ zYhq>BNsMrK{4JnY0^TGXzB0On&K1hFFx>}klhBZ{+*{(EJ{rN(jBv@TH$kaWw!Zwg zqg?T_HtOxp<|D}NXwnor%C7f#4oT@xN&L@87G`H(Ic;H+g5MKcCe%r~g&I7;oVU)l z$K!j*w4(ZMr{y`c7e2q1?;VjlTUIr*yN_WdB7Sf*ML;$F(ZqVGqLEW<{+r`pERUw+ zoEI`};!K|0;MOJtI3UpGqb8J*IJN|WYN;gSSM}Qnv8Bg-T~0O9Jp)R5 z;e*+ks|*xC#ypZk-q*g5e(4mLTapA1<)%IQpn|v1upj&@5_;@^UE$G;is31#msw># z61O)q=kE+*hp1zrur~DKs{cI)s@H>ogehCy5boQ!q0@Wu*Q*b$7~UFh@y(ND-awqH z(B)7f^!OfsUlH>86IK!uAaB1y0UknOWL039)iK?SDgdB@;=i5S5s8y(dsPISH(k&B zelD3>^0L_IdJ9fbh$auy)C_&Rfw=FIK-Ot(KFmY}_TWpO9cAhfQNf3A8W#~+WN6ww zP8{#$mR?kjGNeq~eUfczE^i{fJ3w)Y_$W{s92%(yZE)Qnc;}t2xioTCio*vBsvefB z7EStkpg)sF*e{MOP!F0tL85bYsgMNRmI!iep!HoYd}Sn=FHUP*h{tX5=b-ejAR9^g z?@f!F$QHlDj4a}wBbAfdBC>NWRN)?)W?<5;;=Uem7y`+59*X7211_2ae^L%U)+XihQ1|fruT$QdU|dztKWe zy!c%Cv(m!|E7)gab%=RkwD3*!MBIUw)6~=y$PN67qc)LPI3cw()xpbhJSHLbn*+qR zddEE*hck6=BRnc2i$QncpZy{Iznq0L>VT8DRt22YylfdP*d{8IN~v$;f6WV+AJl?O z!=8PoW5xpg!J`x5w(AtjpubS92DFt>JmrFGJ-ofLq+jx@&j)b(Df^6IO%%}>QAhfr z<(a!@(XkR5W>n|@wGI@4{}>$*UU4!{t{mD7C~ufKi}GFZxUCSK#X2hEt-*#C34oHO zzDxg@H;Czra2|DqUQ)`RRIE@yE^`sb-?&?-#igJb(8L$&I;8F%S$SBRfsIYcPBj1k z*%WGk`Td3!?9K{Sa~VHmu#Gm;)y}+oKE0mKZ4Ug>P52;Vig!0xOe*W5wCS*(+;ntz z;g?*znLnTyI3tw?y3{p!cZ=Y#JojHRZO>)O1QnG0boB* z7Wm~?^%t-y{8@}iE?z}B>g%Q&v*bzrW`4o(j!H;Da`1|HNuQRrB8)c_gAPjc&%q~fnJe|5h~`Utc7YCAG4pm<;eiW6TRTX7YggrSVny7 zh}`|bs&H3Pop_gzL^^WytDtK%9JP>-DzHMMGZgDTBOCC+*0pNRn8QwTX1dR2A!kVL zkhH~8<>RIocemK4Mck1Bm zkelK|$r?E^OgP)c#2}D76rc&agd1)zBHfwgT&E_(TM4~f4(rkxnxJx@{N%X#0e);ji(Yy)HFY|PImGZYT zBQ|TQ2dlvtkCwesTAacf`-&?@le6Y04ZW5t(u<+)0UXG4^Nizlb|!dA6WiA|K3Ob! z5xnI0FK>D*1xQAWj}#gh4Lq=BO%wcsR`i$^SF!F7@Ug*pXg{8b`g@D}V?Vvph(L{< zbmRSVnNZ|U_oig8-j!d?2*#>sP}wCG<6wBja`xeD6Fidr=I*sF`evqpYqYeLewe9=6zr{ z!~k%LxazzM}5uSiXXX2TWgrf<6xrnFJB|T3%H}O|}NU?2Dhm z59+^4t}QZ<9Pq*Q`ghcuhi{S76n!64n4sW5+wRYDsK+o;@~-vVnhZ93W@%8Fq~!jN~U;@ z4T1sl5vp~SQ`wDHrlo>@hc4b?wUZq&k$b`k*$=K@o7Z)X&N|Hc^p()5;Q=frC6tfJ zEbFkj8oQgk5l1TH2hns|72f}Ix3G{K4O7B_zk$F*cpa2~yLk2TnUI;s+=qVNKeHAw zf$mb99-3BxXF`?lLQsa~V-}=)aUcw^ea^&Nw8@OBm)6>)vwaSWkMMzru)p`?4TWMS zcj&K}KPA+;#DwcGY6RU15?6nF7TMuTyWOQUEmC5LC7tP1oy~dG&vHST(R+}&%r^4& zz6ZULoZ>{y0n1KX!x{Hnr~qo$WbhWacaD1I;?uLtG*xy(4m7KNzjD@Hf1q( z2m=D=o!`Ff+Z&UcE@#(dhqUTAo%Q)WyjPl*DFSAlgv7+1xjxNDtZ>j+kOiT53O+T& z;yb(N5;&C0*f_h)1`Zna&?j+qbtOWIuxzA{juzh!kKA`(P;)pq1qZh1koVEx-0RuYtOH7N z$EhE+BW@@?vp!nFJevGF4-d>=e6K&E3K`!I&n_+r+}|9+c0e=F(tY!>J_3SA-n|}H z`0qpbMImUfuHvQsX801_xM!%>_JcY&aH>Ek_Q1{*n$5`qDo1>%Dr#Kz3P-3HQ5P zg9xRyIAVwaF|*~Go#Ro_7=B|X8ygY!Oug0K-_*EtY%VrK2@_;OTn0cN@PNv91F6lYJxtL$|pxCDx3QBa|nb8GAjCVjNez3Ra@Bsf%Q|MUr9} zx}M_*;X*5NF+V@m`prI5T#DF63mnh7HFyH1AFM5FYipoA&HO{VYvs(xJ3-cuwcy5s z$p!51%JBz0_teh8mfUX26{P!8DHgG?-|zXcmtGQyc+B-rU?=kkAA> z$dt}@H6g5w03)p`AVgOCiU}U@m~Zx)8+{0UBrTM#Le7JylHNCd{cR3;RYeO&_>ivG zGE5b}v2(N4@S^{6&u@j6dRs;P{0I&Z_-~il!=$*`EX^4Bz8G*)T#J?0W6iNsMMR3X z*R6G%0K0qHCv_aa6)Lm=pEcm zBr|tL;%jZtD>}`jq}OiUu>*goRgGOp5XAm1I0$8!L-%g-`IkrkFj(%mxZ=;e<0gUq z;XrEpuS8_XL@rfx8CbG3q^8CbncK_b#CNnyMdkQ-gdtm}`;(~iamCgm`y{*zrcKtk zvT5m>(csAP`rRJ0u;zPDRB@Xffp<+AWbqjG&I&qg!8-nFt{9@;_4QQ zI+Xftm(+j}L-K->4PA%8GhmtoTwp@i$9B8sS|8`@(XP4(MsTQ&CGVOpZ4|SRo0E}# ztZEa!?A{9B!~nK+$)EYia?)pA`K8aOQ?!g?=*X4YA%?+JUl)~Le%v%snGlQFumxU( z?|Ja6h5-Gjt-TL98oBggC%OMZo#h|^uBv*up?EnBUIF#jC2XOO{=LVx?z4z4wEl}C zqS3i#R5H9>V$b{908|PF)>CzCnpuMUx6krdo2qXl#&g^NM5}?17qc1&pbUL>;j!+@LEY0PgU%6X+Ts z;za?=J%p2y3A<1WIiCM(E?w87oaX7jb;NeQpG1YuOVxuj@2r?WSqJ{--r<>PEp5?6 zk9~miW^=o@dTSQ~r0vhO_h(Dfg}|hn4hOV(I-O}pv(mi&kJ|EKES<@VPiCr+e2?Rq zzJl(QC;w`C#mm2h8=kiz*0uXV&}zW3>#@JjxIGM?#K^vdb{$sC0KB(26C~e40_~c| ztrHeR03O@J#c%~;8AnG}Abk@Ve2;LI(5qVWMg`}s*pQ^ovrVD}OH^Sg`y6#&v#tzWIzf3sb z@VrS$O1n8&3HNc_0d2HP9_J1YFO(VV@KKb(^H9*1pj3~VzMGLgLTBMkO0tT%ck7Yx z2w&(2%D2ObUzj@9P4@?~jNF4E@D4JiC&ys>r6Ihx+o2qv9M;}``&xR0c^W3u&tkYB z*R2SVRl{&cKIrP`kMxWqi&eenlfuEI&pKL^h_PRbzmpk?AhD3g#TOE>3o=!bZv*Va z{7`{zc#S+0Kncl`bwPvoW|li(-Dk@#)$9J4Ep7D@)Lx$H4oY9#brFie=9~^WEqrpD z{CfJ;RVgTrbQ6^xtk}TAuUJU{{Jf}Cfn1#Be;aM7%w-zyefow1ZSQEbe&;5-c3+js z{e82zXcr=G9rxl>Y>j=N1w6rYWo#vjnY5TLH;!OtbkR^37CSEgoJ&oT>86P8Uzw;q zb-)~lOcIlOJEd#(-(K57?v2PGtSOp2#ciK)$>Y~(xc6io_*tzdux8Jb+ny-}Z;-dH zcmmacjEkWe*ul?_*iu>hP%}WQxVZhTr1}V`3jw5V7qGcOexVBidykf*d1_`Jf&|V@ zZ}p;0s+=Z7m-gP&8_ram$FrdRk?dyuLDMPVIroZ^m`8*x!|4)3Jay0@z^!eC(O5RWgKz>~DoP|Pn zbby8Fm^OZIBRKAq8b>Q?`V7s>R|k*z_!3iCq=w@3hb_lF*C1>_ zC-`&i5amxe!Tx5kwwuH9uDI8j8frX0xac@yIj|kn=cm5E22GP#Cmaj_|21ZnMZAe@ z{d~z@#oUDDe&%+U$X2RoMJ^82Em=|$&NRFIlEpLY8~m5yHSjq6n#vJq=qEo*l)0F5 zUC^d-EX&UI(B`gmTBH}W8}1M>BwJpFz6yOrF>Pk*Q${6Ps#%z)4VSPF@dq6i|3?n4 zeqRFgS4sI~k~_(Q;|V>f{YMrB43<||DiF;Tk=z}7mX|7Vq}Z2hYT%^o2vvbr`?iNv z7~`uYe?hM6d0U?Iv&CbrOuXIuyf01B>q61X`^YY@<#+FxUz)(h$L`0QiZyVobJM$< z2dd4nxS;{8|F5&J46CB;!krD0n^0*HRHPdvq!9!}LXeW&2-4jRTU1iIyBnlCHj>ia zsS?uNbp~Jc&F@_2I{XA?o?3CQd#zbdx%Y*epkf#Ymxw84CfQwj0Pnk4N19+uKu73? zchTc5bNU&D?8hTG^UE&zvwIu)(bi?2sk1R+@mG@gP{XxgJ(v~gUv{43c?hpiDhnKJ z_`hPvB7q($d4PDVR1b`4?16dp6{4Vhl)D;P4iNM}L-Na#tn{UAl!iT27YHDNgEb3i z1zs&DX1ZcGH;`F#Qx$S{v}7)L6fSr?&2m|k^vJ_ksHLN=JBPp(dyZmx<>xfMrxJYjjmpC(3egWADMjVp4qU4sF({=h?fOVr>fu4fu75Uz6qP z4&EdhRh8!fn>R{+=PiNEGGJTi2U*RZ3*x+Zk&hkA^;EQ&-x;H3B0XjKqI5(M zn8cJL?-<3=sT^1{q(F-CyQZ1YddWH`^c{I_%n#YrY<;ItB&cDB&DBAD>dE*VRc2N% zj=4);5%Sscb1l(hj(e!5Pn2hko%h(0umH4|tTMXumW7ht91TDb7~}^b6W2o;$jeT~ z+%LkH?r0Lb*PibcY@B-;Oyaulqzc0LFZ_))QsM51!`$AoL^l(|m1smP#;$e1-az_c zUq24Zd(|A^rM@t>(fHU?ISBFV*d!_GF|bnR!+Up@MsAJPid~eT3PLr42D|Ap;K!7k z*}i-}QE|tXy-iF$m!JTY%fHN20Ai%Hb+)h~M6Tva83-UttlSl{j@=|&SI8>U2VwtR zG*%a6IKR<;kvr(EDUiOUR9)(aAiY()5 zWnkSI4MmvIgTkuom-OQ-@Yhq!1$s0l>OW)Iof7R*if zEd2FIWL}drT+bf;_ER0xhfkYz=0e1HABkW*9j0uQ`0e%*)KI?L2 zq*e;a!bY!nVXIu!i`xEU7JF)gtRMab{=>R8QM7#DQmKL8rmC`miCT>0Po;adZeP78 z6&}dr7(Z@8<%V({)6ABs2B3kTm^njDC`gg=R}OV$zk{{{cMu%}9y))@;mYw3IZRY{ zbXwbMzTusGlsVZO zphn>S(1@)fdv8UsjI8O+;~DoT9}q`N=`{YY-k%F#BSPlGC~+`6y=IYnXfhlOL8@sm zV-)X9QUM*i72Zb7_H#nQ5J?n(0j~LD<-g;tAC}^1jJKH{?4#6uxrI&&j&-y3-M>4E z6>%wLrWDHw_sm1#CtInc7G3nf$n!@8X~$N?qhBpiSD<$%>JnW>Lr&q$x=ZL8v|lmY z2LW6ZL8gxv{*4o&jGzB%Q8^c&V?IxL+z*V*`3Lt2Wo!2d;uNe*Yg= zQm`kGj|*%Slf;EY#a!RlxOc@Y{BQ#xe)$m+W~{K?(*OW@gRy*IqVMX-Kk+>)pEG|p zz!(OPQDPV$MSTSSJ$PVFCKw}RUBRv6sOzzirfW%F0t#G@;C4UG|345rz3yEI%h!Ac z6KxBLQaaC#ugT9DYY4mDBPi|K8T)*?PC4frC?TkA)+z`hM{u%`4! z0)D^n%@r-2nmc>zii8}zS~CdN|J8?j0SkKToq| zeiPf=psRIP;ndooUSmVDWeG>SGFPSZEwqXSlI4{Oy@oarz4&~rA3b0ND}(;oj2i3| zEsY{{BL|pY7re?tOIfe=mPRylqH9F3W&*3%nSfgdp8+ZI(3H%}i{Q57O(-T5uJI;@$e$?J(rYcyx7 zq_?4E67Y?H+j-7v)^|&pdI@6MCYg>4)~Gk2<=o@oM%-uuC$ecxg; z9Hr*Jdn4={AMJ3T=aR>%Gc?zuy=;@r@Z4S};RE9#k}eRA`z7aYmhs;dga4NzA~J8e zq-w&4cbqwGnqLapQ6(vdt%QTUL5;vpOmM!2Eo|U`xOv&FmT?Xv^kP)?85T9#vq~-3 zn!7$sY0q!qBOX7Fo}#KxTGbEY$1?P}7fs@G2g>B@O-LRkO`B@yn27Q6I$PCrdZp;@N!?mEI$JW$3otcyN#!%;dxy0*nIC0so6cY9yo7YYD7MMK&x%jdgRF&$t4#F;q&?aMc?i@^+X%lNC~9UzrBftmMe4S+~?C&~i6jsk&7ixY)a zr3kqBhM4t*r9VYS$px|!`jbAd{?Vn>QcKALGYP3GSL}y<7%uT(Cxd-SgK4(*gN-?U zOJwRwpeqic0g4de%CSEn5sP|^jS>Qu-_|7axL4!ld+5nS#-vqJqWR5Hf(&@$r;thV zfXV|b>i>Q5-N7=98BJ5Vm? zs<@x}l}cOd_WCCuvM|=*u9uOw&(@!$#&MY)q4qx>m8%1m0!6BH>(D&HUWL6^zp~KB zd3R@)2MchU_2$a-=LiOSuK(6p`pdB;EkYRJ1J)3u%xE42=zp1^oJ{PNjGftU4$5my zj-@f7$%JiX&~=R%Y|MxZ;EzjsP_#aLKXwTJqzR`BHSZMyxA%%h`}S@&UJm1B%MF)`lquoFPSP63M5LiYu>h(a&m^GkSNJoBsC^} z3V4J8zM;*fOHtPK;W3jt`Uf+Thdqx(M#`CpnI#x0)6qVtp+*rr6>&zrqRK!Q|1Z|y zn<8NNqMD92QZq&`qq7-HQW-*7-quko=u$YW>yi_q6-X5?s&%SWy7A?HdS@La0kIRq zoOT)&QIySSQyK5Xm8pKq%>cwx{PtsD8s{2VLhEHP!}sogftfI-ZjJZkoWiyxy}noV z*nS1$ia_?dL?KdNr$U}qaW>#F8Eh6R{IJMJqJnq%lr9TXh$$!vInDM~9^iTNie~=P z7;hD^fI5wJ{|^TFf88A?$;lWvvK6X4jc2!D5N!?Ka5;%5PY5Rwe08Gzmu9JJ*jL=A zZO&B(a!=xa4utkU2~G}NmQv#v>=I%3*HN&Zj6ZOJq?L)MQr5|T;r{c+xR}evUtLi3 z0uzGE-&?n_f{bZhIhr1d*23>I$8}kI{DV-W48-`=b}I^t^9H2a=gqczt`2L&_IqoP zG!H+P1~c`anGZuILw8c~o)coXnkJ_cz`r&m&ZZ^VK(QyY=^p=RQ@Vd07~!Ae`vGId z^MstN2iaXk-!}~rx7~k=aTy#D6}=OYm32T4t*ELc=YRf#D*pl9!0Oc>)Oa=sDx~_( z2S2G5Y_zRa!OAKneguey*ZN#NsAH<}xA-QVPCoE2KL}sE{&}4_cs;r6-cu-IwR*1> z>^t()X=GjD24hJOnU&qa8(92arsw|7`VmF@^Pd6SRj+hAA+T5a#}O9~Ri0YfEU|>; zTdf|7K!3jBrU_dFO7_BD-O~CV*sbIbqI=B}{5H)Ptdb-9I-Py8&xGP%oeOxUZ@_=H z|MVW`cHoyM;`DUGiDpImue&>PcSbDDM0{_ZHGZ#naPa&UVp7!JP$Ktk=41x;V+9

    p0NZ!WK-SDvpILX1AY_?Sw+>6=zV1W^cNhBJ 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 diff --git a/naked-objects/etc/naked-objects.ucls b/naked-objects/etc/naked-objects.ucls deleted file mode 100644 index 8e9afac6d0af..000000000000 --- a/naked-objects/etc/naked-objects.ucls +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml deleted file mode 100644 index 88c982dfd795..000000000000 --- a/naked-objects/fixture/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - 4.0.0 - - - com.iluwatar - naked-objects - 1.18.0-SNAPSHOT - - - naked-objects-fixture - - - - ${project.groupId} - naked-objects-dom - - - - diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/DomainAppFixturesProvider.java b/naked-objects/fixture/src/main/java/domainapp/fixture/DomainAppFixturesProvider.java deleted file mode 100644 index ccc11f2b8ece..000000000000 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/DomainAppFixturesProvider.java +++ /dev/null @@ -1,38 +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. - */ -package domainapp.fixture; - -import org.apache.isis.applib.annotation.DomainService; -import org.apache.isis.applib.annotation.NatureOfService; -import org.apache.isis.applib.fixturescripts.FixtureScripts; -import org.apache.isis.applib.services.fixturespec.FixtureScriptsSpecification; -import org.apache.isis.applib.services.fixturespec.FixtureScriptsSpecificationProvider; - -import domainapp.fixture.scenarios.RecreateSimpleObjects; - -/** - * Specifies where to find fixtures, and other settings. - */ -@DomainService(nature = NatureOfService.DOMAIN) -public class DomainAppFixturesProvider implements FixtureScriptsSpecificationProvider { - @Override - public FixtureScriptsSpecification getSpecification() { - return FixtureScriptsSpecification.builder(DomainAppFixturesProvider.class) - .with(FixtureScripts.MultipleExecutionStrategy.EXECUTE) - .withRunScriptDefault(RecreateSimpleObjects.class) - .withRunScriptDropDown(FixtureScriptsSpecification.DropDownPolicy.CHOICES) - .withRecreate(RecreateSimpleObjects.class).build(); - } -} diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java b/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java deleted file mode 100644 index 58b656a9816f..000000000000 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java +++ /dev/null @@ -1,72 +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. - */ - -package domainapp.fixture.modules.simple; - -import org.apache.isis.applib.fixturescripts.FixtureScript; - -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.dom.modules.simple.SimpleObjects; - -/** - * Fixture to create a simple object - */ -public class SimpleObjectCreate extends FixtureScript { - - // endregion - - - // region > simpleObject (output) - private SimpleObject simpleObject; - - @javax.inject.Inject - private SimpleObjects simpleObjects; - - // region > name (input) - private String name; - - /** - * Name of the object (required) - */ - public String getName() { - return name; - } - - public SimpleObjectCreate setName(final String name) { - this.name = name; - return this; - } - - /** - * The created simple object (output). - */ - public SimpleObject getSimpleObject() { - return simpleObject; - } - - // endregion - - @Override - protected void execute(final ExecutionContext ec) { - - String paramName = checkParam("name", ec, String.class); - - this.simpleObject = wrap(simpleObjects).create(paramName); - - // also make available to UI - ec.addResult(this, simpleObject); - } - -} diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectsTearDown.java b/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectsTearDown.java deleted file mode 100644 index c0319d95383e..000000000000 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectsTearDown.java +++ /dev/null @@ -1,34 +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. - */ - -package domainapp.fixture.modules.simple; - -import org.apache.isis.applib.fixturescripts.FixtureScript; -import org.apache.isis.applib.services.jdosupport.IsisJdoSupport; - -/** - * TearDown/Cleanup for SimpleObjects - */ -public class SimpleObjectsTearDown extends FixtureScript { - - @javax.inject.Inject - private IsisJdoSupport isisJdoSupport; - - @Override - protected void execute(ExecutionContext executionContext) { - isisJdoSupport.executeUpdate("delete from \"simple\".\"SimpleObject\""); - } - -} diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java b/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java deleted file mode 100644 index be891158a0d7..000000000000 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java +++ /dev/null @@ -1,95 +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. - */ - -package domainapp.fixture.scenarios; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.google.common.collect.Lists; - -import org.apache.isis.applib.fixturescripts.FixtureScript; - -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.fixture.modules.simple.SimpleObjectCreate; -import domainapp.fixture.modules.simple.SimpleObjectsTearDown; - - -/** - * Create a bunch of simple Objects - */ -public class RecreateSimpleObjects extends FixtureScript { - - public final List names = Collections.unmodifiableList(Arrays.asList("Foo", "Bar", "Baz", - "Frodo", "Froyo", "Fizz", "Bip", "Bop", "Bang", "Boo")); - - // region > number (optional input) - private Integer number; - - // endregion - - // region > simpleObjects (output) - private final List simpleObjects = Lists.newArrayList(); - - public RecreateSimpleObjects() { - withDiscoverability(Discoverability.DISCOVERABLE); - } - - /** - * The number of objects to create, up to 10; optional, defaults to 3. - */ - public Integer getNumber() { - return number; - } - - public RecreateSimpleObjects setNumber(final Integer number) { - this.number = number; - return this; - } - - /** - * The simpleobjects created by this fixture (output). - */ - public List getSimpleObjects() { - return simpleObjects; - } - - // endregion - - @Override - protected void execute(final ExecutionContext ec) { - - // defaults - final int paramNumber = defaultParam("number", ec, 3); - - // validate - if (paramNumber < 0 || paramNumber > names.size()) { - throw new IllegalArgumentException(String.format("number must be in range [0,%d)", - names.size())); - } - - // - // execute - // - ec.executeChild(this, new SimpleObjectsTearDown()); - - for (int i = 0; i < paramNumber; i++) { - final SimpleObjectCreate fs = new SimpleObjectCreate().setName(names.get(i)); - ec.executeChild(this, fs.getName(), fs); - simpleObjects.add(fs.getSimpleObject()); - } - } -} diff --git a/naked-objects/integtests/.gitignore b/naked-objects/integtests/.gitignore deleted file mode 100644 index 88dfbbca9e7c..000000000000 --- a/naked-objects/integtests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/translations.pot diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml deleted file mode 100644 index e4006561ad58..000000000000 --- a/naked-objects/integtests/pom.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - 4.0.0 - - - com.iluwatar - naked-objects - 1.18.0-SNAPSHOT - - - naked-objects-integtests - - - - - src/test/resources - - - src/test/java - - ** - - - **/*.java - - - - - - - - - ${project.groupId} - naked-objects-fixture - - - - org.apache.isis.core - isis-core-unittestsupport - - - - org.apache.isis.core - isis-core-integtestsupport - - - org.apache.isis.core - isis-core-specsupport - - - - org.hamcrest - hamcrest-library - - - - org.apache.isis.core - isis-core-wrapper - - - org.apache.isis.core - isis-core-runtime - - - - org.assertj - assertj-core - test - - - - org.hsqldb - hsqldb - - - - - - - - - diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java b/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java deleted file mode 100644 index 3ac5a1d75f2e..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java +++ /dev/null @@ -1,60 +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. - */ -package domainapp.integtests.bootstrap; - -import org.apache.isis.core.commons.config.IsisConfiguration; -import org.apache.isis.core.integtestsupport.IsisSystemForTest; -import org.apache.isis.objectstore.jdo.datanucleus.DataNucleusPersistenceMechanismInstaller; -import org.apache.isis.objectstore.jdo.datanucleus.IsisConfigurationForJdoIntegTests; - -/** - * Initializer for the Simple App - */ -public final class SimpleAppSystemInitializer { - - private SimpleAppSystemInitializer() { - } - - /** - * Init test system - */ - public static void initIsft() { - IsisSystemForTest isft = IsisSystemForTest.getElseNull(); - if (isft == null) { - isft = new SimpleAppSystemBuilder().build().setUpSystem(); - IsisSystemForTest.set(isft); - } - } - - private static class SimpleAppSystemBuilder extends IsisSystemForTest.Builder { - - public SimpleAppSystemBuilder() { - withLoggingAt(org.apache.log4j.Level.INFO); - with(testConfiguration()); - with(new DataNucleusPersistenceMechanismInstaller()); - - // services annotated with @DomainService - withServicesIn("domainapp"); - } - - private static IsisConfiguration testConfiguration() { - final IsisConfigurationForJdoIntegTests testConfiguration = - new IsisConfigurationForJdoIntegTests(); - - testConfiguration.addRegisterEntitiesPackagePrefix("domainapp.dom.modules"); - return testConfiguration; - } - } -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/BootstrappingGlue.java b/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/BootstrappingGlue.java deleted file mode 100644 index e41399fdd7d8..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/BootstrappingGlue.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * O * 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. - */ -package domainapp.integtests.specglue; - -import org.apache.isis.core.specsupport.scenarios.ScenarioExecutionScope; -import org.apache.isis.core.specsupport.specs.CukeGlueAbstract; - -import cucumber.api.java.After; -import cucumber.api.java.Before; -import domainapp.integtests.bootstrap.SimpleAppSystemInitializer; - -/** - * BootStrapping IntegrationTesting Before and After Steps - */ -public class BootstrappingGlue extends CukeGlueAbstract { - - @Before(value = {"@integration"}, order = 100) - public void beforeScenarioIntegrationScope() { - org.apache.log4j.PropertyConfigurator.configure("logging.properties"); - SimpleAppSystemInitializer.initIsft(); - - before(ScenarioExecutionScope.INTEGRATION); - } - - @After - public void afterScenario(cucumber.api.Scenario sc) { - assertMocksSatisfied(); - after(sc); - } -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/CatalogOfFixturesGlue.java b/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/CatalogOfFixturesGlue.java deleted file mode 100644 index 7a75a038139f..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/CatalogOfFixturesGlue.java +++ /dev/null @@ -1,31 +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. - */ -package domainapp.integtests.specglue; - -import org.apache.isis.core.specsupport.specs.CukeGlueAbstract; - -import cucumber.api.java.Before; -import domainapp.fixture.scenarios.RecreateSimpleObjects; - -/** - * Test Execution to append a fixture of SimpleObjects - */ -public class CatalogOfFixturesGlue extends CukeGlueAbstract { - - @Before(value = {"@integration", "@SimpleObjectsFixture"}, order = 20000) - public void integrationFixtures() throws Throwable { - scenarioExecution().install(new RecreateSimpleObjects()); - } -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java b/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java deleted file mode 100644 index b7af9f05232d..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java +++ /dev/null @@ -1,50 +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. - */ -package domainapp.integtests.specglue.modules.simple; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -import cucumber.api.java.en.Given; -import cucumber.api.java.en.When; -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.dom.modules.simple.SimpleObjects; -import java.util.List; -import java.util.UUID; -import org.apache.isis.core.specsupport.specs.CukeGlueAbstract; - -/** - * Test Simple Object Operations - */ -public class SimpleObjectGlue extends CukeGlueAbstract { - - @Given("^there are.* (\\d+) simple objects$") - public void thereAreNumSimpleObjects(int n) throws Throwable { - try { - final List findAll = service(SimpleObjects.class).listAll(); - assertThat(findAll.size(), is(n)); - putVar("list", "all", findAll); - - } finally { - assertMocksSatisfied(); - } - } - - @When("^I create a new simple object$") - public void createNewSimpleObject() throws Throwable { - service(SimpleObjects.class).create(UUID.randomUUID().toString()); - } - -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specs/RunSpecs.java b/naked-objects/integtests/src/test/java/domainapp/integtests/specs/RunSpecs.java deleted file mode 100644 index 8a842a0f3140..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specs/RunSpecs.java +++ /dev/null @@ -1,32 +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. - */ -package domainapp.integtests.specs; - -import org.junit.runner.RunWith; - -import cucumber.api.CucumberOptions; -import cucumber.api.junit.Cucumber; - - -/** - * Runs scenarios in all .feature files (this package and any subpackages). - */ -@RunWith(Cucumber.class) -@CucumberOptions(format = {"html:target/cucumber-html-report", "json:target/cucumber.json"}, - glue = {"classpath:domainapp.integtests.specglue"}, strict = true, tags = {"~@backlog", - "~@ignore"}) -public class RunSpecs { - // intentionally empty -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specs/modules/simple/SimpleObjectSpec_listAllAndCreate.feature b/naked-objects/integtests/src/test/java/domainapp/integtests/specs/modules/simple/SimpleObjectSpec_listAllAndCreate.feature deleted file mode 100644 index 346aa2562258..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specs/modules/simple/SimpleObjectSpec_listAllAndCreate.feature +++ /dev/null @@ -1,26 +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. -# -@SimpleObjectsFixture -Feature: List and Create New Simple Objects - - @integration - Scenario: Existing simple objects can be listed and new ones created - Given there are initially 3 simple objects - When I create a new simple object - Then there are 4 simple objects - - \ No newline at end of file diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java deleted file mode 100644 index 66deaeb84034..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java +++ /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. - */ -package domainapp.integtests.tests; - -import org.junit.BeforeClass; - -import org.apache.isis.core.integtestsupport.IntegrationTestAbstract; -import org.apache.isis.core.integtestsupport.scenarios.ScenarioExecutionForIntegration; - -import domainapp.integtests.bootstrap.SimpleAppSystemInitializer; - -/** - * SimpleApp Integration Tests will implement this Abstract Class. - */ -public abstract class SimpleAppIntegTest extends IntegrationTestAbstract { - - @BeforeClass - public static void initClass() { - org.apache.log4j.PropertyConfigurator.configure("logging.properties"); - SimpleAppSystemInitializer.initIsft(); - - // instantiating will install onto ThreadLocal - new ScenarioExecutionForIntegration(); - } -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java deleted file mode 100644 index f2cbb1723295..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java +++ /dev/null @@ -1,130 +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. - */ -package domainapp.integtests.tests.modules.simple; - -import static org.assertj.core.api.Assertions.assertThat; - -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.fixture.scenarios.RecreateSimpleObjects; -import domainapp.integtests.tests.SimpleAppIntegTest; -import javax.inject.Inject; -import org.apache.isis.applib.DomainObjectContainer; -import org.apache.isis.applib.fixturescripts.FixtureScripts; -import org.apache.isis.applib.services.wrapper.DisabledException; -import org.apache.isis.applib.services.wrapper.InvalidException; -import org.junit.Before; -import org.junit.Test; - -/** - * Test Fixtures with Simple Objects - */ -public class SimpleObjectIntegTest extends SimpleAppIntegTest { - - @Inject - FixtureScripts fixtureScripts; - - RecreateSimpleObjects fs; - SimpleObject simpleObjectPojo; - SimpleObject simpleObjectWrapped; - - @Before - public void setUp() throws Exception { - // given - fs = new RecreateSimpleObjects().setNumber(1); - fixtureScripts.runFixtureScript(fs, null); - - simpleObjectPojo = fs.getSimpleObjects().get(0); - - assertThat(simpleObjectPojo).isNotNull(); - simpleObjectWrapped = wrap(simpleObjectPojo); - } - - /** - * Test Object Name accessibility - */ - public static class Name extends SimpleObjectIntegTest { - - @Test - public void accessible() throws Exception { - // when - final String name = simpleObjectWrapped.getName(); - // then - assertThat(name).isEqualTo(fs.names.get(0)); - } - - @Test - public void cannotBeUpdatedDirectly() throws Exception { - - // expect - expectedExceptions.expect(DisabledException.class); - - // when - simpleObjectWrapped.setName("new name"); - } - } - - /** - * Test Validation of SimpleObject Names - */ - public static class UpdateName extends SimpleObjectIntegTest { - - @Test - public void happyCase() throws Exception { - - // when - simpleObjectWrapped.updateName("new name"); - - // then - assertThat(simpleObjectWrapped.getName()).isEqualTo("new name"); - } - - @Test - public void failsValidation() throws Exception { - - // expect - expectedExceptions.expect(InvalidException.class); - expectedExceptions.expectMessage("Exclamation mark is not allowed"); - - // when - simpleObjectWrapped.updateName("new name!"); - } - } - - /** - * Test ContainerTitle generation based on SimpleObject Name - */ - public static class Title extends SimpleObjectIntegTest { - - @Inject - DomainObjectContainer container; - - @Test - public void interpolatesName() throws Exception { - - // given - final String name = simpleObjectWrapped.getName(); - - // when - final String title = container.titleOf(simpleObjectWrapped); - - // then - assertThat(title).isEqualTo("Object: " + name); - } - } -} diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java deleted file mode 100644 index d57454dc1955..000000000000 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java +++ /dev/null @@ -1,149 +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. - */ -package domainapp.integtests.tests.modules.simple; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.google.common.base.Throwables; -import domainapp.dom.modules.simple.SimpleObject; -import domainapp.dom.modules.simple.SimpleObjects; -import domainapp.fixture.modules.simple.SimpleObjectsTearDown; -import domainapp.fixture.scenarios.RecreateSimpleObjects; -import domainapp.integtests.tests.SimpleAppIntegTest; -import java.sql.SQLIntegrityConstraintViolationException; -import java.util.List; -import javax.inject.Inject; -import org.apache.isis.applib.fixturescripts.FixtureScript; -import org.apache.isis.applib.fixturescripts.FixtureScripts; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.junit.Test; - -/** - * Fixture Pattern Integration Test - */ -public class SimpleObjectsIntegTest extends SimpleAppIntegTest { - - @Inject - FixtureScripts fixtureScripts; - @Inject - SimpleObjects simpleObjects; - - /** - * Test Listing of All Simple Objects - */ - public static class ListAll extends SimpleObjectsIntegTest { - - @Test - public void happyCase() throws Exception { - - // given - RecreateSimpleObjects fs = new RecreateSimpleObjects(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - - // when - final List all = wrap(simpleObjects).listAll(); - - // then - assertThat(all).hasSize(fs.getSimpleObjects().size()); - - SimpleObject simpleObject = wrap(all.get(0)); - assertThat(simpleObject.getName()).isEqualTo(fs.getSimpleObjects().get(0).getName()); - } - - @Test - public void whenNone() throws Exception { - - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - - // when - final List all = wrap(simpleObjects).listAll(); - - // then - assertThat(all).hasSize(0); - } - } - - - /** - * Test Creation of Simple Objects - */ - public static class Create extends SimpleObjectsIntegTest { - - @Test - public void happyCase() throws Exception { - - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - - // when - wrap(simpleObjects).create("Faz"); - - // then - final List all = wrap(simpleObjects).listAll(); - assertThat(all).hasSize(1); - } - - @Test - public void whenAlreadyExists() throws Exception { - - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - wrap(simpleObjects).create("Faz"); - nextTransaction(); - - // then - expectedExceptions.expectCause(causalChainContains(SQLIntegrityConstraintViolationException.class)); - - // when - wrap(simpleObjects).create("Faz"); - nextTransaction(); - } - - private static Matcher causalChainContains(final Class cls) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Throwable item) { - final List causalChain = Throwables.getCausalChain(item); - for (Throwable throwable : causalChain) { - if (cls.isAssignableFrom(throwable.getClass())) { - return true; - } - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("exception with causal chain containing " + cls.getSimpleName()); - } - }; - } - } - -} diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml deleted file mode 100644 index f770fe3a04b0..000000000000 --- a/naked-objects/pom.xml +++ /dev/null @@ -1,407 +0,0 @@ - - - - 4.0.0 - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - - naked-objects - - pom - - - 3.0.4 - - - - 1.9.0 - - UTF-8 - UTF-8 - 2.0.0 - - - - - apache.snapshots - Apache Snapshots - https://repository.apache.org/content/repositories/snapshots/ - - false - - - - - - Cloudbees snapshots - http://repository-estatio.forge.cloudbees.com/snapshot/ - - - - false - - - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.3.1 - - - - [3.2.1,) - - - [1.8.0,) - - - All plugin versions must be - defined! - true - true - - - - - - - validate-enforce - validate - - enforce - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - -parameters - - - - source - compile - - - test - test-compile - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.16 - - - **/*Test.java - **/*Test$*.java - **/*Test_*.java - **/*Spec*.java - - - **/Test*.java - **/*ForTesting.java - **/*Abstract*.java - - true - true - ${project.build.directory}/surefire-reports - - - - - org.apache.maven.plugins - maven-surefire-report-plugin - 2.16 - - false - - - - test - - - - - - maven-clean-plugin - 2.5 - - - maven-resources-plugin - 2.6 - - - maven-jar-plugin - 2.4 - - - maven-install-plugin - 2.5.1 - - - maven-deploy-plugin - 2.8.1 - - - maven-site-plugin - 3.3 - - - maven-war-plugin - 2.4 - - - - org.mortbay.jetty - maven-jetty-plugin - 6.1.26 - - - - org.apache.maven.plugins - maven-shade-plugin - 2.2 - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - - run - - - - - - - org.simplericity.jettyconsole - jetty-console-maven-plugin - 1.56 - - - - - org.apache.rat - apache-rat-plugin - 0.10 - - true - true - - **/target/** - **/target-ide/** - - **/*.project - **/.classpath - **/.settings/** - **/*.launch - **/ide/eclipse/launch/** - **/ide/intellij/launch/** - src/site/resources/ide/eclipse/** - - **/rebel.xml - **/*.gitignore - **/*.log - **/*.pdn - **/*.svg - **/*.json - **/*.min.js - **/*.js - - **/translations.pot - **/translations*.po - - - - AL2 - Apache License 2.0 - - - Licensed to the Apache Software Foundation (ASF) under one - - - - JQRY - MIT - - - Dual licensed under the MIT or GPL Version 2 licenses. - - - - JMOCK - JMock - - - Copyright (c) 2000-2007, jMock.org - - - - DOCBK - DocBook 4.5 - - - Permission to copy in any form is granted for use - Permission to use, copy, modify and distribute the DocBook DTD - is hereby granted in perpetuity, provided that the above copyright - This is the catalog data file for DocBook XML V4.5. It is provided as - XML Catalog data for DocBook XML V4.5 - DocBook additional general entities V4.5 - XML EXCHANGE TABLE MODEL DECLARATION MODULE - - - - W3C - XHTML - - - Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio), - - - - - - Apache License 2.0 - - - MIT - - - JMock - - - DocBook 4.5 - - - XHTML - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-report-plugin - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - domainapp - - - - naked-objects - naked-objects-webapp - - - - - - - - - - - org.apache.isis.core - isis - ${isis.version} - pom - import - - - - org.apache.isis.viewer - isis-viewer-wicket - ${isis.version} - pom - import - - - - org.assertj - assertj-core - ${assertj-core.version} - - - - - - ${project.groupId} - naked-objects-dom - 1.18.0-SNAPSHOT - - - ${project.groupId} - naked-objects-fixture - 1.18.0-SNAPSHOT - - - ${project.groupId} - naked-objects-webapp - 1.18.0-SNAPSHOT - - - - - - - - - m2e - - - m2e.version - - - - target-ide - - - - - - dom - fixture - integtests - webapp - - diff --git a/naked-objects/webapp/ide/eclipse/launch/.gitignore b/naked-objects/webapp/ide/eclipse/launch/.gitignore deleted file mode 100644 index 3d9734548ceb..000000000000 --- a/naked-objects/webapp/ide/eclipse/launch/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/SimpleApp-PROTOTYPE-jrebel.launch -/SimpleApp-PROTOTYPE-no-fixtures.launch -/SimpleApp-PROTOTYPE-with-fixtures.launch -/SimpleApp-SERVER-no-fixtures.launch -/SimpleApp-PROTOTYPE-jrebel.launch -/SimpleApp-PROTOTYPE-no-fixtures.launch -/SimpleApp-PROTOTYPE-with-fixtures.launch -/SimpleApp-SERVER-no-fixtures.launch diff --git a/naked-objects/webapp/ide/intellij/launch/README.txt b/naked-objects/webapp/ide/intellij/launch/README.txt deleted file mode 100644 index 6659454efdbe..000000000000 --- a/naked-objects/webapp/ide/intellij/launch/README.txt +++ /dev/null @@ -1,25 +0,0 @@ -==== - The MIT License - Copyright (c) 2014-2016 Ilkka Seppälä - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -==== - -Copy into workspace\.idea\runConfigurations directory, and adjust file paths for Maven tasks. - diff --git a/naked-objects/webapp/ide/intellij/launch/SimpleApp_PROTOTYPE.xml b/naked-objects/webapp/ide/intellij/launch/SimpleApp_PROTOTYPE.xml deleted file mode 100644 index 9831f9a1f7bf..000000000000 --- a/naked-objects/webapp/ide/intellij/launch/SimpleApp_PROTOTYPE.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/naked-objects/webapp/ide/intellij/launch/SimpleApp__enhance_only_.xml b/naked-objects/webapp/ide/intellij/launch/SimpleApp__enhance_only_.xml deleted file mode 100644 index 06423bc48671..000000000000 --- a/naked-objects/webapp/ide/intellij/launch/SimpleApp__enhance_only_.xml +++ /dev/null @@ -1,46 +0,0 @@ - - -s - - - \ No newline at end of file diff --git a/naked-objects/webapp/lib/.gitignore b/naked-objects/webapp/lib/.gitignore deleted file mode 100644 index 70eee7e4f6b8..000000000000 --- a/naked-objects/webapp/lib/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# -# explicitly ignoring Microsoft JDBC4 jar -# (cannot redistribute, licensing) -# -sqljdbc4.jar diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml deleted file mode 100644 index 244d1737d539..000000000000 --- a/naked-objects/webapp/pom.xml +++ /dev/null @@ -1,321 +0,0 @@ - - - - 4.0.0 - - - com.iluwatar - naked-objects - 1.18.0-SNAPSHOT - - - naked-objects-webapp - - This module runs both the Wicket viewer and the Restfulobjects viewer in a single webapp configured to run using the datanucleus object store. - - war - - - .. - - - - - - org.mortbay.jetty - maven-jetty-plugin - - - - - org.simplericity.jettyconsole - jetty-console-maven-plugin - - - - createconsole - - - ${basedir}/src/main/jettyconsole/isis-banner.png - ${project.build.directory}/${project.build.finalName}-jetty-console.jar - - package - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.8 - - - validate - - maven-version - - - - - - - maven-war-plugin - - simpleapp - - - false - - - ${maven.build.timestamp} - ${agent.name} - ${user.name} - Maven ${maven.version} - ${java.version} - ${os.name} - ${project.version} - - - WEB-INF/lib/isis-core-webserver*.jar, - WEB-INF/lib/javax.servlet-api-*.jar, - WEB-INF/lib/javax.websocket-api-*.jar, - WEB-INF/lib/jetty-all-*.jar - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.codehaus.mojo - build-helper-maven-plugin - [1.5,) - - maven-version - - - - - - - - - - - - - - - - - - - ${project.groupId} - naked-objects-dom - - - - org.datanucleus - datanucleus-enhancer - - - - - ${project.groupId} - naked-objects-fixture - - - - org.datanucleus - datanucleus-enhancer - - - - - - - org.apache.isis.viewer - isis-viewer-wicket-impl - - - org.apache.isis.core - isis-core-viewer-restfulobjects-server - - - org.apache.isis.core - isis-core-security-shiro - - - - - - org.apache.isis.core - isis-core-runtime - - - org.apache.isis.core - isis-core-wrapper - - - org.apache.isis.core - isis-core-security - - - - - - org.apache.isis.core - isis-core-webserver - runtime - true - - - - - org.apache.geronimo.specs - geronimo-servlet_3.0_spec - - - - - org.hsqldb - hsqldb - - - - - - - - - org.lazyluke - log4jdbc-remix - - - org.slf4j - slf4j-api - - - - - - - - - self-host - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - - - - - - - - - - - - intellij - - - idea.version - - - - - org.apache.geronimo.specs - geronimo-servlet_3.0_spec - - compile - - - - - jrebel - - - target - dom.simple,org.apache.isis.objectstore.jdo.applib - warn - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java b/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java deleted file mode 100644 index 89d316d20f8d..000000000000 --- a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java +++ /dev/null @@ -1,158 +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. - */ -package domainapp.webapp; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import com.google.common.base.Joiner; -import com.google.common.io.Resources; -import com.google.inject.AbstractModule; -import com.google.inject.Module; -import com.google.inject.name.Names; -import com.google.inject.util.Modules; -import com.google.inject.util.Providers; - -import org.apache.wicket.Session; -import org.apache.wicket.request.IRequestParameters; -import org.apache.wicket.request.Request; -import org.apache.wicket.request.Response; -import org.apache.wicket.request.http.WebRequest; - -import org.apache.isis.viewer.wicket.viewer.IsisWicketApplication; -import org.apache.isis.viewer.wicket.viewer.integration.wicket.AuthenticatedWebSessionForIsis; - -import de.agilecoders.wicket.core.Bootstrap; -import de.agilecoders.wicket.core.settings.IBootstrapSettings; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchTheme; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchThemeProvider; - - -/** - * As specified in web.xml. - * - *

    - * See: - * - *

    - * <filter>
    - *   <filter-name>wicket</filter-name>
    - *    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
    - *    <init-param>
    - *      <param-name>applicationClassName</param-name>
    - *      <param-value>webapp.SimpleApplication</param-value>
    - *    </init-param>
    - * </filter>
    - * 
    - * - */ -public class SimpleApplication extends IsisWicketApplication { - - private static final long serialVersionUID = 1L; - - /** - * uncomment for a (slightly hacky) way of allowing logins using query args, eg: - * - * ?user=sven&pass=pass - * - *

    - * for demos only, obvious. - */ - private static final boolean DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS = false; - - - @Override - protected void init() { - super.init(); - - IBootstrapSettings settings = Bootstrap.getSettings(); - settings.setThemeProvider(new BootswatchThemeProvider(BootswatchTheme.Flatly)); - } - - @Override - public Session newSession(final Request request, final Response response) { - if (!DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS) { - return super.newSession(request, response); - } - - // else demo mode - final AuthenticatedWebSessionForIsis s = - (AuthenticatedWebSessionForIsis) super.newSession(request, response); - IRequestParameters requestParameters = request.getRequestParameters(); - final org.apache.wicket.util.string.StringValue user = - requestParameters.getParameterValue("user"); - final org.apache.wicket.util.string.StringValue password = - requestParameters.getParameterValue("pass"); - s.signIn(user.toString(), password.toString()); - return s; - } - - @Override - public WebRequest newWebRequest(HttpServletRequest servletRequest, String filterPath) { - if (!DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS) { - return super.newWebRequest(servletRequest, filterPath); - } - - // else demo mode - try { - String uname = servletRequest.getParameter("user"); - if (uname != null) { - servletRequest.getSession().invalidate(); - } - } catch (Exception e) { - System.out.println(e); - } - return super.newWebRequest(servletRequest, filterPath); - } - - @Override - protected Module newIsisWicketModule() { - final Module isisDefaults = super.newIsisWicketModule(); - - final Module overrides = new AbstractModule() { - @Override - protected void configure() { - bind(String.class).annotatedWith(Names.named("applicationName")).toInstance("Simple App"); - bind(String.class).annotatedWith(Names.named("applicationCss")).toInstance( - "css/application.css"); - bind(String.class).annotatedWith(Names.named("applicationJs")).toInstance( - "scripts/application.js"); - bind(String.class).annotatedWith(Names.named("welcomeMessage")).toInstance( - readLines(getClass(), "welcome.html")); - bind(String.class).annotatedWith(Names.named("aboutMessage")).toInstance("Simple App"); - bind(InputStream.class).annotatedWith(Names.named("metaInfManifest")).toProvider( - Providers.of(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"))); - } - }; - - return Modules.override(isisDefaults).with(overrides); - } - - private static String readLines(final Class contextClass, final String resourceName) { - try { - List readLines = - Resources.readLines(Resources.getResource(contextClass, resourceName), - Charset.defaultCharset()); - return Joiner.on("\n").join(readLines); - } catch (IOException e) { - return "This is a simple app"; - } - } - -} diff --git a/naked-objects/webapp/src/main/jettyconsole/isis-banner.pdn b/naked-objects/webapp/src/main/jettyconsole/isis-banner.pdn deleted file mode 100644 index 37543c93c333124664a254bbd5bb13846195959a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69658 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%0Ac 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 z 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 diff --git a/naked-objects/webapp/src/main/jettyconsole/isis-banner.png b/naked-objects/webapp/src/main/jettyconsole/isis-banner.png deleted file mode 100644 index cd9ecfe02a1f78352a0fb42d056430178a53ea3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30776 zcmeEu(|cu2(C@^yolH2f?M!U%I6Jm&XJSmuiJk1&wrwX9Pi&vO-*ecvFqpGWFMJOpqBEjRsfBW_gNm}Zs%C~P|@n6Xu7W|6>nH8D$^#F5Lkre$_Jw1hlks zVN?)TBXwhAsWy z-E%MIOQw0JJzrKk70=7nx65BH)GIWqUgG@Mhf$d!5d#rLc7#}eDqzh2PtKnJs73uB zIa;I#md-e143Yy95saMv3?eLmES?261a+x+V`@Tc`NjJQ*#43 z$<+OUfX%4LQP+kGz8VpLrs3AqzPN@uA_X~y3e4vBd^@fcqYTWq1W*Q+A6UXB34)u3 zg8bg^muFSIJNeF&Z;$-tc;F=fKf)JS*&*kGgwshY5pWpkbvZj1dosvV-)%=<9EJ3x zYCA_^=@@*+;W;2xV*e|2-p=Vl_*4>0elt|%>2q_6BgEH2*?7<1C&Q4Fl1UcN2sx(+ zFz|mj4gWxCz)PI>w5jU7+~#v0uE$8}c-ee3SN-)1O#{BSp%O8W{d>GwAFuD>-LFwS zo$l;)OEvxF>&ERY75}%4;oD|*tuDv8X`zyd#d%n|7=ejMPDqts!n|+@Vy_|T?<{&) zAax?xDEnJkCQS!d^tB3m;Xi;eF^_@!!4ESiRlVS^lEU;}wPXW!cU=u)*9$-gIJ8};_r z!ZuNWZok$h^&(0A%Pih{COv@dJEcCd1iaAuP3&jY6n_oQg9+U-#<#ceGBzQ<`^i@O zZobd?P=h)B1Qkm9mD7Svoi!w@8B^WKocYtvWP{vpfslH5SlJjYR+fKk^}By#6y^1A z`yLciaA3;ngaPJVpCTD%Xo66VAM9$$5J6@0FG+DzuCo;_sflk|Dfb>}!>%V=~&>_(qY z#~R$+tX?Xpvd~<~auJTu{h_@F-EKeiv10lU8f7b#K$e1EArr zL8I)}<>KFs$8Ac3{sxStF(S!J3l3F+k4~s|aya`44AL390ettL93Gy$1#P&V~_d_MO0mn^V&5i^zZ55`9A2Hqx zZnd2?{TnyhkLRzk+naVxe9!N@Z_|{TS`+H-P3Z@#PC!v` zSk6(%Xw@1)EhAvlOF;k`ULD+06JoZqv`eP{LHn9*&Y3USXB{XYZesN_?prmJ=y#fa z(oTB+ZSZYYAdd^x%lvUQ$(o^`)SUwk~uC2!DZgGK1{-N;w$(70rE^Bv3N=VSX@ zbWmQs^EMW*et;F3=j`T1bn<==BU@buSar_L{g?a{*NjcVLu~8xJ353Ih=k8xYQ0>| zo#LE(Hb+J8wHPSo-HzPdy#bu{|La+Y}Cd7GwvzBTDv z=DwKfz4UMGw8`5H7aV^*A6g!Y?{HnP^itYr7wN=I3U;6&wiPUC)cQ@wRJH_~8a z*>UIjkks* zr}^&3PNghH|8}$%pw7Y5-`8cU0-~aGfv?2&NC$?!qOoxFbA5L2(OX-uwq`OpoKN5V zV^c>V*7xpAk&9|u?c{r9ZImE#S1~gZ1ygI0TtH7=%~Xpq?sS+I$pu}_ug!;3#5fRd zj6$HID|m|%N7u*0MmdqBdClsymCb0CBMhANR)=R=a~KlA5Mr$wT-1n9!A-j>fdNU= z>E}n4k8xILB4ySAZvD?uFJq%~WOAzx)<0_%_KOz_4-cdA)jE%TmqNbxaj)yTo`24h zQI`VUG;_~2_uFS5iS)5D52&7{5r9A_576zaKJ~sqaYzE9gY*&$!f)TFSr#1qH_+0* zmwes5Z(72``UZVqRX%E*QUDU)yM$8BA{hW^F+cfPZ)oY9qkby@s`>g{=yS=BWvcC9 zZU7We53hj;toWLNjYJvib@um7oA%x%T3d&sB%HEsgqBHAKjRf{LPM?0p;qGm-(gvmP9l?bMsc z)wfm6UM_fJt`lu_RSNdM+c1$bD+0tolpIQY?UVThs!KaloStOlldIZ0tqJSpNpVDYc zwM?;H&s)I)w`a(@4(oqV?7~4I^)CqKqXP~P44q~Rmx8SdufRneq{^+l*YjZg>iYZ> z5+U3B@P49d-nr{ja-wQM-5#xclk;wNx;ICuPLl2R+nuFk>8UE2T+of?h4}ACNdR|( zpCc;`-0^xw|d$x$FU-{U4$ z(R{91VqFq8pRv_)P$Wcb<$qASTrIeCa#~QMhhz>1{K6l+51sOCeXI2|!(lr|%Qw-* zj>fdl=oMU+)(+)X?$TiuCR1j{IF0dRUr{LchAs+K0Ilu=YdR;7E(ohjXDCjZvK0LjHz6M%%iSIW`_5J`^W1~MxH6~Eb~_eSL?B@ zQHm;8ngIS-xM+sG(LdVxmLA!dBt;7t*rM_|%b%0d&8!$c-q%F-OkJA?^y#?y`kg#g zb|tf(wp&wYGq16EOv~C^h=Of#Jw38j~W6MXU#(UFi-T)Z(SGor(gJ6gc@nkUXM z;!o0*qZHJ=BB}DBQ&5AfuFPl^nto8xBko#rGWt315xpOBc$iD~yQgeiKP2)&8|+mE zBG`w6UM5{9FBX3nI;44OOb!b$U666DR4pYBV#dMlfWo$!!@2 zHDBkueY->PHjD7IOL>k0In4709x z?Rr$9=+>E1gN`k;G^j-uvbfu%7-cwbQd!A%{B;W#|F=p((!WE{&T^xnvRyKuoxnx zoxt?z{`q5^hEgS%Dm|^N8U_=)VPN{EIFOuQ>?Z{Q$tGeb{uo5<-to`Z*z7~3(@}%J zc4Aek(tzz8!A1W!HjfZdl}kqZ0h}o>bIbm;#75Yrwnj-Cd_a9a-~HCH-_hM6*SXLA z7!#kKZ~0kcN!wr->QV$F3*}kGRP7fQp)7P}LvvcdiPqgc?cL=~qbVfs-_CY4M16Zj zl8R32VJ(Et%lamiK38c4t=)U=S%sZpZr`23eGM6bCR1AN+v>I+Fs$LC>JePPSxZ^g zTUb1}XcfdxxFw_!wxiZjdu&c8(P6BHDPmzoZHZLxaBB_ieI(hI_4Nlr`_FGp1Wnz6 z9X141I>lL|boeV(8G3eW!&w9EV5@25?N!gZ-KJ&g>5Uim(c8yJ9#md%um}#Nb&mX8V#HbU}aRs5?z{(IQeM z6Byurkkccc-)csm3!G2k>QvdV`Zho#wl{#!G-1$spw@S z$M4O2T2 z?jN{oP=PvB5LO`f6U=Kw6m5i@7&ao?dI!en7@vEY76Y|(wP7Gn`w~ft_Qj#7onQ!7 zgOFhMk zrMl|(p=>O-SjQ!Mv&xmqt9&kO?8j;CcgLe~|CNomPtK+mC;P_@B8>Kbpa1F?=Wm%{Vgd8D_BDE|9+upR{SyM?-P znLn8vqQnv+hM7i&lEBP0YksrL>vlXl-z%FSwoCA`w@ba_%7V;I?FB7D$MY)RJK4Np z)PI#!eZwjCvj4fc?Z~LqlKAJbRs(ffLZUQ9bkHpSd~y)?fj87VI|(Q8&|k5gN10<% z6e=FFR92rM?Tk`C-&N1*8@#hl&}bv|Q0zN(hlNyyEVrrsW!-K$>&$VpHD}p> zx;X$eB?^F&S+Wlqth{pS3#vkHin?B?PU+rW`1dL3^Wh$q`L^9*{=r>;eg8YRjOA{Y zZ@cq#>Kf^kk%XU_A!Kl-F902p0JROXZ>*Yc#W38&rbj7k**d-4FdNulZ3i2$6^LGl z2#ddx#^0BS_3crNwGD@0o&vr4ReW2-*%8Yl4uncN8YszXq`70fd(DyYCl$hD$XZg$ zMp=P8Yv=%&`A2~rK-_on`Pda+E zr;9q5z?c&&5n{p!2EY(_X&P|ObdAW~z}wR8K@Pqdsp)ZTJ~_Au>JoZK1oUsPIr*5|r<->o|PPZfaz>Z#Q6vtj2T z;es5#Z>}H4ku*l1s8-~>ex`6dZ@v|CDR>s2UWGfuY^v^8Y4dc_ZZH@2-S3xctljNE zoJk@w`S#_%&LQd(+(shY1U1kh{Iw}}Xvf6VIOYql$Li3J+RVnw^~NxTN1<QXk%-4xIoUc!RneJmmY?kzW@0l(S*Wk9%Z!LE;{rZWYwle`NWVSW zfL4RyQcF6x|1WGUQx4e};9-8=`_U$+jcLE~*#&Xq zgB>CuI1O5%Y~9r5-Ou+jXO{O-7-m9!`D5WV458D0hbiRVI38pqld=LzgVXnIA?J4; ztk(PhoeX}yUWINmd0mu0%U5UKOlOD@SFg9*CHpPfd6mq`liOD_S33^6ePho{>(jbV`~2RTFwxUhI>rFIyQSp^_j4$CjB=ns7m=SG?CsZ^^op<~b)9~_J= zzl#W}ZL98*AuLownutIEX?lv$5JP{?;<9{)Iu|=E(qYmmF!{MNO4xXDJ%dU+9?}v8 z2;D{h(6Sl|Do=wZKJi%WYSR2?^Bf+-^s${`)@`trFZxl>V@zD}F(tt9x>UsiG78v{lcs+KHE3)-KzfQLi&CYI{ zlJ1GZ7I=erTX^&yXKuK6cn6D6(AZv&e+aK3B2;mZjG$}NK`G>J2&&;;;Fx7d zJrT>h*ld86STYm=5lgK8fV=xSs*;#O>pC2 z_DAf}43ZcsRkC>bj*d;_co`V?D*rkjU(}2PQn$fhu{L|ZFt$J8JKk!oDknPjI7bnv zd2PHz`aE^tukkhhl1g%oLR=w227OTH7q6#U>J1v3&#_24U%qhEtF3!pj4~)?K6}pS zC$8rDBhu*ZWJj!jaCjZBmYiw+S1l)9N4<;9sX}484BT7<@TRwQ)l?PtZhI8n;{2M( z+}8gSBh~LTz4RFef@chwVh|f!PO4+ugF4)bWsMpaE&(g`wmCL@ysyM(l1Dk7CWivJsJd2ZWmB|J11`%sdRI{*=(1s<01$3MF0BfHoM zP|x9XS1kKNunH8{0jYZ48oZTZJSzaZ2l}Y2fgRP#;|xd=cB&EdtvHP0@$Qe#wLY9g zP^u58mmJ_oh!2_j9eoMMfXL5X!kPZ8U}=-X$hF{0MT*Iu=Xj}B*0a~yZtF|GSQb|N zyf7epICn2_NI}Iu#d4!#uOWxxZ!9<SI=;^=ZN*UVJEx`(4{J{{w;-+p-_Z$F%hSVof#0{wyG4dgn+W0=@V z|DaIP7oCKRsG{xtk!KQAM|6paVFq>;n*t>U^by$%Fy#m1Kg_@Evk;*;X;jL2wb^s8 zkwe|zNe6+pvvoj#lT<;0}zedY_I~N&M-QJ>nvTHo^{nD+TgS0yg*?jJRctHs3IXqMr zS$G_QZ0&V4N<5T;K0IcZcBlrM2>6m%2ctE~zG2xK>Jz(q@(29Vg6KXy^Z6~mO ze#OY8k8Jl!)JBR@IC-w5o>o$Vwn9_&TK$o4@Nh@rVGP4i!#}bfoq(~nS)1D48E%LF zkM|0v=4Todqcde*E|erWNCf! zCi4lay`P6mX#B2SVd{g~qxm?)`>=TgtcbkBssw24 znB9LdbAC~rK*Mg4<8h<)fW-gP<-`<*u`MP;yRQ#>=L8=PHcEM5J*N@a#&@Yx$#Bf% z)9F!2uSW^sM@Gl?!8v{Hk2kK)5N-t0u-Y3<=A5AGAsHhbQX~tp`>+9tXZl3BXpPW^ z)_Jb?med&DJr9w*yjgOKpDpN4iaQ}9$P?}xKbZeujg3b*!d`rrV+BQq&b6D4jpRnF%JS@CchmC@tj60EoM2F~W=+#WS9_D-ZQQiR zfUA)l8F2I=K~$agMc|U9iEh6v1S<^f_}+DCWJB&)3~mZj7gKMeYZq# z`E%j%<G;;PkZ0atZZ$GRmCocn;dmAllps(=dJw#XO`+nFTRsnz*qtU=mnK` znBrIVF&69!Um8hafgalh67!};=#y%sd-yS3zv+dc3-lR9Fj#mQ6V5GrUV9CIAvnzI z#Tm;BLw$q)HJ6QeQ`0;!+MVP4?c_&jsg9KBy611I1r|3!&#Ha`SQ2Cu0h1xS81<<1 zjPbnbJAD;M^Krw=`v+!K>!p8*?)vkH!RyhG!oSi6!Dw{O#8Ix@1j7|X69OZeB*i+i zJh)(zl~{*k!d4`61Y-5|LO@8P=-BI-CG^Mh-b=Q=RNEYt?gb1)w0`sNYx4rtujOYP z;d}8h&i<~)VT7*}gsny2a-9cw)>^P&_G z=Z61f%2CEY9h}FsCN)byM`Wgo6TcnyGK`?K@Z5YVB8K;Of^~w z;|^|SbXc$$@-12PFT)4K(Tqi_3oBxS-4voWRXyUYlD5ljAllWU(zJJyWKHpL&M|kA zxOiF=P+n{pj`2sIhKc~x=qYYdo{UrkuyofKY`0bHg9}WKCQ;0Npxcs#rI;h^ZxY`zQ9CQ1^e{5o6eWZP z`=S|%?;Ee9j-qpSdyv6^5?K@SBt}J^S-sDbrH+7&{#}R1)(wRqhWip=7`bB76Fc>DsffFgH#M%QVC~(!IMa2MhSmq z_jXbwSQ>!X(Y&zxMJVVRv$0JQ*^eXOoA4fDseG#wJ79xZ2~*PzI1YboG#ENK2+>Q& za{pYkpnCIA=U9ZBC1V25UtH#Q%03BKD`q2`k_FFIp8Js-m5Yn{Rs41Py;Q9=47AD3 zZL9Dz&z9D-YaW_jT$`3_`VG3?#@(Ge*I4@63V~S8GTilE6V^#J3UKC!2X-Ih@0kW3 z7d=ZY!$~-~pdd1NNUyt~zs-H#NCC66-kAwxzL+?)T$H@O)+gHVl0$Q5(4-7Z_J&xU z^ORkF4C>raJA=>8e)40WwgRmy!v-p9O`tq@BF4Y@ zrwABvXTq8e7tz~tvv3G%woEFO<$miSo*3t4uAtBR?uNMT{f!WO*C(DkoN8s_NLzV& zNQkjgtjuO>mze51~JFXG*=i$!O)TqyLg{w=-Jl(aK4J zD-r#Kn>^UmYB;+kY*ct^cA~~l1xMm;?Om+#wD!`R=SMiE1x@ z5_c4kYcyFL|44e_<%cm}_u7rIrwB7Vb2BogpHSPb6RU!-_}eMXmA$;wx{Txp(@|M$J)smcW-({)I*4bJ|_F_~7bQrmJf_i}R~e|0x*Ujmti z6*ybHlGaJ80nRJ2`hB7&IQo!CL1b!WYExnKd+qu}$IQUbzN{z?av}v9$q5S&TdH|) zHN-GSelD-{D^^T_7$({uvR*HAQdGZMCtw3b0BQ^_!d`YrBXF?MwG?!*dvLAH6CSIW zr>-$%agUN6QXH@o6d6^UW$KlfyF0YN8$WzxK8uQ7_7P6ZEpHMiOia{EvD1@hhYcU=ikYPO#? zb#jTtXQv0U5JFgX)OqnaBuCl5ip#r>xb34&Hv zC|~;kYnqGa?s~Y^cp83bszY%WHfo{+_k7KaK8vLR{`_Jz+BS)vsgK%TnMGk7(Kv)4}0JiZ$Pim0_=Fcd&;5yfc|}geH^5bY)E$d&Yq!1`9aJ=!vHk ztBa#i8ZMqFDx0*K+7j)>_~%=wdTg0v-aMDS@fNgPGtAtxRu@I?0K5E;9f@X0n&`W& za=Q7ee5hMG9~sy#(6x+$RHD#NA z@>OmmOIG!DW@iVUHH@R)rpouJIEP*ALe0+`S!VSW9NEhE&u_HT@?~=-Dn;f)nton# zizV9?4|gM3CE=R({PZ=~@!Byk%a;5gzkM*IoKxSk-vXB&`8ox|Z5y{1CElM)yC30e z{8u}4{_o?mDDSPS+aGst#{O0}1HLhzewV5-m!3E2?Zn;>Q{4jF$9WoY0-s*FES(Y) z#J@j9u3Q%L(Xg?G52#%pdUd$c^OEJ3A$9oUHU_EqJ2pq5qBN=z5z}U}M@N&en2-u1 z+^Ecu%}fAGGe(h@5}4YA>cP6q+c!nJ{5b{RM}seP;nro!H4Y+!fztf47&{W=GVB$d zEw9*P8ovVfE*a=#KY_{pNY=`wJv2s2^?V7E=v%h*l+?Fg0keSPU*<4|M#?nyVKQl$ zz|r4`412}?kDKn{$Rv6VMw>m32qc%B;Sm-w*v`Af8C9AKcHK=E)&ysrU1fsX3Iu1a zYf6`mNUnU973+R_M7UL(;f?Fn)thFfRh)EIjrtn(i*p$)`Z`(5PRd*32o>E8f4rg| zE1J_XU-z=I4(rQ1nG3Y%-^!;I>2_L1)jxP@Z`k(f1O%E?_GgnnuD2!?V_KfefXO+8 zUbh&R8*fiLnIr@rw*?Ti0z8Gi zfCn6ihooyoFX@;3J^zc2ZKAy%~o?Mc6RATo5rFlWy#A`dQuZ-*~e6QQd4lmx)n4u zj$qZn-#sLIx$I#{jH&TH$g`L^J!LD%*1Q_Mfm3|MIa#yhqTP5@qSlT}YHE~Bg>n3) zH)t<;^n^iGG=;WSzn>kKeb3RRT{7L$Zoo@1PNS68kzRP%3B~xAuyIYuA^QuIFOxZR z_ieBaLeMSc{xe~>O-1NJ6SJl1NjU*&7br7$---} zJY|kKq0jX);qd_2lTagi&7_5W(2&M_$jCw^SD4gwYr>4 zwewZ!FTg+kuD5Te*S&?4yoq6>vQmbqziH5mBD;uO0^0tj_D3pZ2_(+K_Q=p%8}WH(JK|F9BLZ5NBC4JS{w#q=Zn^5UjBdxPpQ)1b{^=U z<~v%p79@kI0M6s_FilnT7RJFDW*#&qSEZrr3zBq50s1spkYta7QI}kbL%Pc}r~4yV z?#o{go>A^sZye$lNqjrPL;DONOc;T?^E<5;I9_s|(sx4RY^tcj*FQsn{YVI*6CElS z_$mCz4%iyXyv*2Ghz?~c*D7)VZIYBzg>2sYYwBEutj>=2fH!Y_yxiM=A!G7X8nzj^ z>wE9`3_`*ckyDO*-h7#RXV*={N9ORf4$0-!(FA3sI$x|;yIc%t zY@4(JpE6E(6g_3ER}SfH?kJZ;ztzn-H^CXdTd;b`nVTlMPYY~2bmOr8+LDG@PfwSm z(r@);N8Gu+T$9E5wMe~Bo54(Q!F&8Rc-dwRjf>Fs5IyB6B$RhlBk`}!vI;)<0b-!a zcY5`ff!}94dDA$IdYj$@S>fw36|Wn=##%H41h7*ptUMSxU_B>0eSDd#TeHD@blSz! z)(uFy{;tp07O0M`Ce1_@3;W7m#P2#S)mQNzpa*`r7>mb4S-z2VJs)Ngk(}qSx_gc{ zQ*GSNjmRh>wVzz}Un5uD{QGMqUoza$#^}YSd)L#}B6wV?S*rcmUHdTmv3|&?r5JV) z2MQ`7LnUv}b^BS7L>7+-enLhc*V-lM=d&KGS5U%eA(Hfj6Q=HKH6pKwT=Rq?r-xA? zD1?>znAUBP*4lX(#YRE^x*a8s>UyJ9z5-2Tqt~H~Z#D)i#_#|s=c^dxJ;g~ULk{p; zyFNc&$t7b!Cnc97>2VFjIm=Jk1SCYdyAgR@T#U?f`{XZgriX62686@wy%@o654fGt zRk3i|G|q5Qrj|`y^}Fd+SS`_1+}+I`Zb}uYWINxLG+<>-(G{zGUs33_YKzzT=85eD z>V{My?7du+LWjfEe5`(c9p`mul5P}>7Ac=cT+1B9ppW3ibqqcMb4DN-g1T`53FGBI z7WQpBf=;b3|9x_Lj_LhT*S&#=I5%H@ueBgeujtnMRS_C;lV;cBg{yOJJ3$G+(g{-FO`tH|A}DBwRefN@b!VrysA8$}`k_$L zz?b@H6s)M#80V(5>i`XH@SivO#rme1WoMJtw zE&mgff%?BO8Mr`GIo0$(Ul~+U!0`0j-E+k4!N1o<%TF32YwxepBixXpuyp&UhTsI? zVZte-h9Sw6NVbb#bwYgAd60)yh5Y}?|8Gp%)p~@^uUa#fq%!CW-2$N?^)I)492Fd-+9R-y><(>R;3*GdQ4bAxYMv6j=~tZXC&nNd?8!Fm=8=fiNFmAvnKnK3}^( zz2Ba$6RSY|(a%M5?`6f@5enraT?AVXQ)nYVE zmobb&$i1VHl0-X~FCHZ-E;?SJ(_H;+rCN_K1TJ|g8+|BvA-h|N2`#6)L6&)aDw|Ji zNqgzb=5+D#D)f0PyG-K$R;yKS7R09h8{e`h3=!{pky^RhXy`BNL9n~hcK%Q` zHItjaqiQK7r7dPOedOgy_mAD5?+azBp~zCiC$j}G;#VUeV1I{u@Eu*Pw$$t$2G&#k zw4iel{JS(+awRrBKv*71-70TS8Nu@BNu(|&uRl|Rl_`S=4;g*iaUG(iwi#DZ$c4~I_=G}!S-Hm!Qc^F5x5mvX zgYfF(SaL7#Sem+EU^N#+!$ZitE-O&pWM%HgMS z=%y!w(1ptjqH2FO!7>q!HKMm2{y3)`fi=CYVV{g8;%oUht*CjzNll4j z?bU@x6Lyp@fZYxZ-kV@Pq#ljW#pkk-Z9sbDq zNeea_+GV&ejmIItR+Tmch`-2FHDgIc7iITRdIi)|=mt%6&55%3>KAEusc|!39-JXwXfG6@1$(& z#(qQ>thSxO5d%-6;s@3a0><^?&>7kKXdPu_bcI4=Ly-;oIt4bhODpVe5ov`zuwtfWbkLC-zc7W|YK)ls^{e6f+=E9<>sz zP)>*A<9kvkI9b-hVj8V@?_=HMbW(7`7m-n9%1Pt!ju;P+T!Mho; z$RKMDsW1>l3_xxZMFSUaMFaxrQT$q3iM=qTCk#slaOdhy3<=dwl&4<_w}2E%BLz^Q zvDR7OTCp4mDXgchwQB8GjDEbZBAOc;&?0rxgf44OYevNqYsaRpFp~l3R=`BiFN_Tk zvTV4bc>1@ff@Ty*WB}zb(!(?PdIwYL1(9XIYh-8hB(r`Q2mz=ldVF96Ryq{9=l0kL z9BU}LM&bz`gp13l`Q=t;9pgTJu-K}Iy;reaCljX`Z`R%6*Xk?iJEqNxUWXKKuL!Ag z`+;B%$BjuOsYhqB7!AC{4^!i$tb{~8ITrV%5a_#oTCF#)^(^z8vettAm2nC$05QFo zkpOxAuNQ{IWHlDXd?GE6A|G|ssZIWpf1TYXuaAF;Fu(=zlO{NP<^7f%P6wg zc$<#OHq|s3cqX{OWVi_#Sy=ZjC2dnPaUM~?wF~7m@g>#mgpMg5eYzG7Z#u)cI&AVJ zY{fs$bTkdPM)_G-gk%P=)a3ZmQS)(j>@$L5xby(FSB0Sij_0>=DH-xg);Ux%qpzx! z)-hv1Alk#Dqttk*!D$UQrdEtA6HY9w?hTcxUf7Bxu;x8PFtID7zFiBpxKOS@#}!08@$Q6|2@=8);^!}|&Ea5twO|Ae z2qSiflYMBH8p+IHVwM>!(MB1IoVqrgr&3EPto-vuT1Q3YH)Ugqq~MTPN$?Ny?qevV|vQCO<;h$ z=_MJ9S)n8|z500U%NksFCbn;<Pj!m~?Nvbz4b!_EI}^ zi#dGZaW+Qr`&WXG!xS=-e0-)cZU<(1c$4PHPAcWx&mnT))R7BifSjHg z&JO+NFitev4n%rRb4`oeO1%m(i^kj+8I4CEc|2ApjU*%x(?VJgTCC7?&NWz#J(^T1 zq=-PL{LMl5HbW%ZpF4!GJPL}#@ncI2gIa_(ZupL#5%o|1ueRIys4l(8laeMKnrR4( zX9$t#zcA%V*o~f_T<;0=Ngzm)!?3@kB4&o)$;jbch7H^mr~~OtypAQr{%(7OKs~m; zWUNDMw1uE+1i?#ONIwX>Kt_Y|fmC869Cf7(5_cIh0{wP)ti7{**N1j>WehaBL06dx zuypJa6%N%E*S)RiuVgv=Z-0@U;)*HFzWpQjrrzv%07=jQ;rh_Cu^iND_e2ekm~7}q zJjlE#D1yU)u;|$Ku&bo!Yxm@68XfQwXA&uGrTYX5Pw8_p|c=nYXis20{1mf;&@(wyKQ>}uZwYVtU?jbE9Cn`a(4Hm0jv;7QOrQ^5z?!@i z81aJ{)7Q}ywLKY|VeL18vSM+%euH%kRWahll9~sb$V{>cEL}s;Y+FJRBkh-dHXHvt z@F-0D(3hC^%ESUH{a2>Z?-Ue?{DBb4QFdMPFTM{hgV0w%{An9kc^9Oqzl+&xJv_ie zxdE-5^uPGNqy$8j%LW!WvGTm%z}y`=kxK14SlkBSXksW%_d=DnQQvpd|BK(^VhUTQ zPD9a<*EkG_pWBm7kArIb~Q(|JyV*Jw;rzOd6>V%|3~6 z$Uua7PxlPoGWw&+x%^7b-8YfzEjiSx&=LyR@^yanBgOl9k28={0}KOJn+#3w=Dv6n zZ4wAwjagfz4zpHu&2r3T#WsKT1QusKR|&R+vkp&VnCjLGg*u{iry-sy^r; zXVG6Pjxyxn8CX{11MVpigD;Myb`3^y-G76eKxMv!$39|ytfpO?*qVvsuRs-H)RTBW zyi-l?H&^z5+I!ESsG=rp5O9DYN@f`HFyxE`i4umKhn&-(B#{gvO3rb}S#nMiBr9Ra zK|l~tL~>M;AgHK&=Y4nU`+jVFTeVxYRa><`r|!My^gZX??tc2|?s1gsB#;gj_lwjk zjZ*!4&X+sDN8g>XddHhWWT>^t0Sv)ohy*$ijEZLwxdA@_yiW+IXf`L{@?>t6m=YPT z$^dxkzg-SUfy)f~R$i?0 z;ICilX;O#J_nX60b%8Z1&4YYF^@cw;BB@{hZ7u$jyZCV9EE~KV3gL|nil6v4-Oc** zD*q7yP;(!sI{Ut{q=3lr-}SKkzwKE)DLL7o>wUXp{S31gmv*6te_vh)Fo?Jp1!iFU zt@;VIf`RJgtP1#_!mF1AobXRi85Q_jcYfIOVr}AN7(J4S!;WX*PhY3YaXrU_G+FDj zCl|`XpI($0j(Mm59Vz|p!0%(;?r(P?jnRI3R{zAul62b)r1o_Sbzo}nJ>1qIuZZyN z)@+3CvlrJ0)}KV{u5%B?GeI-F^v!Ee(?E8GGTIU0ZOadC_KY=2C8SOsBxY8`+NKuY z-=45|JHt~fm~!^R!xaVylkY;0q|?$m7!TCsJHm0&NSqwKd8G00c1n0H+&#hWF^~|P zd22|TnBl-fGVJ*7t-OA#s)sT6*(Tols`rL=_k*23$syfrgxwq8SLdlKHt~X$J7xTT z6s~c1vKeKtak|h{|N7x^0UR;TRFnAX9g~04VXHFHlx0BDndwilFbDo_F3$I`MZ&5F zx6hvJ$IA$8a+omeJ^AQsmlF?@N+3uT*?i;CNAVlA;+`$mKMrb|ipBqa2R+G~Gt6#{&&je6urMr_hA^xaYWk_pA^zs*5LmV<6))K3+XxFfNxM5(+Z);N4D3NYgfaC-%{$v zRxhr_6l%bHJ6Vj(NO(&^4Y$^vxVs-JtDEjjNEFIGz7nF;%;K7PPs=hHRPqVMP6M%E zss7M}t0#SMcK)8W;0;IoCi6sWt937}POPyfr9mB)jK!eeqjyDw`c0owyK^;(I=h`& z$*|@iD9godPhcgt0!+hTNL>Oc;ugF0yQth_To5^f6c&4UIu@sw@&_}}lj;d-ufz@} z{VgL97Vf03e*5oYarN8px5hq(iL%)OqDSAA9vTj^DfCagHFmHI-@`8|tvaW-O;cYZ z?ujlFMHl40tPyBE=chkuPbvFJ&jH=h@Mn|Yp&i61r`DXc?(p_C|C`h;p%B+-&g6r2 z2Nx1X|0z%d^u_}Cja_^1hZw$6n)2^Zf|dhe$I1EqO|ZoE!A+DH=EJaEld1|kA;Vdc ztpml+fk4L$q;}e0%yV%8Kc1CM;U_w1AH&wgtrIO}1se6)om11hWO|7z{0O40lsUqo zUTUeQ#51$b6mEh)#DWlH<~1*digz|H1iB}zv+Vrw@BHxF%|seBBlZ_+E7uUL5@n;uf-uXGqZsy)dX{5;Hy1R(My_YZ`^m;RoX?6 zLjnaqtS{T`?GqEm(&!QpR3^U=iJQ&p=4laW(ezKR0*aZ&M5I+4qi;APqdGs+(r3Q_92JAmo2t#Uf(i%(+ zG_>-}`qeBZjhhX#=4_tAsl7RA*_YgD+WHsKZ_Ri6vt!=o?(;>K8@iDXVw@{;Q2k7R z9bCotdzgb>D42^;Gz45|K0Y7U=XzHW?OG1ejChsFfK7Gfu)V!l%df* zByS-T+>h$wn(g@Eg9vrHa2}@{Y3NW0NMHw^kuL=ZLy6g67y-?CQ0C% zp~}V=AZ}epy>XYF{NQAaY(3&%MQ}on%gj<+J3{-_bQ|{T^jX^S)Szq3W$aUx!pZjQ z0IpS#wBEK61J}gn*IeYg9Jj!;QRMIRndrU4XbAPLdH}DHiZa?x;x7@}3ZqK>Qb+7u z@=nj76?~^SNF)6&yG6xC=?JgT$*7DY<>j&0yjw|4_}pYUQ1nF+*14HFeDrp$;f5_u}Vv9lsm_ zx*>4Aj<`YqXH2rks#8>3D#Ed^3pU z6Tb$p!&Nb^;kNZoAh9xsTZ0J1ZufS1SN{w%gV^)~-g)_6HL3JCSxEZCj@A<;dkk;y z0Cav7Xu1@ZdO1Dzi22-)RbuJUqf|tg0|~nGc{-DU2tL{5H<5r^46`l;3*g`)j$lE= zh=~1M&QDt-0BA1a;s;JQAN5R%PpOq}chCVc$}UR9#PFVUc_KtOq~MLbK0z)cCqYD7 zvaDy;+J>M=e#}#42DE_zQ9?!tChZ+QW8G>M$Fg+|4rXA1YJOwfLhz*Y+)bI|6Zq96 zxq?=d1nQV|i4xchi#oHO(uQ`wcwE7M#2H8Wwn0q7P>?@*1@ct|C0r`E>+?MCfRhXK z$(1asH4JCl`i_5@i-_1~VW;>(6$;tK*yDWC;MRAfGz<=+QXV9A26K1T$=0`uy~4#{ zy?82#-$l@ZFDRJcFeqJJY+52W-#=w^4_a2-HrZqI0}S4p>{+Gw<2)@ zKe{7XcVUpxcmJ8V6n7SwRuO&kw5-UREWEC2?^UW?4P&>;_EJ}>3ySe#(V*-^!K+=F zh-A}Hr)AZcI`d_kK@=%j>h>PjE6xZ*?}ab-bRuv7{dIUsv(8TLSnqgi-w^HzKZ&5C zlj<&?HJyt!UwsuSDiC?1p;vz9^Z-ZC(^C1)__T%t{srx+6=5rXHI0}kT^7oc@K z&~}c}QU5s`$ku=Q|YUvtmEpl2a8Tm z@DUn%^GPw*g$pfw(bkE;!0vmif>c2O|Gg7^yIb31&-X`DxNl`kA;#noSZn zuK%8g#=yBG6BvPTlK*P?B)!YC{#sGE9@#uxS!|y_DTT-6OCys2H~slegDZOVPbXOH4#x`D_YyPNr;o?uUtcKQZ2at)*zs^p2m>~h zQjsJSBmecC?q)iTypd_gD=_(VqR{IjvM zk7wkeq`Su&L*`pMfMwKTsaHl0A>NVZHX1?Lp*^xrS;C*8uhZR;3x|fRxqr`uAB7&Z zpxAiJz43VV`Lt_!pmJNqWWyH1S+)?^{+n@!k&tn9atG%c4nY5N5+-VCF?$4q*;;B$R0kV*w@^&Mp*w*StnF z0=fjLtt5Ouh%Tt<($RieF}zag$mUz1PfT3gI5TaT&&%S%d+d;nW;S^_q%cs3&zOPI z=*(6ci5qI+lwx=>7iC@lGsfL^N{J(`Ah#NIkYLNjp+2=`M3#k$M@z`f`%z!K;mf;XQ(;jzmt6ml_@#H|m2ODhO>%hRe^#E)9oL=KH#XHoWGPV@ ziT^7T9i%ZP3pO|{wiA)y(J!Eqr;i=}(GlXlZ%K$;cYfF7{-mxF#SRH_C>P0?c}v}7YuOkvmEgT7bOkBVvk=)Jwj_ja#tCZlI?Ezz2$Z5bav=0&KT zW70$rDsFucf4bFGzrjEu$<6RwB!fs57SH#*Y~*a2@fqnub`q57AMisOav%PhxU)Db zrT+qmQWms~W0Y%_gtyf(3>nWbQ zYI^{XyfIOeQ?qcc_`cyQj1y~0K%=>OrIzW(xbSTHJazDt7g@Bo;KTCy#LlMy)>K|t zfWgm&`g!2`)r)EBUj^a|dLoDP!L-A)caSOlc4mu6khkD)?xrAV1iUV@))Yp(u}1bv zljos86y@y5Tve4fAHS`!C%%c^iqX^vs4DTfqdIr!eVTrK(%am9-joTpYf3duLK*5+ z5pV(@Lc(TQ(EPAes(O;yEeigNpI3DlSoJMTS}ac4T70Fx2q6y*((p+~fLEbG!8N6F zrlt#zOYNa;_7v90BHz>2XI^DYNH(8lGa)kc73q{y!@pP6erkB0LfB<$7&0)Y_wi zgdhQ$I#Ybw^ao#ubApLT-0`C;7BS_v(nTcv-ZrEE(+NTslROgC1*g;I@W^L};x-TxIEFbeooMFW3t08%9v+osC)So4)%Ti6bxeG$2+4RPii@|3Mrk@oQ z%kv!{IBeDN@b<_q-Xl6YDe|Nf`45>l`jb_5@i{Q>`!=5uuupNnE30U}Xd?;kD0gjo zZsF(6vq=`$SC>^O(O{J9eh^LQxqiMbx9zAvKaZ;@CEjwLl;n!n;P}Kc;%cY85c}z3%xGKuw%yBBnoHIq6nphahgTJ{k*`}%XS6hFK@3azVTUr`@czBcX2SNyf>|y&&9HAG@EFIPsutz=&USUdCY@KOC|6Xj2Y{zzGsF&FwZt+ zgH8z81%w?*1L1q|qxf`6t8RBh56K|`pC;6lFY(l9*lPlqd%Etbsl7Qc_005ZZ0Q}5 z5g#XoQL<~lci-Tq7mK&#WOqa~QZr*dn+j^Bef7E=YKuc_|1hghYiU77dQ4pC!oBYYE8q0&laL@1qdsQJp|7aR;J({K zD|RsIG~ZpqzFJ`ksOy|OX|i;KEvbor5WEaX;qjfC2y3U4g#0NyIcoc z%pm6pIJn6dEKsY_=Wt+a41%6YUIw8TPGn4rUCk@M5N5WtY?tKLd>q0VwT+Ym6{0El zU6|5nyv;Nw%xQJCzS=nwIBu9c{wu_*`a7+Km`aqvjl-Zv&4imy*Gr9qhW9@rjcaYI zQDR~;Jl5uf5*RrOx2)f%uUtqdN4hB*P+d8$b5}`~x+bJS930zn?h9IL*nmA%z)tbU zu#o*3p6HDd4Uze-8>kf*4L^$}MGhBBpJ!O?!s$KJGMGIS*e8|m5w1n%Ig3K&`?6iQ zk1oLvkdx-S%?$(>OKntL`hGO0(_l?rceJNgV@phLJUxm_JT5tw{_6%ld5r0rbZtR* z@mwh`$>&@VXo|eJ9tlFYt{e@zj3pmEDwH=L3F^Vw&RLR;TbJ=3VTa5w^l4Qs0r6r1SFW?TbK3v@p z6}AFwRHf>}>mKO;g*FpECkyw$MrH~uKOMP&QTG9T$FLs8^@cr77f_teM($QNWZ|Uh zz#YSka~LU5E0!1YaC=-|&z`o4y(8#O{!NUcBs(C||6QSxt6_yF+_9$Jth3ukvQCX_ zn@rHzs#Ih6BXjQrRxHy%GsfY&o>W{2<$Y=I=(8;@a^mZg%G7Axo@%8eMTq%(8vD$r zVutJ;`3Ix78YSwu-TN^Ux>UWf1ZeZSAJI;Om&2mcg{?;7;nL9kM%P#O-rt1bsJ}y= zOm}RK%^iz6rz@BX?bANKxzw14zp4gyJ&Kn072;4O_0tZX$!-)TTSCmoi9<@m;Arw)NSZr{toec1R{ zF@asK7tvi|gj1D*6s=&f6%JK^^s0C1ik8EtmcM8JTF)WM1(J|t@+OH`nkrA2*ST!) zGB)(|o19@R=dcPxGIi>eR{#wei^IV2*-Fo8qLwh}rgxQ%O!`FZJ)>?-F*qf!=0t@K z@`!Rq#(=Wn`cmS8CWGTYxaAaO>Ureaoc|xj;l>YO9D+~8C9)C>IQVK-4mYoukd0#& zMn>!$TuCS44Z(48Zsa|Tegx-(j>gmzl)r%xerG2uBM70G?c_d@{Y#6VO&U2N@iVQU zOfa7&-e#b~I_qWrQ|X_!v9V~D5Hj4(uC8We58(y+oCW((v!fa;C(fP zp|$2=v%W`fYE;f5|LtR)@v)zU&Xj+>W;`qjtk}zeGc(y?&hjn85~MS%#ZcT=c?Ajx zetYQ@+&4?j@IvM%@;jO9obzHu*+N(RQ>~aLa=t~1|3OqVn{w-g{@bl>`*a;zyHiFN zsMbs_hytn!wtUAJO;*fGo+>>$FugTN1U|Y>192`N>hIK9s**2um9vxpc%tg-5M;!> z2?bG;$d?UGrB|OR{2L-UYv!p)L+5|%rZCD3aUrP%x5RlyLoTRC&{++VX{C@0xKtLI zpiWf{ahFw-mF{CG$cr9#!`Y~{PcJt;G`R(d=OjQK*qFTD{9i)D&rx*OWiW}DAeTS( zK+ExXQ+TpFQ!l=E@VUYm1ZrcMrb-^BG=IP?G&R?g>|MtM^|rp+T9WKy`Q}o zB{44EHFy7Ks8`?4#79~G1xNG48o5Ff`d&b$a#!HAxZna*knF|@z_DBwC zk);FRrQdG!9<$ku+FbZF0@B{Z8@qW_rws?2G)Lvat#Vo*B4QW*F{*fC2$JoHaJ~#K zc5=gWNU|~-pc!7eh~8d-6TO8{n@8#*<)r?d5yYISU94hE>%>);%dN+bFOkw+dnr1J>I7^;yWDvI}j#H8UG*H+Eq_K)bk zNH3hP-Y_Ut_W0>`LnzeE+up<_J%8guzb+cF58#m_0b88FDgWNYvsM()LrDjR6_-cj z+x7p9U>1+q1+PJ$kjS1B7miw|9Z~z`3S@9savkm(%5UT;k!JNNJw+@P;N%cT+r9|HL%2ei%%uF|1ZG<&Xqi==AG7H z{L*gZLc;Sf;P0;Y5)ZzNDM5w6jp4dHUYA+ZCmYPN4wTavN9vVLH3+b`nFA0(>Y`QE zXVXYVJPT~d1=n(k71)HLcSiX2Zs-Hu^)5Iq zC)2T}VW&lKwNOG$8NEF$0v$0j#&=fz;(w#lis#u*(3f{+7DrzfO}ccYWPQdh@I}cH zRpRp3qzCh7h$JklLSzs{_qTFA+x$tMl!N>9XFGyk7n6;tg%y%UU!M1gOR(-)ueXy-EKOMbknR=Ak*hf= zxu2;eVM0ap9cE|m9obwa6yGeTP}5o(TcmPg>r5G6oq1Yvk8H6#=%S%(V>A+dD>2I3 z{dChVVu+uHWohd%|9H)qwMalRN=Vv(xqr{1^z)pTl&wbLc#-fiD?ogIz=s5R=sWzz zPu*-3k`+0KP7+UUs{Q20$r*|J&XoX%e$Bx>4kI!b2PRc^QGTeFo-U`dT~^cJS&=_? zBO-RQN;k|=AIR*}33KNHx*_b3>jrEZdrJBl4`ws3Xeo!mkg>0{CCI~jH`VG6web9p zW>LumO3)4~USC&neER20r#lgvWnP79VM_KcFqR}8_RlSq3*ykf(Z?lco`>S$2Yx$t z9e`&1NC8ct?~Sn=`OY#Zesrg|>g;RkbsQrVx8=LGMSQ^3Q#}FuxhQv>G0O!;CJ_s- zkOUr#LDMx!Ha<_)7!;uCwTQldZ&G>nC-Q=5RMi{bKTth(G*$^7VRgvi3F7HLv{*CD zN8No5ZnkyC*$7m zR~6Qm_YHT$R70~Wb-HlEqe+w-O&GBre2Svx!@%H{JfDr>)dg9Jc=@J zlea=yqsbYM@sv^uo?_Kw!;SqHlyt?B^usmX;!>kYt?VS8?ujHE+JWR|*sBQ#I;q>l zY%KtcF%%~C&vo%Ml>o=XJ_Mp)F$aZpYu8ehs||4n4LV$Ui|S3hTN<6!VxW02Q}Q}$KM6J%0-;fqp|Fq(OMpKUk#X)w^?d9 ze=5SDy?Q4ii8T1?Thw4@icErj{q}no^Ati*gfS;BQ>9+Ig97yD@znrQdf=cREyXH)&0=~z4W40t-G!Qe| zv}v*P=umOU)xdcKQ9%~d%X<;*8Kq#ko&j}Gb>G~>e=if?GexSQ*2*%oF`9r*<4uAg zCn0Gr+*HM?MUkabT))HWo$WhyPg;v#?YKIqt}&&lLG0dTS901mK)@i|KWbWWK-n6lCY#lgsb#LhUD@rfbOim9C?CK*!(tz z5B6M5>}fMt?B;uH^%+2SfJWyZhE8JuW*!@H_3(UN-^-o`KQR<>9uS5n@ll|_!>6P#w^ z#~U_l?L!##By}%th{);S-WE7xC?08GL@n}9{Y!^ib-hW_{BH@2m)441P${AaCk@0Mt zCpIRbuy9&H^(-qRPeO_~i^J(kz*$<|R8KF9+Un=jVOy|dBOwC_qaU&u(#_$(u%cAcInxqU9)~Tqoc_8;sV_;&s?ycATUXf1cGVy z$sj#F5m!3MT5F-3SiRJF#t!yW76qu?jR+s~7fyFiq*BKhcH8a0ZL`I)`sCKWEd8-U zOmO@`Q{(+aqer}8QOum01mzPf4M;@8$7exAX(Wrts=gnlpxGhhNMd!dg$=D*gN$zE zwr2_!y$G4r6DS(P-};ctvJ!Zu*4CTg7;`@vAfYaGZs3{Y+9|(NfFU(IQB*XDKcXS^ zaiDI$yNgdX?70SKNE*G_|Jc^c5tibcyE|p{$U&S_Ad~mtG~6>IkolKoG+O1G;nOIS z{=0kyG{ow?emaN5i3%{fzylUBnc%IYwS7CD0+JWePj|T*>i8M!p7iL`&IGY$emSYY z#&0rJEH6n7rJ{H*@04~02K~Dy=;$)BqgSPUVitt??eXQGv+We6NR9y&9Q?>T{D}Qd z0kSUyjvJgNR-#vwiO|65INZq$-J}6U=H|W}Y6Ps>;^nueI}LekIEzn59{eIPoFsH( z1QIEwb~9hr$bx3@LqDsRjIcQnl@ErU=$APWn?kzbRzfJ}J2KQ{o#`)iWc zfO1t1GD_-5QQmDMg))KhuSrUA$!aGm)Q%0_gbpoGQf;c5^@^jrT- zDt<2}IUF^RR|%+^2W~6MdZnaAyJ-8+a8i`A7$~h!b6B?~%BMDQts+1vLpm_(tK85< zP$6iC>*uqmk;oy0kZFx2Qs`C)$|NAbG(&hHw*9Q!T{RYEVzuJJ#Eb1(=rFboB9wiyu?#39adIo(+oi43%nUXn1K`#o&*2jz{ELTzqPi^`rMe7&$c z+qxvJ1MO)Fw+GXZ;pWUIWUE*f`v{)6QVtLck^{=n<%&eFd$5t`-|=dcts*5GKEek_}@Mlmh} z+}YYR(Kr;NxQ7jweVWa_=y$py>ykaiFl#c?9}49fnj7si`u)w^<$Gv#qJNSi*WBsq zM>C;Y)Tg<3LZ}9B7Lcma>YF1eb-z7&!qD-hKI8d8Wa+98wYm}fW%rNmnvv+LM_In> zG4F0_$2&CQA({_i{B4?CvoR<&^PHc))pZl{LqoD?_G-@q19+rCh`@IDZHu0;LUPEN zE1Qbs9B9OMxo@1TS_p<5S2tVKl5t!GNne1PQZ8`76 z>m9LD#vs`yt)_<7m%gv5>B>b9n$2$?4%1p)H;j);1s=!qK}lHx-4m^ZJ{$KBbnC~I zYWp-j!R5Yo+r47@bn3=&M!}rnL|| z`mmKeyTmQ{Z!$DLMXIk$wkKT6%Np}s^dPNP@SA6V!}Qb($~<_PZ9ISXR|BHYf7Hd8 zdi}}B-#!lE0-B}Mff6;Jm@;eKdFz!?<{XhX@XSg@I4Y*uAxQX(x8kkHm;3r6sM|STpt|p!@-sHw zuP5aKQyxg-R%Z!^`3Gyst$xrSk8xydjDBDiV&Pmw%TC!I8H$`#{)$7@OgCb5cAOfV zTISG$ln9jPuA98loop1RRlw)dhK`p}KM1Y_=a{|B$HXysPA0`=2Er;u(tLyX!^`$~ zU&6p2 z9qTxr#)J~O%j(Sx9UvSr-O1!5d{%f4^|@g`1u5M6437*T(tiby4G2fB6%o|c z?PkNoYAOXFZwN%i-Fgk~q;~Cz5F`H>m%C_Eg7<{Pywte^fh_|ydKfFQCD4l#ocLA` zSjy&fbl0}=302rsNL=aOQSge*+&bAq^J%XLOX=m&?Tq@*{gIEGsV`eiyMFpoa}tCb zVx5R+A-oXip8{*+zH=M8(Af?f8g()zuniVTM97}Kx%{}{V>KrrIFE0AC-1=8pyK0f z_XltuODbr)E3rl-ZgQB%XSsWg*{g-LvWpTN@hgSYQtA>fuPP zixz{YHQ^JBJ3vGHqFFU+(3!VcMn4Nrt80*0a|UYvt%a^R)mu$yadF*p5>I>B23uyP zQa(ula|~ggV#tB)1;0)9T)ug;xOas8x51YXX(jg@f~Abonv3sxG0ft4xQld2EF&CE z!L-mfYFp@|7PKnPu2K$#d;=tEFyn=|xvq#?azP^rmkGr;3EMe{new$#XL8gBXA@jU zsz>C)#X2r7&>4|+WUV{Hj%AQ_zHM<j&!owCwq%5$9-~RY`uNYl(8SS_m$XEs&SUDzl;yZ`5Kuh2eY|m zNnq!F|F_^|OO6_XSk4RqhiRabACI_SRm?Zdt@SV#GPrSBLqdD$If@5=4VA9#0@eA7 z4DPE$T3RT7NXsR3ZtZqH6)obu6E|(Xjeq8y>PPZJktNfju1LA+Id46YHkr;q_^vtK z-!)avUrlOS^JfB7hpNaPO8d2Q-eU!*SHjDKwWj>xUa9+EGEW$9c`v8&k;)NbrQp#* zr_8z(>LZ2?)z`!^&GV}AwK>R0OSiQ&0XTR>OC_f6w<@scJEyy&%%b;rNeClHgQ$9L zVqc?gN)jfi|GVVZ&KucyUwz~VKjS1UvJ6GU1cG8f3+$B*j0AUXFvsDXI|17tU~Nrp z`7LwMH6FvfB_FQG-Rg=-Np2=Q*H^k#5x~K5VQBJwC>CS^RVi7dfcQ^LG%acg{Kg0L zltUX&(R;yBx)Cg^i8QvKh8_xV#|Q20E3C%XvJU~Z|GrhMEskq z$3Qs_8e7r;%Hfm*iZ=ZK^OvP}+2{e3>%?K{ICz)9D|UNu1-9gW8Quvv!yZlWa;()IubJ;cT?iVmz+v7J4zG@FK(g(EPi1~(wZA>zv< zb~X**VbzE!D(s*#*z7XyU#72t*$`L~kIFiG1)IKzjV8# - -

    - Apache Isis™ is a platform to let you rapidly develop - domain-driven apps in Java. -
    -
    - This app has been generated using Apache Isis' - SimpleApp archetype, - to create a purposefully minimal application that nevertheless includes fixture data, integration tests and BDD specs. -
    -
    - The app itself consists of a single domain class, SimpleObject, - along with an equally simple (factory/repository) domain service, SimpleObjects. -
    -
    - For more details, see the Apache Isis website. -

    diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/isis.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/isis.properties deleted file mode 100644 index 929d1775a8b9..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/isis.properties +++ /dev/null @@ -1,300 +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. - - -################################################################################# -# -# specify system components. -# -# The values correspond to the named components in the installer-registry.properties file -# in the org.apache.isis.core:isis-core-runtime JAR (in the org.apache.isis.core.runtime package) -# -# Although all configuration could reside in isis.properties, the recommendation is -# to split out into component specific files: -# -# xxx_yyy.properties files -# -# where -# * xxx is the component type, and -# * yyy is the component name. -# -# For example, viewer_wicket.properties holds configuration information specific to the Wicket viewer. -# -################################################################################# - - -# -# configure the persistor (object store) to use -# - -# JDO/DataNucleus objectstore -isis.persistor=datanucleus - - - -# -# configure authentication mechanism to use (to logon to the system) -# - -#isis.authentication=bypass -isis.authentication=shiro - - -# -# configure authorization mechanism to use -# - -#isis.authorization=bypass -isis.authorization=shiro - - - - - -################################################################################# -# -# MetaModel -# -# The metamodel typically does not require additional configuration, although -# the system components (defined above) may refine the metamodel for their needs. -# -################################################################################# - - -# -# Additional programming model facet factories, or remove standard facet factories. -# Comma separated list of fully qualified class names. -# -#isis.reflector.facets.include= -#isis.reflector.facets.exclude= - - -# -# Metamodel validation (in addition to that automatically performed by the programming model facet factories) -# Default implementation does nothing. -# -# Use a custom implementation to enforce additional constraints specific to your app/project/company. -# -#isis.reflector.validator=org.apache.isis.core.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault - - - -# -# Whether to allow deprecated annotations/method prefixes (otherwise raise metamodel validation errors). -# If not specified, default is to allow. -# -isis.reflector.validator.allowDeprecated=false - - - -# -# Implementation to use for reading dynamic layout. Default implementation reads Xxx.layout.json files from classpath. -# -#isis.reflector.layoutMetadataReaders=org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson - - - -# -# patterns for applying CssClassFa facet (font-awesome icons), matching on action names -# -isis.reflector.facet.cssClassFa.patterns=\ - new.*:fa-plus,\ - add.*:fa-plus-square,\ - create.*:fa-plus,\ - update.*:fa-edit,\ - change.*:fa-edit,\ - remove.*:fa-minus-square,\ - move.*:fa-exchange,\ - first.*:fa-star,\ - find.*:fa-search,\ - lookup.*:fa-search,\ - clear.*:fa-remove,\ - previous.*:fa-step-backward,\ - next.*:fa-step-forward,\ - list.*:fa-list, \ - all.*:fa-list, \ - download.*:fa-download, \ - upload.*:fa-upload, \ - execute.*:fa-bolt, \ - run.*:fa-bolt, \ - calculate.*:fa-calculator, \ - verify.*:fa-check-circle, \ - refresh.*:fa-refresh, \ - install.*:fa-wrench - - -# -# patterns for applying CssClass facet (CSS styles), matching on member names -# -isis.reflector.facet.cssClass.patterns=\ - delete.*:btn-warning - - -################################################################################# -# -# Value facet defaults -# -# (see also viewer-specific config files, eg viewer_wicket.properties) -# -################################################################################# - -# as used by @Title of a date -isis.value.format.date=dd-MM-yyyy - - - -################################################################################# -# -# Application Services and fixtures -# -################################################################################# - -# -# Specify the domain services. -# -# These are the most important configuration properties in the system, as they define -# the set of the classes for Isis to instantiate as domain service singletons. -# From these domain service instances the rest of the metamodel is discovered, while the -# end-user gains access to other domain objects by invoking the actions of the domain services. -# -isis.services-installer=configuration-and-annotation -isis.services.ServicesInstallerFromAnnotation.packagePrefix=domainapp - -# additional services/overriding default (@DomainService) implementations -isis.services = - - - -# Specify the (optional) test fixtures -# -# Fixtures are used to seed the object store with an initial set of data. For the -# in-memory object store, the fixtures are installed on every run. For other -# object stores, they are used only when the object store is first initialized. -# -isis.fixtures=domainapp.fixture.scenarios.RecreateSimpleObjects - - -# -# required by EmailServiceDefault -# -#isis.service.email.sender.address=some.valid@email.address -#isis.service.email.sender.password=the.password.for-isis.notification.email.sender.address - - - -# -# whether ExceptionRecognizers should also log any recognized exceptions -# (default false; enable for diagnostics/debugging) -# -#isis.services.exceprecog.logRecognizedExceptions=true - - -# -# disable to (automatically registered) ExceptionRecognizerCompositeForJdoObjectStore service -# almost all of this service should be registered. Since all exception recognizer implementations -# are consulted in the event of an exception, it's not sufficient to override the implementation -# (in isis.services); instead this configuration property disables this particular implementation. -# -#isis.services.ExceptionRecognizerCompositeForJdoObjectStore.disable=true - - -################################################################################ -# -# Auditing, Publishing, Command -# -################################################################################ - -# -# Whether changes to objects should be audited; if not set, defaults to "none" -# - if not set or set to "none", can explicitly enable using @DomainObject(auditing=Auditing.ENABLED) -# - if set to "all", can explicitly disable using @Object(auditing=Auditing.DISABLED) -# -#isis.services.audit.objects=all|none - -# -# Whether changes to objects should be published; if not set, defaults to "none" -# - if not set or set to "none", can explicitly enable using @DomainObject(publishing=Publishing.ENABLED) -# - if set to "all", can explicitly disable using @Object(publishing=Publishing.DISABLED) -# -#isis.services.publish.objects=all|none - -# -# Whether all (or all non-query only) actions should be published; if not set, defaults to "none" -# - if not set or set to "none", can explicitly enable using @Action(publishing=Publishing.ENABLED) -# - if set to "all", can explicitly disable using @Action(publishing=Publishing.DISABLED) -# -#isis.services.publish.actions=all|none|ignoreQueryOnly - - -# -# Whether all (or all non-query only) actions should be reified as commands; if not set, defaults to "none" -# - if not set or set to "none", can explicitly enable using @Action(command=CommandReification.ENABLED) -# - if set to "all", can explicitly disable using @Action(command=CommandReification.DISABLED) -# -#isis.services.command.actions=all|none|ignoreQueryOnly - - - - - -################################################################################ -# -# Policies -# -################################################################################# - -# -# Whether editing of object properties is allowed; if not set, defaults to "true" -# - if not set or set to "true", can explicitly disable using @DomainObject(editing=Editing.DISABLED) -# - if set to "false", can explicitly enable using @DomainObject(editing=Editing.ENABLED) -# -#isis.objects.editing=true|false - - - - - -################################################################################ -# -# i18n -# -################################################################################# - -# -# force read translations, even if running in prototype mode -# -#isis.services.translation.po.mode=read - - - - - -################################################################################ -# -# Viewer defaults -# -################################################################################# - -# -# Specify viewer defaults -# -#isis.viewers.paged.standalone=30 -#isis.viewers.paged.parented=10 - - -#isis.viewers.propertyLayout.labelPosition=LEFT -#isis.viewers.parameterLayout.labelPosition=LEFT diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/persistor.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/persistor.properties deleted file mode 100644 index c73af73c78d4..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/persistor.properties +++ /dev/null @@ -1,128 +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. - - - -################################################################################# -# -# Persistor -# -################################################################################# - - - -# generally speaking this should not be enabled -isis.persistor.disableConcurrencyChecking=false - - - - -################################################################################# -# -# JDBC configuration -# -################################################################################# - -# -# configuration file holding the JDO objectstore's JDBC configuration -# (this is a bit of a hack... just exploiting fact that Isis also loads this file) -# - - -# -# JDBC connection details -# (also update the pom.xml to reference the appropriate JDBC driver) -# - -# -# HSQLDB in-memory -# -isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=org.hsqldb.jdbcDriver -isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:hsqldb:mem:test -isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=sa -isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword= - -# -# HSQLDB in-memory (using log4jdbc-remix) -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=net.sf.log4jdbc.DriverSpy -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:log4jdbc:hsqldb:mem:test -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=sa -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword= - - - -# -# HSQLDB to file -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=org.hsqldb.jdbcDriver -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:hsqldb:file:/tmp/isis-simple-app/hsql-db;hsqldb.write_delay=false;shutdown=true -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=sa -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword= - -# -# HSQLDB to file (using log4jdbc-remix) -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=net.sf.log4jdbc.DriverSpy -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:log4jdbc:hsqldb:file:/tmp/isis-simple-app/hsql-db;hsqldb.write_delay=false;shutdown=true -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=sa -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword= - - - -# -# PostgreSQL Server -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=org.postgresql.Driver -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:postgresql://localhost:5432/isis -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=isis -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword=isis - -# -# PostgreSQL Server (using log4jdbc-remix) -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=net.sf.log4jdbc.DriverSpy -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:log4jdbc:postgresql://localhost:5432/isis -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=isis -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword=isis - - - -# -# MS SQL Server -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=com.microsoft.sqlserver.jdbc.SQLServerDriver -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:sqlserver://127.0.0.1:1433;instance=.;databaseName=simple -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=sa -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword=p4ssword - -# -# MS SQL Server (using log4jdbc-remix) -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionDriverName=net.sf.log4jdbc.DriverSpy -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=jdbc:log4jdbc:sqlserver://127.0.0.1:1433;instance=SQLEXPRESS;databaseName=jdo -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionUserName=jdo -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionPassword=jdopass - - - -# -# neo4j -# (experimental; run with -P neo4j profile in webapp project) -# -#isis.persistor.datanucleus.impl.javax.jdo.option.ConnectionURL=neo4j:neo4j_DB - diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/persistor_datanucleus.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/persistor_datanucleus.properties deleted file mode 100644 index 675ced3bf8c0..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/persistor_datanucleus.properties +++ /dev/null @@ -1,93 +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. - -# -# configuration file for the JDO/DataNucleus objectstore -# - -# identifies @PersistenceCapable entities to be eagerly registered -# if move class to other package (eg com.mycompany.myapp.dom) then update -isis.persistor.datanucleus.RegisterEntities.packagePrefix=domainapp.dom.modules - -# -# hook to perform additional initialization when JDO class metadata is loaded -# default implementation will attempt to run 'create schema' for the specified schema. -# -#isis.persistor.datanucleus.classMetadataLoadedListener=org.apache.isis.objectstore.jdo.datanucleus.CreateSchemaFromClassMetadata - - -# whether to persist the event data as a "clob" or as a "zipped" byte[] -# default is "zipped" -#isis.persistor.datanucleus.PublishingService.serializedForm=zipped - - -##################################################################### -# -# DataNucleus' configuration -# -# The 'isis.persistor.datanucleus.impl' prefix is stripped off, -# remainder is passed through to DataNucleus -# -##################################################################### - -isis.persistor.datanucleus.impl.datanucleus.schema.autoCreateAll=true -isis.persistor.datanucleus.impl.datanucleus.schema.validateTables=true -isis.persistor.datanucleus.impl.datanucleus.schema.validateConstraints=true - - -# -# Require explicit persistence (since entities are Comparable and using ObjectContracts#compareTo). -# see http://www.datanucleus.org/products/accessplatform_3_0/jdo/transaction_types.html -# -isis.persistor.datanucleus.impl.datanucleus.persistenceByReachabilityAtCommit=false - - -# -# How column names are identified -# (http://www.datanucleus.org/products/datanucleus/jdo/orm/datastore_identifiers.html) -# -isis.persistor.datanucleus.impl.datanucleus.identifier.case=MixedCase - -# -# L2 cache -# off except if explicitly marked as cacheable -# http://www.datanucleus.org/products/datanucleus/jdo/cache.html -# -isis.persistor.datanucleus.impl.datanucleus.cache.level2.type=none -isis.persistor.datanucleus.impl.datanucleus.cache.level2.mode=ENABLE_SELECTIVE - - - -# -# uncomment to use JNDI rather than direct JDBC -# -#isis.persistor.datanucleus.impl.datanucleus.ConnectionFactoryName=java:comp/env/jdbc/quickstart - -# -# uncomment to use JTA resource -# -#isis.persistor.datanucleus.impl.datanucleus.ConnectionFactory2Name=java:comp/env/jdbc/quickstart-nontx -#isis.persistor.datanucleus.impl.javax.jdo.option.TransactionType=JTA - - - -# -# -# JDBC connection details -# ... are in persistor.properties -# -# diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/shiro.ini b/naked-objects/webapp/src/main/webapp/WEB-INF/shiro.ini deleted file mode 100644 index 971ae697f669..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/shiro.ini +++ /dev/null @@ -1,93 +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. -# - -[main] - -contextFactory = org.apache.isis.security.shiro.IsisLdapContextFactory -contextFactory.url = ldap://localhost:10389 -contextFactory.authenticationMechanism = CRAM-MD5 -contextFactory.systemAuthenticationMechanism = simple -contextFactory.systemUsername = uid=admin,ou=system -contextFactory.systemPassword = secret - -ldapRealm = org.apache.isis.security.shiro.IsisLdapRealm -ldapRealm.contextFactory = $contextFactory - -ldapRealm.searchBase = ou=groups,o=mojo -ldapRealm.groupObjectClass = groupOfUniqueNames -ldapRealm.uniqueMemberAttribute = uniqueMember -ldapRealm.uniqueMemberAttributeValueTemplate = uid={0} - -# optional mapping from physical groups to logical application roles -#ldapRealm.rolesByGroup = \ -# LDN_USERS: user_role,\ -# NYK_USERS: user_role,\ -# HKG_USERS: user_role,\ -# GLOBAL_ADMIN: admin_role,\ -# DEMOS: self-install_role - -ldapRealm.permissionsByRole=\ - user_role = *:ToDoItemsJdo:*:*,\ - *:ToDoItem:*:*; \ - self-install_role = *:ToDoItemsFixturesService:install:* ; \ - admin_role = * - -# to use ldap... -# (see docs for details of how to setup users/groups in Apache Directory Studio). -#securityManager.realms = $ldapRealm - -# to use .ini file -securityManager.realms = $iniRealm - - - -# ----------------------------------------------------------------------------- -# Users and their assigned roles -# -# Each line conforms to the format defined in the -# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc -# ----------------------------------------------------------------------------- - -[users] -# user = password, role1, role2, role3, ... - - -sven = pass, admin_role -dick = pass, user_role, self-install_role -bob = pass, user_role, self-install_role -joe = pass, user_role, self-install_role -guest = guest, user_role - - - -# ----------------------------------------------------------------------------- -# Roles with assigned permissions -# -# Each line conforms to the format defined in the -# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc -# ----------------------------------------------------------------------------- - -[roles] -# role = perm1, perm2, perm3, ... -# perm in format: packageName:className:memberName:r,w - -user_role = *:SimpleObjects:*:*,\ - *:SimpleObject:*:* -self-install_role = *:DomainAppFixtureService:*:* -admin_role = * diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-en.po b/naked-objects/webapp/src/main/webapp/WEB-INF/translations-en.po deleted file mode 100644 index 47b82d11e9f6..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-en.po +++ /dev/null @@ -1,213 +0,0 @@ -############################################################################## -# -# .pot file -# -# Translate this file to each required language and place in WEB-INF, eg: -# -# /WEB-INF/translations-en_US.po -# /WEB-INF/translations-en.po -# /WEB-INF/translations-fr_FR.po -# /WEB-INF/translations-fr.po -# /WEB-INF/translations.po -# -# If the app uses TranslatableString (eg for internationalized validation -# messages), or if the app calls the TranslationService directly, then ensure -# that all text to be translated has been captured by running a full -# integration test suite that exercises all relevant behaviour -# -############################################################################## - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations(java.lang.String) -msgid ".pot file name" -msgstr ".pot file name" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#resetTranslationCache() -msgid "Clear translation cache" -msgstr "Clear translation cache" - - -#: domainapp.dom.modules.simple.SimpleObjects#create() -msgid "Create" -msgstr "Create" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#discoverable -msgid "Discoverable" -msgstr "Discoverable" - - -#: org.apache.isis.applib.fixtures.FixtureType#DOMAIN_OBJECTS -msgid "Domain Objects" -msgstr "Domain Objects" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations() -msgid "Download Translations" -msgstr "Download Translations" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Exclamation mark is not allowed" -msgstr "Exclamation mark is not allowed" - - -#: domainapp.dom.modules.simple.SimpleObjects#findByName() -msgid "Find By Name" -msgstr "Find By Name" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#fixtureScriptClassName -msgid "Fixture script" -msgstr "Fixture script" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#friendlyName -msgid "Friendly Name" -msgstr "Friendly Name" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "General" -msgstr "General" - - -#: domainapp.dom.app.homepage.HomePageService#homePage() -msgid "Home Page" -msgstr "Home Page" - - -#: domainapp.dom.modules.simple.SimpleObjects#listAll() -msgid "List All" -msgstr "List All" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#localName -msgid "Local Name" -msgstr "Local Name" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#lookup() -#: org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions#lookup() -msgid "Lookup" -msgstr "Lookup" - - -#: domainapp.dom.modules.simple.SimpleObject#name -#: domainapp.dom.modules.simple.SimpleObjects#create(java.lang.String) -#: domainapp.dom.modules.simple.SimpleObjects#findByName(java.lang.String) -msgid "Name" -msgstr "Name" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName(java.lang.String) -msgid "New name" -msgstr "New name" - - -#: org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#object() -msgid "Object" -msgstr "Object" - - -#: domainapp.dom.modules.simple.SimpleObject#title() -msgid "Object: {name}" -msgstr "Object: {name}" - - -#: domainapp.dom.app.homepage.HomePageViewModel#objects -msgid "Objects" -msgstr "Objects" - - -#: org.apache.isis.applib.fixtures.FixtureType#OTHER -msgid "Other" -msgstr "Other" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Parameters" -msgstr "Parameters" - - -#: domainapp.fixture.DomainAppFixturesService -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu -msgid "Prototyping" -msgstr "Prototyping" - - -#: domainapp.fixture.DomainAppFixturesService#recreateObjectsAndReturnFirst() -msgid "Recreate Objects And Return First" -msgstr "Recreate Objects And Return First" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#object -msgid "Result" -msgstr "Result" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#className -msgid "Result class" -msgstr "Result class" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#key -msgid "Result key" -msgstr "Result key" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript() -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript() -msgid "Run Fixture Script" -msgstr "Run Fixture Script" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript -msgid "Script" -msgstr "Script" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Script-specific parameters (if any). The format depends on the script implementation (eg key=value, CSV, JSON, XML etc)" -msgstr "Script-specific parameters (if any). The format depends on the script implementation (eg key=value, CSV, JSON, XML etc)" - - -#: domainapp.dom.modules.simple.SimpleObjects#title() -msgid "Simple Objects" -msgstr "Simple Objects" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToReadingTranslations() -msgid "Switch To Reading Translations" -msgstr "Switch To Reading Translations" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToWritingTranslations() -msgid "Switch To Writing Translations" -msgstr "Switch To Writing Translations" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#type -msgid "Type" -msgstr "Type" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Update Name" -msgstr "Update Name" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "name" -msgstr "" - - - - - -############################################################################## -# end of .pot file -############################################################################## - diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-es.po b/naked-objects/webapp/src/main/webapp/WEB-INF/translations-es.po deleted file mode 100644 index 8b4c2d7bd275..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-es.po +++ /dev/null @@ -1,208 +0,0 @@ -############################################################################## -# -# .pot file -# -# Translate this file to each required language and place in WEB-INF, eg: -# -# /WEB-INF/translations-en_US.po -# /WEB-INF/translations-en.po -# /WEB-INF/translations-fr_FR.po -# /WEB-INF/translations-fr.po -# /WEB-INF/translations.po -# -# If the app uses TranslatableString (eg for internationalized validation -# messages), or if the app calls the TranslationService directly, then ensure -# that all text to be translated has been captured by running a full -# integration test suite that exercises all relevant behaviour -# -############################################################################## - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations(java.lang.String) -msgid ".pot file name" -msgstr "fichero .pot" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#resetTranslationCache() -msgid "Clear translation cache" -msgstr "Limpiar la caché de traducciones" - - -#: domainapp.dom.modules.simple.SimpleObjects#create() -msgid "Create" -msgstr "Crear" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#discoverable -msgid "Discoverable" -msgstr "Descubrible" - - -#: org.apache.isis.applib.fixtures.FixtureType#DOMAIN_OBJECTS -msgid "Domain Objects" -msgstr "Domain Objects" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations() -msgid "Download Translations" -msgstr "Descargar traducciones" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Exclamation mark is not allowed" -msgstr "No se admite el signo de exclamación" - - -#: domainapp.dom.modules.simple.SimpleObjects#findByName() -msgid "Find By Name" -msgstr "Buscar por Nombre" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#fixtureScriptClassName -msgid "Fixture script" -msgstr "Script de Instalación" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#friendlyName -msgid "Friendly Name" -msgstr "Nombre común" - - -#: domainapp.dom.app.homepage.HomePageService#homePage() -msgid "Home Page" -msgstr "Página de Inicio" - - -#: domainapp.dom.modules.simple.SimpleObjects#listAll() -msgid "List All" -msgstr "Listar Todos" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#localName -msgid "Local Name" -msgstr "Nombre Local" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#lookup() -#: org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions#lookup() -msgid "Lookup" -msgstr "Buscar" - - -#: domainapp.dom.modules.simple.SimpleObject#name -#: domainapp.dom.modules.simple.SimpleObjects#create(java.lang.String) -#: domainapp.dom.modules.simple.SimpleObjects#findByName(java.lang.String) -msgid "Name" -msgstr "Nombre" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName(java.lang.String) -msgid "New name" -msgstr "Nuevo nombre" - - -#: org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#object() -msgid "Object" -msgstr "Objeto" - - -#: domainapp.dom.modules.simple.SimpleObject#title() -msgid "Object: {name}" -msgstr "Objeto: {name}" - - -#: domainapp.dom.app.homepage.HomePageViewModel#objects -msgid "Objects" -msgstr "Objetos" - - -#: org.apache.isis.applib.fixtures.FixtureType#OTHER -msgid "Other" -msgstr "Other" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Parameters" -msgstr "Parámetros" - - -#: domainapp.fixture.DomainAppFixturesService -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu -msgid "Prototyping" -msgstr "Prototipo" - - -#: domainapp.fixture.DomainAppFixturesService#recreateObjectsAndReturnFirst() -msgid "Recreate Objects And Return First" -msgstr "Recrear Objetos y Devolver el Primero" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#object -msgid "Result" -msgstr "Resultado" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#className -msgid "Result class" -msgstr "Clase del resultado" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#key -msgid "Result key" -msgstr "Clave del Resultado" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript() -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript() -msgid "Run Fixture Script" -msgstr "Ejecutar Script de Instalación" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript -msgid "Script" -msgstr "Script" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Script-specific parameters (if any). The format depends on the script implementation (eg key=value, CSV, JSON, XML etc)" -msgstr "Parámetros específicos del Script (si hay alguno). El formato depende de la implementación del script (por ejemplo, clave=valor, CSV, JSON, XML, etc.)" - - -#: domainapp.dom.modules.simple.SimpleObjects#title() -msgid "Simple Objects" -msgstr "Objetos básicos" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToReadingTranslations() -msgid "Switch To Reading Translations" -msgstr "Cambiar a Lectura de Traducciones" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToWritingTranslations() -msgid "Switch To Writing Translations" -msgstr "Cambiar a Escritura de Traducciones" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#type -msgid "Type" -msgstr "Tipo" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Update Name" -msgstr "Nombre de la Actualización" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "name" -msgstr "" - - - - - -############################################################################## -# end of .pot file -############################################################################## - diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-nl.po b/naked-objects/webapp/src/main/webapp/WEB-INF/translations-nl.po deleted file mode 100644 index 4e35a228fc80..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/translations-nl.po +++ /dev/null @@ -1,208 +0,0 @@ -############################################################################## -# -# .pot file -# -# Translate this file to each required language and place in WEB-INF, eg: -# -# /WEB-INF/translations-en_US.po -# /WEB-INF/translations-en.po -# /WEB-INF/translations-fr_FR.po -# /WEB-INF/translations-fr.po -# /WEB-INF/translations.po -# -# If the app uses TranslatableString (eg for internationalized validation -# messages), or if the app calls the TranslationService directly, then ensure -# that all text to be translated has been captured by running a full -# integration test suite that exercises all relevant behaviour -# -############################################################################## - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations(java.lang.String) -msgid ".pot file name" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#resetTranslationCache() -msgid "Clear translation cache" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#create() -msgid "Create" -msgstr "Creëren" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#discoverable -msgid "Discoverable" -msgstr "Discoverable" - - -#: org.apache.isis.applib.fixtures.FixtureType#DOMAIN_OBJECTS -msgid "Domain Objects" -msgstr "Domain Objects" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations() -msgid "Download Translations" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Exclamation mark is not allowed" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#findByName() -msgid "Find By Name" -msgstr "Zoek op Naam" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#fixtureScriptClassName -msgid "Fixture script" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#friendlyName -msgid "Friendly Name" -msgstr "" - - -#: domainapp.dom.app.homepage.HomePageService#homePage() -msgid "Home Page" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#listAll() -msgid "List All" -msgstr "Lijst Alle" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#localName -msgid "Local Name" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#lookup() -#: org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions#lookup() -msgid "Lookup" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#name -#: domainapp.dom.modules.simple.SimpleObjects#create(java.lang.String) -#: domainapp.dom.modules.simple.SimpleObjects#findByName(java.lang.String) -msgid "Name" -msgstr "Naam" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName(java.lang.String) -msgid "New name" -msgstr "Nieuwe naam" - - -#: org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#object() -msgid "Object" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#title() -msgid "Object: {name}" -msgstr "" - - -#: domainapp.dom.app.homepage.HomePageViewModel#objects -msgid "Objects" -msgstr "Objects" - - -#: org.apache.isis.applib.fixtures.FixtureType#OTHER -msgid "Other" -msgstr "Other" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Parameters" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu -msgid "Prototyping" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#recreateObjectsAndReturnFirst() -msgid "Recreate Objects And Return First" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#object -msgid "Result" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#className -msgid "Result class" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#key -msgid "Result key" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript() -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript() -msgid "Run Fixture Script" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript -msgid "Script" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Script-specific parameters (if any). The format depends on the script implementation (eg key=value, CSV, JSON, XML etc)" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#title() -msgid "Simple Objects" -msgstr "Eenvoudige Objecten" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToReadingTranslations() -msgid "Switch To Reading Translations" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToWritingTranslations() -msgid "Switch To Writing Translations" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#type -msgid "Type" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Update Name" -msgstr "Updaten Naam" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "name" -msgstr "" - - - - - -############################################################################## -# end of .pot file -############################################################################## - diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/translations.po b/naked-objects/webapp/src/main/webapp/WEB-INF/translations.po deleted file mode 100644 index 3644a2880d63..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/translations.po +++ /dev/null @@ -1,213 +0,0 @@ -############################################################################## -# -# .pot file -# -# Translate this file to each required language and place in WEB-INF, eg: -# -# /WEB-INF/translations-en_US.po -# /WEB-INF/translations-en.po -# /WEB-INF/translations-fr_FR.po -# /WEB-INF/translations-fr.po -# /WEB-INF/translations.po -# -# If the app uses TranslatableString (eg for internationalized validation -# messages), or if the app calls the TranslationService directly, then ensure -# that all text to be translated has been captured by running a full -# integration test suite that exercises all relevant behaviour -# -############################################################################## - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations(java.lang.String) -msgid ".pot file name" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#resetTranslationCache() -msgid "Clear translation cache" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#create() -msgid "Create" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#discoverable -msgid "Discoverable" -msgstr "" - - -#: org.apache.isis.applib.fixtures.FixtureType#DOMAIN_OBJECTS -msgid "Domain Objects" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#downloadTranslations() -msgid "Download Translations" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Exclamation mark is not allowed" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#findByName() -msgid "Find By Name" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#fixtureScriptClassName -msgid "Fixture script" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#friendlyName -msgid "Friendly Name" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "General" -msgstr "Common" - - -#: domainapp.dom.app.homepage.HomePageService#homePage() -msgid "Home Page" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#listAll() -msgid "List All" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#localName -msgid "Local Name" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#lookup() -#: org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions#lookup() -msgid "Lookup" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#name -#: domainapp.dom.modules.simple.SimpleObjects#create(java.lang.String) -#: domainapp.dom.modules.simple.SimpleObjects#findByName(java.lang.String) -msgid "Name" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName(java.lang.String) -msgid "New name" -msgstr "" - - -#: org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#object() -msgid "Object" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#title() -msgid "Object: {name}" -msgstr "" - - -#: domainapp.dom.app.homepage.HomePageViewModel#objects -msgid "Objects" -msgstr "" - - -#: org.apache.isis.applib.fixtures.FixtureType#OTHER -msgid "Other" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Parameters" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu -msgid "Prototyping" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#recreateObjectsAndReturnFirst() -msgid "Recreate Objects And Return First" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#object -msgid "Result" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#className -msgid "Result class" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureResult#key -msgid "Result key" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript() -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript() -msgid "Run Fixture Script" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript -msgid "Script" -msgstr "" - - -#: domainapp.fixture.DomainAppFixturesService#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -#: org.apache.isis.applib.fixturescripts.FixtureScripts#runFixtureScript(org.apache.isis.applib.fixturescripts.FixtureScript,java.lang.String) -msgid "Script-specific parameters (if any). The format depends on the script implementation (eg key=value, CSV, JSON, XML etc)" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObjects#title() -msgid "Simple Objects" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToReadingTranslations() -msgid "Switch To Reading Translations" -msgstr "" - - -#: org.apache.isis.core.runtime.services.i18n.po.TranslationServicePoMenu#switchToWritingTranslations() -msgid "Switch To Writing Translations" -msgstr "" - - -#: org.apache.isis.applib.fixturescripts.FixtureScript#type -msgid "Type" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject#updateName() -msgid "Update Name" -msgstr "" - - -#: domainapp.dom.modules.simple.SimpleObject -msgid "name" -msgstr "" - - - - - -############################################################################## -# end of .pot file -############################################################################## - diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_restfulobjects.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_restfulobjects.properties deleted file mode 100644 index 0a85fb681bc9..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_restfulobjects.properties +++ /dev/null @@ -1,66 +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. - -# -# configuration file for the Restful Objects viewer -# - -# the baseUrl for hrefs in the events generated by the RO EventSerializer -isis.viewer.restfulobjects.RestfulObjectsSpecEventSerializer.baseUrl=http://localhost:8080/restful/ - -# renders param details in the (incorrect) form that they were for GSOC2013 viewers -# isis.viewer.restfulobjects.gsoc2013.legacyParamDetails=true - -# whether to honor UI hints, in particular Render(EAGERLY). Defaults to false. -#isis.viewer.restfulobjects.honorUiHints=false - - - -############################################################################### -# Non-standard configuration settings. -# -# If enabled of the following are enabled then the viewer is deviating from the -# RO spec standard; compatibility may be compromised with RO clients. -############################################################################### - -# whether to show only object properties for object members -# (on the object representation only) -# Takes precedence over the other 'suppress' below. -#isis.viewer.restfulobjects.objectPropertyValuesOnly=true - -# whether to suppress "describedby" links. Defaults to false. -#isis.viewer.restfulobjects.suppressDescribedByLinks=true - -# whether to suppress "update" links. Defaults to false. -#isis.viewer.restfulobjects.suppressUpdateLink=true - -# whether to suppress "id" json-prop for object members. Defaults to false. -#isis.viewer.restfulobjects.suppressMemberId=true - -# whether to suppress "links" json-prop for object members -# (on the object representation only). Defaults to false. -#isis.viewer.restfulobjects.suppressMemberLinks=true - -# whether to suppress "extensions" json-prop for object members -# (on the object representation only). Defaults to false. -#isis.viewer.restfulobjects.suppressMemberExtensions=true - -# whether to suppress "disabledReason" json-prop for object members -# (on the object representation only). Defaults to false. -#isis.viewer.restfulobjects.suppressMemberDisabledReason=true - -############################################################################### diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_wicket.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_wicket.properties deleted file mode 100644 index ba9eaaffb873..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/viewer_wicket.properties +++ /dev/null @@ -1,91 +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. - -# -# configuration file for the Wicket viewer -# - -# -# The maximum length of titles to display in standalone or parented tables. -# Titles longer than this length will be truncated with trailing ellipses (...) -# -# For example, if set to 12, the title -# "Buy milk on 15-Feb-13" will be truncated to "Buy milk ..." -# -# If set to 0, then only the icon will be shown. -# -isis.viewer.wicket.maxTitleLengthInStandaloneTables=0 -isis.viewer.wicket.maxTitleLengthInParentedTables=0 - - -#isis.viewer.wicket.datePattern=dd-MM-yyyy -#isis.viewer.wicket.dateTimePattern=dd-MM-yyyy HH:mm -#isis.viewer.wicket.datePickerPattern=DD-MM-YYYY - -#isis.viewer.wicket.datePattern=dd/MM/yy -#isis.viewer.wicket.dateTimePattern=dd/MM/yy HH:mm -#isis.viewer.wicket.datePickerPattern=DD/MM/YY - - -# -# whether to strip wicket tags from markup (default is true, as they may break some CSS rules) -# -#isis.viewer.wicket.stripWicketTags=false - - -# -# whether to suppress the 'rememberMe' checkbox on the login page (default is false) -# -#isis.viewer.wicket.suppressRememberMe=false - -# -# if user attempts to access a protected URL before signing in, then as a convenience the viewer will continue -# through to that destination after successful login. If you consider this to be a security risk then this flag -# disables that behaviour (default is false). -# -#isis.viewer.wicket.clearOriginalDestination=true - - -# -# whether to show action dialogs on their own page rather than as a modal dialog (default is false) -# -#isis.viewer.wicket.disableModalDialogs=false - - -# -# the maximum number of pages to list in bookmark (default is 15) -# -#isis.viewer.wicket.bookmarkedPages.maxSize=15 - - -# -# whether to show the bootstrap theme chooser (defaults false) -# -#isis.viewer.wicket.themes.showChooser=false -isis.viewer.wicket.themes.showChooser=true - -# -# comma-separated list of themes to choose from (default is to show all themes from bootswatch.com). -# -#isis.viewer.wicket.themes.enabled=bootstrap-theme,Cosmo,Flatly,Darkly,Sandstone,United - - - -# -# whether to automatically select dependent choice when the choice it depends upon changes. -# -#isis.viewer.wicket.disableDependentChoiceAutoSelection=false \ No newline at end of file diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/web.xml b/naked-objects/webapp/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index bb6098f0bcfa..000000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,309 +0,0 @@ - - - - - Simple app - - - about/index.html - - - - - org.apache.shiro.web.env.EnvironmentLoaderListener - - - - ShiroFilter - org.apache.shiro.web.servlet.ShiroFilter - - - - ShiroFilter - /* - - - - - - - - - - - isis.viewers - wicket,restfulobjects - - - - - - - IsisLogOnExceptionFilter - org.apache.isis.core.webapp.diagnostics.IsisLogOnExceptionFilter - - - IsisLogOnExceptionFilter - /wicket/* - - - IsisLogOnExceptionFilter - /restful/* - - - - - - - ResourceCachingFilter - org.apache.isis.core.webapp.content.ResourceCachingFilter - - CacheTime - 86400 - - - - ResourceCachingFilter - *.js - - - ResourceCachingFilter - *.css - - - ResourceCachingFilter - *.png - - - ResourceCachingFilter - *.jpg - - - ResourceCachingFilter - *.gif - - - ResourceCachingFilter - *.html - - - ResourceCachingFilter - *.swf - - - - Resource - org.apache.isis.core.webapp.content.ResourceServlet - - - Resource - *.css - - - Resource - *.png - - - Resource - *.jpg - - - Resource - *.gif - - - Resource - *.js - - - Resource - *.html - - - Resource - *.swf - - - - - - - WicketFilter - org.apache.wicket.protocol.http.WicketFilter - - applicationClassName - domainapp.webapp.SimpleApplication - - - - WicketFilter - /wicket/* - - - - - configuration - - development - - - - - - - - - - org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap - - - - - javax.ws.rs.Application - org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplication - - - - resteasy.servlet.mapping.prefix - /restful/ - - - - - - IsisSessionFilterForRestfulObjects - org.apache.isis.core.webapp.IsisSessionFilter - - - authenticationSessionStrategy - org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationSessionStrategyBasicAuth - - - - whenNoSession - basicAuthChallenge - - - - - IsisSessionFilterForRestfulObjects - RestfulObjectsRestEasyDispatcher - - - - IsisTransactionFilterForRestfulObjects - org.apache.isis.viewer.restfulobjects.server.webapp.IsisTransactionFilterForRestfulObjects - - - IsisTransactionFilterForRestfulObjects - RestfulObjectsRestEasyDispatcher - - - - - RestfulObjectsRestEasyDispatcher - org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher - - - RestfulObjectsRestEasyDispatcher - /restful/* - - - - - - - - - - diff --git a/naked-objects/webapp/src/main/webapp/about/images/isis-logo.png b/naked-objects/webapp/src/main/webapp/about/images/isis-logo.png deleted file mode 100644 index 5284fe73242502a9dbefd1f79af51ba36c773ecf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14160 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%0AwvS3t7R5SVwRK)Za~97RViV; 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 - - - - - - Apache Isis™ SimpleApp - - - - -
    - Isis Logo - -

    - This app has been generated using Apache Isis' - SimpleApp archetype, - to create a purposefully minimal application that nevertheless includes fixture data, integration tests and BDD specs. -
    -
    - The app itself consists of a single domain class, SimpleObject, - along with an equally simple (factory/repository) domain service, SimpleObjects. -

    - -

    To access the app:

    -
      -
    • -

      - wicket/ -

      -

      - provides accesses to a generic UI for end-users, - Isis' Wicket Viewer. - As its name suggests, this viewer is built on top of Apache Wicket™. -

      -
    • -
    • -

      - - restful/ - -

      -

      - provides access to a RESTful API conformant with the - Restful Objects spec. This is part of Apache Isis Core. The - implementation technology is JBoss RestEasy. -

      -
    • -
    - -

    - The default user/password is sven/pass (as configured in the - shiro.ini file). -

    - -
    - - diff --git a/naked-objects/webapp/src/main/webapp/css/application.css b/naked-objects/webapp/src/main/webapp/css/application.css deleted file mode 100644 index 9f1612af1a24..000000000000 --- a/naked-objects/webapp/src/main/webapp/css/application.css +++ /dev/null @@ -1,19 +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. - */ - diff --git a/naked-objects/webapp/src/main/webapp/images/spinning-icon.gif b/naked-objects/webapp/src/main/webapp/images/spinning-icon.gif deleted file mode 100644 index 75e3b1e5baa32a169f85a25f2031f3058b834e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5266 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 c+@WreO4w$XYg_@Jv!N)wRF$cG@h0Sd0dX=M!T - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/null-object/etc/null-object.urm.puml b/null-object/etc/null-object.urm.puml deleted file mode 100644 index a937a2b178e2..000000000000 --- a/null-object/etc/null-object.urm.puml +++ /dev/null @@ -1,41 +0,0 @@ -@startuml -package com.iluwatar.nullobject { - class App { - + App() - + main(args : String[]) {static} - } - interface Node { - + getLeft() : Node {abstract} - + getName() : String {abstract} - + getRight() : Node {abstract} - + getTreeSize() : int {abstract} - + walk() {abstract} - } - class NodeImpl { - - LOGGER : Logger {static} - - left : Node - - name : String - - right : Node - + NodeImpl(name : String, left : Node, right : Node) - + getLeft() : Node - + getName() : String - + getRight() : Node - + getTreeSize() : int - + walk() - } - class NullNode { - - instance : NullNode {static} - - NullNode() - + getInstance() : NullNode {static} - + getLeft() : Node - + getName() : String - + getRight() : Node - + getTreeSize() : int - + walk() - } -} -NullNode --> "-instance" NullNode -NodeImpl --> "-left" Node -NodeImpl ..|> Node -NullNode ..|> Node -@enduml \ No newline at end of file diff --git a/null-object/pom.xml b/null-object/pom.xml deleted file mode 100644 index 755db259ebaa..000000000000 --- a/null-object/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - null-object - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/null-object/src/main/java/com/iluwatar/nullobject/App.java b/null-object/src/main/java/com/iluwatar/nullobject/App.java deleted file mode 100644 index 2a1e3d316606..000000000000 --- a/null-object/src/main/java/com/iluwatar/nullobject/App.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -/** - * - * Null Object pattern replaces null values with neutral objects. Many times this simplifies - * algorithms since no extra null checks are needed. - *

    - * In this example we build a binary tree where the nodes are either normal or Null Objects. No null - * values are used in the tree making the traversal easy. - * - */ -public class App { - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - Node root = - new NodeImpl("1", new NodeImpl("11", new NodeImpl("111", NullNode.getInstance(), - NullNode.getInstance()), NullNode.getInstance()), new NodeImpl("12", - NullNode.getInstance(), new NodeImpl("122", NullNode.getInstance(), - NullNode.getInstance()))); - - root.walk(); - } -} diff --git a/null-object/src/main/java/com/iluwatar/nullobject/Node.java b/null-object/src/main/java/com/iluwatar/nullobject/Node.java deleted file mode 100644 index bae4f84eb6c6..000000000000 --- a/null-object/src/main/java/com/iluwatar/nullobject/Node.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -/** - * - * Interface for binary tree node. - * - */ -public interface Node { - - String getName(); - - int getTreeSize(); - - Node getLeft(); - - Node getRight(); - - void walk(); -} diff --git a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java b/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java deleted file mode 100644 index f9f33c67f434..000000000000 --- a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Implementation for binary tree's normal nodes. - * - */ -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; - - /** - * Constructor - */ - public NodeImpl(String name, Node left, Node right) { - this.name = name; - this.left = left; - this.right = right; - } - - @Override - public int getTreeSize() { - return 1 + left.getTreeSize() + right.getTreeSize(); - } - - @Override - public Node getLeft() { - return left; - } - - @Override - public Node getRight() { - return right; - } - - @Override - public String getName() { - return name; - } - - @Override - public void walk() { - LOGGER.info(name); - if (left.getTreeSize() > 0) { - left.walk(); - } - if (right.getTreeSize() > 0) { - right.walk(); - } - } -} diff --git a/null-object/src/main/java/com/iluwatar/nullobject/NullNode.java b/null-object/src/main/java/com/iluwatar/nullobject/NullNode.java deleted file mode 100644 index 67c5530158cf..000000000000 --- a/null-object/src/main/java/com/iluwatar/nullobject/NullNode.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -/** - * - * Null Object implementation for binary tree node. - *

    - * Implemented as Singleton, since all the NullNodes are the same. - * - */ -public final class NullNode implements Node { - - private static NullNode instance = new NullNode(); - - private NullNode() {} - - public static NullNode getInstance() { - return instance; - } - - @Override - public int getTreeSize() { - return 0; - } - - @Override - public Node getLeft() { - return null; - } - - @Override - public Node getRight() { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void walk() { - // Do nothing - } -} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/AppTest.java b/null-object/src/test/java/com/iluwatar/nullobject/AppTest.java deleted file mode 100644 index 13e92034a2c7..000000000000 --- a/null-object/src/test/java/com/iluwatar/nullobject/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java deleted file mode 100644 index 778344e0679f..000000000000 --- a/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.nullobject; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Date: 12/26/15 - 11:47 PM - * - * @author Jeroen Meulemeester - */ -public class NullNodeTest { - - /** - * Verify if {@link NullNode#getInstance()} actually returns the same object instance - */ - @Test - public void testGetInstance() { - final NullNode instance = NullNode.getInstance(); - assertNotNull(instance); - assertSame(instance, NullNode.getInstance()); - } - - @Test - public void testFields() { - final NullNode node = NullNode.getInstance(); - assertEquals(0, node.getTreeSize()); - assertNull(node.getName()); - assertNull(node.getLeft()); - assertNull(node.getRight()); - } - - @Test - public void testWalk() throws Exception { - NullNode.getInstance().walk(); - } - -} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java deleted file mode 100644 index 6a683a60e538..000000000000 --- a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.slf4j.LoggerFactory; - -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 { - - 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 - * terminated with the {@link NullNode} instance. - * - *

    -   * root
    -   * ├── level1_a
    -   * │   ├── level2_a
    -   * │   │   ├── level3_a
    -   * │   │   └── level3_b
    -   * │   └── level2_b
    -   * └── level1_b
    -   * 
    - */ - private static final Node TREE_ROOT; - - static { - final NodeImpl level1B = new NodeImpl("level1_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level2B = new NodeImpl("level2_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level3A = new NodeImpl("level3_a", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level3B = new NodeImpl("level3_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level2A = new NodeImpl("level2_a", level3A, level3B); - final NodeImpl level1A = new NodeImpl("level1_a", level2A, level2B); - TREE_ROOT = new NodeImpl("root", level1A, level1B); - } - - /** - * Verify the number of items in the tree. The root has 6 children so we expect a {@link - * Node#getTreeSize()} of 7 {@link Node}s in total. - */ - @Test - public void testTreeSize() { - assertEquals(7, TREE_ROOT.getTreeSize()); - } - - /** - * Walk through the tree and verify if every item is handled - */ - @Test - public void testWalk() { - TREE_ROOT.walk(); - - 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 - public void testGetLeft() throws Exception { - final Node level1 = TREE_ROOT.getLeft(); - assertNotNull(level1); - assertEquals("level1_a", level1.getName()); - assertEquals(5, level1.getTreeSize()); - - final Node level2 = level1.getLeft(); - assertNotNull(level2); - assertEquals("level2_a", level2.getName()); - assertEquals(3, level2.getTreeSize()); - - final Node level3 = level2.getLeft(); - assertNotNull(level3); - assertEquals("level3_a", level3.getName()); - assertEquals(1, level3.getTreeSize()); - assertSame(NullNode.getInstance(), level3.getRight()); - assertSame(NullNode.getInstance(), level3.getLeft()); - } - - @Test - public void testGetRight() throws Exception { - final Node level1 = TREE_ROOT.getRight(); - assertNotNull(level1); - assertEquals("level1_b", level1.getName()); - assertEquals(1, level1.getTreeSize()); - assertSame(NullNode.getInstance(), level1.getRight()); - 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/object-mother/README.md b/object-mother/README.md deleted file mode 100644 index cda3336cf991..000000000000 --- a/object-mother/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: pattern -title: Object Mother -folder: object-mother -permalink: /patterns/object-mother/ -pumlid: LOr13iCW30JlVKNx0E3UKxxYW9KGWK7sklb-wR6dtLbfj9k15DxRurKbDo_isfudCEsTaj8TZuhJTpVMF0GiY7dqL9lVjDHqqOT2OQk7X4a0grZgPAkaiL-S4Vh0kOYH_vVeskFyVMyiPUKN -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) diff --git a/object-mother/etc/object-mother.png b/object-mother/etc/object-mother.png deleted file mode 100644 index 807343d9f9e42c2b3f306beb5c8e2199bbedafb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19705 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 diff --git a/object-mother/etc/object-mother.ucls b/object-mother/etc/object-mother.ucls deleted file mode 100644 index ef6cee5eff45..000000000000 --- a/object-mother/etc/object-mother.ucls +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/object-mother/etc/object-mother.urm.puml b/object-mother/etc/object-mother.urm.puml deleted file mode 100644 index 1bb52f2ed6c6..000000000000 --- a/object-mother/etc/object-mother.urm.puml +++ /dev/null @@ -1,45 +0,0 @@ -@startuml -package com.iluwatar.objectmother { - class King { - ~ isDrunk : boolean - ~ isHappy : boolean - + King() - + flirt(queen : Queen) - + isHappy() : boolean - + makeDrunk() - + makeHappy() - + makeSober() - + makeUnhappy() - } - class Queen { - - isDrunk : boolean - - isFlirty : boolean - - isHappy : boolean - + Queen() - + getFlirted(king : King) : boolean - + isFlirty() : boolean - + makeDrunk() - + makeHappy() - + makeSober() - + makeUnhappy() - + setFlirtiness(flirtiness : boolean) - } - interface Royalty { - + makeDrunk() {abstract} - + makeHappy() {abstract} - + makeSober() {abstract} - + makeUnhappy() {abstract} - } - class RoyaltyObjectMother { - + RoyaltyObjectMother() - + createDrunkKing() : King {static} - + createFlirtyQueen() : Queen {static} - + createHappyDrunkKing() : King {static} - + createHappyKing() : King {static} - + createNotFlirtyQueen() : Queen {static} - + createSoberUnhappyKing() : King {static} - } -} -King ..|> Royalty -Queen ..|> Royalty -@enduml \ No newline at end of file diff --git a/object-mother/pom.xml b/object-mother/pom.xml deleted file mode 100644 index 9b91718888d4..000000000000 --- a/object-mother/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.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 deleted file mode 100644 index b1b5f36100f0..000000000000 --- a/object-mother/src/main/java/com/iluwatar/objectmother/King.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * 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; - -/** - * Defines all attributes and behaviour related to the King - */ -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 deleted file mode 100644 index e7e4886022b4..000000000000 --- a/object-mother/src/main/java/com/iluwatar/objectmother/Queen.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * 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; - -/** - * Defines all attributes and behaviour related to the Queen - */ -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 deleted file mode 100644 index 42271a21df3c..000000000000 --- a/object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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; - -/** - * Interface contracting Royalty Behaviour - */ -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 deleted file mode 100644 index 118253d56c51..000000000000 --- a/object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * 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; - -/** - * Object Mother Pattern generating Royalty Types - */ -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 deleted file mode 100644 index cc5af45aab1e..000000000000 --- a/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * 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; - -/** - * Test Generation of Royalty Types using the object-mother - */ -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 drunkUnhappyKing = RoyaltyObjectMother.createDrunkKing(); - Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); - drunkUnhappyKing.flirt(notFlirtyQueen); - assertFalse(drunkUnhappyKing.isHappy()); - } - - @Test - public void queenIsBlockingFlirt() { - King soberHappyKing = RoyaltyObjectMother.createHappyKing(); - Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); - soberHappyKing.flirt(notFlirtyQueen); - assertFalse(soberHappyKing.isHappy()); - } - - @Test - public void successfullKingFlirt() { - King soberHappyKing = RoyaltyObjectMother.createHappyKing(); - Queen flirtyQueen = RoyaltyObjectMother.createFlirtyQueen(); - soberHappyKing.flirt(flirtyQueen); - assertTrue(soberHappyKing.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); - } -} diff --git a/object-pool/README.md b/object-pool/README.md deleted file mode 100644 index 15fee51aa0fc..000000000000 --- a/object-pool/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Object Pool -folder: object-pool -permalink: /patterns/object-pool/ -pumlid: JSV94SCm2030Lk829Fxf1cF6bWU1XYDkFtdcjxiD9Qc3o-LrPQvu0pW-_HnvrLx1JgR9cfrimf1wCD7XnW-sWsESsXPcicl0nFW1RB-PiYqp0KxwVo-VVTMKBm00 -categories: Creational -tags: - - Java - - Difficulty-Beginner - - Performance ---- - -## Intent -When objects are expensive to create and they are needed only for -short periods of time it is advantageous to utilize the Object Pool pattern. -The Object Pool provides a cache for instantiated objects tracking which ones -are in use and which are available. - -![alt text](./etc/object-pool.png "Object Pool") - -## Applicability -Use the Object Pool pattern when - -* the objects are expensive to create (allocation cost) -* you need a large number of short-lived objects (memory fragmentation) diff --git a/object-pool/etc/object-pool.png b/object-pool/etc/object-pool.png deleted file mode 100644 index b8ede36c5a47660b8c699f03f8bceee99d84985c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8877 zcmd6NWmr^g*S5DJA>Acif;2{VRxp5?G`En>;5l&RDaUL1a8%*0btX#hviAkNcFH4g2E7=gXAKE!7o^+wdc!&2Bl>5(8|{A#MFSP_)GF5dod!9$Oh4lw%X;}l=-KbKmubja2j-^nlRKhGzc(` zi7!#j$`zXZuobKK1*I zZFx?r(w{#a&7r2wUjHFNn~DvXqpwVL(YB}glUqQG-QV)FHWPW?5(vb=!f0CBF5w>r znv{vk*z4j~$}1-(GnH3ipM$GYahU2yvB1{NG&-LK!5PWL&SLDkA}%cr$L~KsjNozi z;JMV3EcPWh1N?Z-%b)Yao*SHhobL-LR%gl~GtqCy^D>BCBS%jlcBHL7M0Dmicbhej z=DKj?s8`k^pE7fm_j3C^i}laEN+7F^up7gVBlzW}CrjhT#0!vP&RMfS=VJIOU<$u#VEPPGy4%lQ_d zZLmD&Iyuoc#M5%qzD*agbo~SOuwnmvTmt}hc;^vHr?3twjK7ndV9n({ZME(WWLwpE zd&iL3c~Dkw-}}VI4fX_o*7fzk`!h~0%hjTY`p~n$+N*tm#nCsZ!VZP!2l>~SgK8&< z2>|3@^wWh`w!$=i`yX|mzL_2qZh5d7$0XbYxifDq=V$ajr{!^N4>Ubw+=~dCAQ&;B zbVyrrVC3qSi@e>PyfTL~b5SotNESkPuD!n;duYY_ying_+3n5~E}i$& z8%y6|29bN5iwM`Ju9-xOX0|rIRwMfoUn8f>3?A?-F%>kp8cc3wQab+{gU^P9D=q*xlYw|dnVH!5S?Uw%Z>{~~en_bV#(;^z1rp2;z=tKF{+kn? zfd)(k&f{x~xbzScNQ-c@)%XrTv|W1m`skCA9#@i?@=iT*B~OY(ovnAz^Tw&sr}29c z1sHxB?Bc$O>Gq5U;-$?Yk6wj0D(g@Zh`n3!0u$F0M>>tW6Z8knox8;`}EIGJ3g0K;ELzw+ww`^pT|kS7@>9Z={^_f&t^ET01ae`+2_( zO&^WyL(=N+T10}WlwE)*IoD)$gw0PV;x4aC!Y@{9h4tNzs^-{�{S#)qtqVQ3p2b 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 diff --git a/object-pool/etc/object-pool.ucls b/object-pool/etc/object-pool.ucls deleted file mode 100644 index 9c924a87d069..000000000000 --- a/object-pool/etc/object-pool.ucls +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/object-pool/etc/object-pool.urm.puml b/object-pool/etc/object-pool.urm.puml deleted file mode 100644 index ca74f8cec5ec..000000000000 --- a/object-pool/etc/object-pool.urm.puml +++ /dev/null @@ -1,30 +0,0 @@ -@startuml -package com.iluwatar.object.pool { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - abstract class ObjectPool { - - available : Set - - inUse : Set - + ObjectPool() - + checkIn(instance : T) - + checkOut() : T - # create() : T {abstract} - + toString() : String - } - class Oliphaunt { - - counter : int {static} - - id : int - + Oliphaunt() - + getId() : int - + toString() : String - } - class OliphauntPool { - + OliphauntPool() - # create() : Oliphaunt - } -} -OliphauntPool --|> ObjectPool -@enduml \ No newline at end of file diff --git a/object-pool/pom.xml b/object-pool/pom.xml deleted file mode 100644 index 4ebb4038575e..000000000000 --- a/object-pool/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - object-pool - - - junit - junit - test - - - 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 deleted file mode 100644 index 2da4244b6bb8..000000000000 --- a/object-pool/src/main/java/com/iluwatar/object/pool/App.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * instantiate and each object is only needed for a short period of time, the performance of an - * entire application may be adversely affected. An object pool design pattern may be deemed - * desirable in cases such as these. - *

    - * The object pool design pattern creates a set of objects that may be reused. When a new object is - * needed, it is requested from the pool. If a previously prepared object is available it is - * returned immediately, avoiding the instantiation cost. If no objects are present in the pool, a - * new item is created and returned. When the object has been used and is no longer needed, it is - * returned to the pool, allowing it to be used again in the future without repeating the - * computationally expensive instantiation process. It is important to note that once an object has - * been used and returned, existing references will become invalid. - *

    - * In this example we have created {@link OliphauntPool} inheriting from generic {@link ObjectPool}. - * {@link Oliphaunt}s can be checked out from the pool and later returned to it. The pool tracks - * created instances and their status (available, inUse). - * - */ -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) { - OliphauntPool pool = new OliphauntPool(); - LOGGER.info(pool.toString()); - Oliphaunt oliphaunt1 = pool.checkOut(); - LOGGER.info("Checked out {}", oliphaunt1); - LOGGER.info(pool.toString()); - Oliphaunt oliphaunt2 = pool.checkOut(); - LOGGER.info("Checked out {}", oliphaunt2); - Oliphaunt oliphaunt3 = pool.checkOut(); - LOGGER.info("Checked out {}", oliphaunt3); - LOGGER.info(pool.toString()); - LOGGER.info("Checking in {}", oliphaunt1); - pool.checkIn(oliphaunt1); - LOGGER.info("Checking in {}", oliphaunt2); - pool.checkIn(oliphaunt2); - LOGGER.info(pool.toString()); - Oliphaunt oliphaunt4 = pool.checkOut(); - LOGGER.info("Checked out {}", oliphaunt4); - Oliphaunt oliphaunt5 = pool.checkOut(); - LOGGER.info("Checked out {}", oliphaunt5); - LOGGER.info(pool.toString()); - } -} diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java b/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java deleted file mode 100644 index e76d003521a5..000000000000 --- a/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.object.pool; - -import java.util.HashSet; -import java.util.Set; - -/** - * Generic object pool - * @param Type T of Object in the Pool - */ -public abstract class ObjectPool { - - private Set available = new HashSet<>(); - private Set inUse = new HashSet<>(); - - protected abstract T create(); - - /** - * Checkout object from pool - */ - public synchronized T checkOut() { - if (available.isEmpty()) { - available.add(create()); - } - T instance = available.iterator().next(); - available.remove(instance); - inUse.add(instance); - return instance; - } - - public synchronized void checkIn(T instance) { - inUse.remove(instance); - available.add(instance); - } - - @Override - public synchronized String toString() { - return String.format("Pool available=%d inUse=%d", available.size(), inUse.size()); - } -} diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java b/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java deleted file mode 100644 index cc705b2b3698..000000000000 --- a/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.object.pool; - -/** - * - * Oliphaunts are expensive to create - * - */ -public class Oliphaunt { - - private static int counter = 1; - - private final int id; - - /** - * Constructor - */ - public Oliphaunt() { - id = counter++; - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public int getId() { - return id; - } - - @Override - public String toString() { - return String.format("Oliphaunt id=%d", id); - } -} diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/OliphauntPool.java b/object-pool/src/main/java/com/iluwatar/object/pool/OliphauntPool.java deleted file mode 100644 index 24e65070ac3b..000000000000 --- a/object-pool/src/main/java/com/iluwatar/object/pool/OliphauntPool.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.object.pool; - -/** - * - * Oliphaunt object pool - * - */ -public class OliphauntPool extends ObjectPool { - - @Override - protected Oliphaunt create() { - return new Oliphaunt(); - } -} diff --git a/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java b/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java deleted file mode 100644 index c92399c32e8d..000000000000 --- a/object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.object.pool; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java b/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java deleted file mode 100644 index 46ed22b3642a..000000000000 --- a/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.object.pool; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/27/15 - 1:05 AM - * - * @author Jeroen Meulemeester - */ -public class OliphauntPoolTest { - - /** - * Use the same object 100 times subsequently. This should not take much time since the heavy - * object instantiation is done only once. Verify if we get the same object each time. - */ - @Test(timeout = 5000) - public void testSubsequentCheckinCheckout() { - final OliphauntPool pool = new OliphauntPool(); - assertEquals(pool.toString(), "Pool available=0 inUse=0"); - - final Oliphaunt expectedOliphaunt = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=1"); - - pool.checkIn(expectedOliphaunt); - assertEquals(pool.toString(), "Pool available=1 inUse=0"); - - for (int i = 0; i < 100; i++) { - final Oliphaunt oliphaunt = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=1"); - assertSame(expectedOliphaunt, oliphaunt); - assertEquals(expectedOliphaunt.getId(), oliphaunt.getId()); - assertEquals(expectedOliphaunt.toString(), oliphaunt.toString()); - - pool.checkIn(oliphaunt); - assertEquals(pool.toString(), "Pool available=1 inUse=0"); - } - - } - - /** - * Use the same object 100 times subsequently. This should not take much time since the heavy - * object instantiation is done only once. Verify if we get the same object each time. - */ - @Test(timeout = 5000) - public void testConcurrentCheckinCheckout() { - final OliphauntPool pool = new OliphauntPool(); - assertEquals(pool.toString(), "Pool available=0 inUse=0"); - - final Oliphaunt firstOliphaunt = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=1"); - - final Oliphaunt secondOliphaunt = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=2"); - - assertNotSame(firstOliphaunt, secondOliphaunt); - assertEquals(firstOliphaunt.getId() + 1, secondOliphaunt.getId()); - - // After checking in the second, we should get the same when checking out a new oliphaunt ... - pool.checkIn(secondOliphaunt); - assertEquals(pool.toString(), "Pool available=1 inUse=1"); - - final Oliphaunt oliphaunt3 = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=2"); - assertSame(secondOliphaunt, oliphaunt3); - - // ... and the same applies for the first one - pool.checkIn(firstOliphaunt); - assertEquals(pool.toString(), "Pool available=1 inUse=1"); - - final Oliphaunt oliphaunt4 = pool.checkOut(); - assertEquals(pool.toString(), "Pool available=0 inUse=2"); - assertSame(firstOliphaunt, oliphaunt4); - - // When both oliphaunt return to the pool, we should still get the same instances - pool.checkIn(firstOliphaunt); - assertEquals(pool.toString(), "Pool available=1 inUse=1"); - - pool.checkIn(secondOliphaunt); - assertEquals(pool.toString(), "Pool available=2 inUse=0"); - - // The order of the returned instances is not determined, so just put them in a list - // and verify if both expected instances are in there. - final List oliphaunts = Arrays.asList(pool.checkOut(), pool.checkOut()); - assertEquals(pool.toString(), "Pool available=0 inUse=2"); - assertTrue(oliphaunts.contains(firstOliphaunt)); - assertTrue(oliphaunts.contains(secondOliphaunt)); - - } - - -} \ No newline at end of file diff --git a/page-object/README.md b/page-object/README.md deleted file mode 100644 index 16c021dfbb7f..000000000000 --- a/page-object/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Page Object -folder: page-object -permalink: /patterns/page-object/ -categories: Testing -tags: -- Java -- Difficulty-Intermediate ---- - -## Intent - -Page Object encapsulates the UI, hiding the underlying UI widgetry of an application (commonly a web application) and providing an application-specific API to allow the manipulation of UI components required for tests. In doing so, it allows the test class itself to focus on the test logic instead. - - -![alt text](./etc/page-object.png "Page Object") - - -## Applicability - -Use the Page Object pattern when - -* You are writing automated tests for your web application and you want to separate the UI manipulation required for the tests from the actual test logic. -* Make your tests less brittle, and more readable and robust - -## Credits - -* [Martin Fowler - PageObject](http://martinfowler.com/bliki/PageObject.html) -* [Selenium - Page Objects](https://github.com/SeleniumHQ/selenium/wiki/PageObjects) diff --git a/page-object/etc/page-object.png b/page-object/etc/page-object.png deleted file mode 100644 index 4240b438efbb2179ff5efc7f1795d4a1b431e580..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49696 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 - - - - - - - \ No newline at end of file diff --git a/page-object/etc/page-object.urm.puml b/page-object/etc/page-object.urm.puml deleted file mode 100644 index 735cf2889bcb..000000000000 --- a/page-object/etc/page-object.urm.puml +++ /dev/null @@ -1,8 +0,0 @@ -@startuml -package com.iluwatar.pageobject { - class App { - - App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/page-object/pom.xml b/page-object/pom.xml deleted file mode 100644 index 98842b387145..000000000000 --- a/page-object/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - page-object - - - junit - junit - test - - - net.sourceforge.htmlunit - htmlunit - - - diff --git a/page-object/src/main/java/com/iluwatar/pageobject/App.java b/page-object/src/main/java/com/iluwatar/pageobject/App.java deleted file mode 100644 index 5983a4dc3bd5..000000000000 --- a/page-object/src/main/java/com/iluwatar/pageobject/App.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject; - -import java.awt.Desktop; -import java.io.File; -import java.io.IOException; - -/** - * Page Object pattern wraps an UI component with an application specific API allowing you to - * manipulate the UI elements without having to dig around with the underlying UI technology used. This is - * especially useful for testing as it means your tests will be less brittle. Your tests can concentrate on - * the actual test cases where as the manipulation of the UI can be left to the internals of the page object - * itself. - * - *

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

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

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

    - * For illustrations purposes only, a very simple static html app is used here. This main method - * just fires up this simple web app in a default browser. - * - * @param args arguments - */ - public static void main(String[] args) { - - try { - File applicationFile = new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); - - // should work for unix like OS (mac, unix etc...) - if (Desktop.isDesktopSupported()) { - Desktop.getDesktop().open(applicationFile); - - } else { - // java Desktop not supported - above unlikely to work for Windows so try following instead... - Runtime.getRuntime().exec("cmd.exe start " + applicationFile); - } - - } catch (IOException ex) { - ex.printStackTrace(); - } - - } -} diff --git a/page-object/src/main/resources/sample-ui/album-list.html b/page-object/src/main/resources/sample-ui/album-list.html deleted file mode 100644 index 7e674c60abf9..000000000000 --- a/page-object/src/main/resources/sample-ui/album-list.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - Album List - - - - -

    -

    My Album Viewer

    -
    - -
    -
    - - - - - - - - - - - - - - - -
    Album TitleAlbum YearAlbum RatingNumber of SongsArtist
    212011A11Adele
    -
    -
    - - - \ No newline at end of file diff --git a/page-object/src/main/resources/sample-ui/album-page.html b/page-object/src/main/resources/sample-ui/album-page.html deleted file mode 100644 index 44420c6d6d3c..000000000000 --- a/page-object/src/main/resources/sample-ui/album-page.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - Album Page - - - -
    -

    21

    -
    - -
    -
    -
    - - - - - - - - - - - - - - - - - - - -
    Title:
    Artist:
    Year: - -
    Rating:
    Number of Songs:
    -
    -
    -
    - - - \ No newline at end of file diff --git a/page-object/src/main/resources/sample-ui/css/album-list.css b/page-object/src/main/resources/sample-ui/css/album-list.css deleted file mode 100644 index 744eb22dcdf7..000000000000 --- a/page-object/src/main/resources/sample-ui/css/album-list.css +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -table { - font-size: 16px; - border-collapse: collapse; -} - -th { - background-color: #FFFFFF; - border: 1px solid black; - color: black; - width: 150px; - height: 20px; -} - -td { - border: 1px solid black; - background-color: white; -} - -th, td { - padding: 15px; - text-align: left; -} \ No newline at end of file diff --git a/page-object/src/main/resources/sample-ui/css/style.css b/page-object/src/main/resources/sample-ui/css/style.css deleted file mode 100644 index b70a481d02af..000000000000 --- a/page-object/src/main/resources/sample-ui/css/style.css +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -body { - font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; -} \ No newline at end of file diff --git a/page-object/src/main/resources/sample-ui/login.html b/page-object/src/main/resources/sample-ui/login.html deleted file mode 100644 index 2dd082fe54c2..000000000000 --- a/page-object/src/main/resources/sample-ui/login.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - Login - - - -
    -

    Login

    -
    - -
    -
    - - - - -
    Username:
    Password:
    - -
    -
    - - \ No newline at end of file diff --git a/page-object/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java b/page-object/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java deleted file mode 100644 index 79101f3d36b0..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject; - - -import static org.junit.Assert.assertTrue; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.iluwatar.pageobject.pages.AlbumListPage; -import com.iluwatar.pageobject.pages.AlbumPage; -import org.junit.Before; -import org.junit.Test; - -/** - * Test Album Selection and Album Listing - */ -public class AlbumListPageTest { - - private AlbumListPage albumListPage = new AlbumListPage(new WebClient()); - - @Before - public void setUp() { - albumListPage.navigateToPage(); - } - - @Test - public void testSelectAlbum() { - AlbumPage albumPage = albumListPage.selectAlbum("21"); - albumPage.navigateToPage(); - assertTrue(albumPage.isAt()); - } - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java b/page-object/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java deleted file mode 100644 index cb07a8293e1e..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject; - -import static org.junit.Assert.assertTrue; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.iluwatar.pageobject.pages.AlbumListPage; -import com.iluwatar.pageobject.pages.AlbumPage; -import org.junit.Before; -import org.junit.Test; - -/** - * Test Album Page Operations - */ -public class AlbumPageTest { - - private AlbumPage albumPage = new AlbumPage(new WebClient()); - - @Before - public void setUp() { - albumPage.navigateToPage(); - } - - @Test - public void testSaveAlbum() { - - AlbumPage albumPageAfterChanges = albumPage - .changeAlbumTitle("25") - .changeArtist("Adele Laurie Blue Adkins") - .changeAlbumYear(2015) - .changeAlbumRating("B") - .changeNumberOfSongs(20) - .saveChanges(); - - assertTrue(albumPageAfterChanges.isAt()); - - } - - @Test - public void testCancelChanges() { - AlbumListPage albumListPage = albumPage.cancelChanges(); - albumListPage.navigateToPage(); - assertTrue(albumListPage.isAt()); - } - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/LoginPageTest.java b/page-object/src/test/java/com/iluwatar/pageobject/LoginPageTest.java deleted file mode 100644 index ad10a1927840..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/LoginPageTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject; - -import static org.junit.Assert.assertTrue; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.iluwatar.pageobject.pages.AlbumListPage; -import com.iluwatar.pageobject.pages.LoginPage; -import org.junit.Before; -import org.junit.Test; - -/** - * Test Login Page Object - */ -public class LoginPageTest { - - private LoginPage loginPage = new LoginPage(new WebClient()); - - @Before - public void setUp() { - loginPage.navigateToPage(); - } - - @Test - public void testLogin() { - AlbumListPage albumListPage = loginPage - .enterUsername("admin") - .enterPassword("password") - .login(); - albumListPage.navigateToPage(); - assertTrue(albumListPage.isAt()); - } - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumListPage.java b/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumListPage.java deleted file mode 100644 index d212b33f301a..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumListPage.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject.pages; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlAnchor; -import com.gargoylesoftware.htmlunit.html.HtmlPage; - -import java.io.IOException; -import java.util.List; - -/** - * Page Object encapsulating the Album List page (album-list.html) - */ -public class AlbumListPage extends Page { - - private static final String ALBUM_LIST_HTML_FILE = "album-list.html"; - private static final String PAGE_URL = "file:" + AUT_PATH + ALBUM_LIST_HTML_FILE; - - private HtmlPage page; - - - /** - * Constructor - */ - public AlbumListPage(WebClient webClient) { - super(webClient); - } - - - /** - * Navigates to the Album List Page - * - * @return {@link AlbumListPage} - */ - public AlbumListPage navigateToPage() { - try { - page = this.webClient.getPage(PAGE_URL); - } catch (IOException e) { - e.printStackTrace(); - } - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAt() { - return "Album List".equals(page.getTitleText()); - } - - /** - * Selects an album by the given album title - * - * @param albumTitle the title of the album to click - * @return the album page - */ - public AlbumPage selectAlbum(String albumTitle) { - // uses XPath to find list of html anchor tags with the class album in it - List albumLinks = (List) page.getByXPath("//tr[@class='album']//a"); - for (HtmlAnchor anchor : albumLinks) { - if (anchor.getTextContent().equals(albumTitle)) { - try { - anchor.click(); - return new AlbumPage(webClient); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - throw new IllegalArgumentException("No links with the album title: " + albumTitle); - } - - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumPage.java b/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumPage.java deleted file mode 100644 index 7d2318257930..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumPage.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject.pages; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlNumberInput; -import com.gargoylesoftware.htmlunit.html.HtmlOption; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlSelect; -import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; -import com.gargoylesoftware.htmlunit.html.HtmlTextInput; - -import java.io.IOException; - -/** - * Page Object encapsulating the Album Page (album-page.html) - */ -public class AlbumPage extends Page { - - private static final String ALBUM_PAGE_HTML_FILE = "album-page.html"; - private static final String PAGE_URL = "file:" + AUT_PATH + ALBUM_PAGE_HTML_FILE; - - private HtmlPage page; - - - /** - * Constructor - */ - public AlbumPage(WebClient webClient) { - super(webClient); - } - - - /** - * Navigates to the album page - * - * @return {@link AlbumPage} - */ - public AlbumPage navigateToPage() { - try { - page = this.webClient.getPage(PAGE_URL); - } catch (IOException e) { - e.printStackTrace(); - } - return this; - } - - - /** - * {@inheritDoc} - */ - @Override - public boolean isAt() { - return "Album Page".equals(page.getTitleText()); - } - - - /** - * Sets the album title input text field - * - * @param albumTitle the new album title value to set - * @return {@link AlbumPage} - */ - public AlbumPage changeAlbumTitle(String albumTitle) { - HtmlTextInput albumTitleInputTextField = (HtmlTextInput) page.getElementById("albumTitle"); - albumTitleInputTextField.setText(albumTitle); - return this; - } - - - /** - * Sets the artist input text field - * - * @param artist the new artist value to set - * @return {@link AlbumPage} - */ - public AlbumPage changeArtist(String artist) { - HtmlTextInput artistInputTextField = (HtmlTextInput) page.getElementById("albumArtist"); - artistInputTextField.setText(artist); - return this; - } - - - /** - * Selects the select's option value based on the year value given - * - * @param year the new year value to set - * @return {@link AlbumPage} - */ - public AlbumPage changeAlbumYear(int year) { - HtmlSelect albumYearSelectOption = (HtmlSelect) page.getElementById("albumYear"); - HtmlOption yearOption = albumYearSelectOption.getOptionByValue(Integer.toString(year)); - albumYearSelectOption.setSelectedAttribute(yearOption, true); - return this; - } - - - /** - * Sets the album rating input text field - * - * @param albumRating the new album rating value to set - * @return {@link AlbumPage} - */ - public AlbumPage changeAlbumRating(String albumRating) { - HtmlTextInput albumRatingInputTextField = (HtmlTextInput) page.getElementById("albumRating"); - albumRatingInputTextField.setText(albumRating); - return this; - } - - /** - * Sets the number of songs number input field - * - * @param numberOfSongs the new number of songs value to be set - * @return {@link AlbumPage} - */ - public AlbumPage changeNumberOfSongs(int numberOfSongs) { - HtmlNumberInput numberOfSongsNumberField = (HtmlNumberInput) page.getElementById("numberOfSongs"); - numberOfSongsNumberField.setText(Integer.toString(numberOfSongs)); - return this; - } - - - /** - * Cancel changes made by clicking the cancel button - * - * @return {@link AlbumListPage} - */ - public AlbumListPage cancelChanges() { - HtmlSubmitInput cancelButton = (HtmlSubmitInput) page.getElementById("cancelButton"); - try { - cancelButton.click(); - } catch (IOException e) { - e.printStackTrace(); - } - return new AlbumListPage(webClient); - } - - - /** - * Saves changes made by clicking the save button - * - * @return {@link AlbumPage} - */ - public AlbumPage saveChanges() { - HtmlSubmitInput saveButton = (HtmlSubmitInput) page.getElementById("saveButton"); - try { - saveButton.click(); - } catch (IOException e) { - e.printStackTrace(); - } - return this; - } - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/pages/LoginPage.java b/page-object/src/test/java/com/iluwatar/pageobject/pages/LoginPage.java deleted file mode 100644 index b648dfdafc36..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/pages/LoginPage.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject.pages; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput; -import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; -import com.gargoylesoftware.htmlunit.html.HtmlTextInput; -import java.io.IOException; - -/** - * Page Object encapsulating the Login Page (login.html) - */ -public class LoginPage extends Page { - - private static final String LOGIN_PAGE_HTML_FILE = "login.html"; - private static final String PAGE_URL = "file:" + AUT_PATH + LOGIN_PAGE_HTML_FILE; - - private HtmlPage page; - - /** - * Constructor - * - * @param webClient {@link WebClient} - */ - public LoginPage(WebClient webClient) { - super(webClient); - } - - /** - * Navigates to the Login page - * - * @return {@link LoginPage} - */ - public LoginPage navigateToPage() { - try { - page = this.webClient.getPage(PAGE_URL); - } catch (IOException e) { - e.printStackTrace(); - } - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAt() { - return "Login".equals(page.getTitleText()); - } - - - /** - * Enters the username into the username input text field - * - * @param username the username to enter - * @return {@link LoginPage} - */ - public LoginPage enterUsername(String username) { - HtmlTextInput usernameInputTextField = (HtmlTextInput) page.getElementById("username"); - usernameInputTextField.setText(username); - return this; - } - - - /** - * Enters the password into the password input password field - * - * @param password the password to enter - * @return {@link LoginPage} - */ - public LoginPage enterPassword(String password) { - HtmlPasswordInput passwordInputPasswordField = (HtmlPasswordInput) page.getElementById("password"); - passwordInputPasswordField.setText(password); - return this; - } - - - /** - * Clicking on the login button to 'login' - * - * @return {@link AlbumListPage} - * - this is the page that user gets navigated to once successfully logged in - */ - public AlbumListPage login() { - HtmlSubmitInput loginButton = (HtmlSubmitInput) page.getElementById("loginButton"); - try { - loginButton.click(); - } catch (IOException e) { - e.printStackTrace(); - } - return new AlbumListPage(webClient); - } - -} diff --git a/page-object/src/test/java/com/iluwatar/pageobject/pages/Page.java b/page-object/src/test/java/com/iluwatar/pageobject/pages/Page.java deleted file mode 100644 index f292588d2951..000000000000 --- a/page-object/src/test/java/com/iluwatar/pageobject/pages/Page.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - *

    - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

    - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

    - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.pageobject.pages; - -import com.gargoylesoftware.htmlunit.WebClient; - -/** - * Encapsulation for a generic 'Page' - */ -public abstract class Page { - - /** - * Application Under Test path - * This directory location is where html web pages are located - */ - public static final String AUT_PATH = "src/main/resources/sample-ui/"; - - protected final WebClient webClient; - - /** - * Constructor - * - * @param webClient {@link WebClient} - */ - public Page(WebClient webClient) { - this.webClient = webClient; - } - - /** - * Checks that the current page is actually the page this page object represents - * - * @return true if so, otherwise false - */ - public abstract boolean isAt(); - - -} diff --git a/partial-response/README.md b/partial-response/README.md deleted file mode 100644 index 5d03cb359fb2..000000000000 --- a/partial-response/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: Partial Response -folder: partial-response -permalink: /patterns/partial-response/ -categories: Architectural -tags: - - Java - - KISS - - YAGNI - - Difficulty-Beginner ---- - -## Intent -Send partial response from server to client on need basis. Client will specify the the fields -that it need to server, instead of serving all details for resource. - -![alt text](./etc/partial-response.urm.png "partial-response") - -## Applicability -Use the Partial Response pattern when - -* Client need only subset of data from resource. -* To avoid too much data transfer over wire - -## Credits - -* [Common Design Patterns](https://cloud.google.com/apis/design/design_patterns) -* [Partial Response in RESTful API Design](http://yaoganglian.com/2013/07/01/partial-response/) diff --git a/partial-response/etc/partial-response.ucls b/partial-response/etc/partial-response.ucls deleted file mode 100644 index a0b029496352..000000000000 --- a/partial-response/etc/partial-response.ucls +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/partial-response/etc/partial-response.urm.png b/partial-response/etc/partial-response.urm.png deleted file mode 100644 index 17dbd5f1b60df743f40c23a87deb70bc8d952806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27781 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 jzk`|ok%ip - + VideoResource(fieldJsonMapper : FieldJsonMapper, videos : Map) - + getDetails(id : Integer, fields : String[]) : String - } -} -VideoResource --> "-fieldJsonMapper" FieldJsonMapper -@enduml \ No newline at end of file diff --git a/partial-response/pom.xml b/partial-response/pom.xml deleted file mode 100644 index 94c583a9866b..000000000000 --- a/partial-response/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - partial-response - - - junit - junit - - - org.mockito - mockito-core - - - - - \ No newline at end of file diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/App.java b/partial-response/src/main/java/com/iluwatar/partialresponse/App.java deleted file mode 100644 index 2977b50a71d1..000000000000 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/App.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * The Partial response pattern is a design pattern in which client specifies fields to fetch to serve. - * Here {@link App} is playing as client for {@link VideoResource} server. - * Client ask for specific fields information in video to server. - *

    - *

    - * {@link VideoResource} act as server to serve video information. - */ - -public class App { - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Method as act client and request to server for video details. - * - * @param args program argument. - */ - public static void main(String[] args) throws Exception { - Map videos = new HashMap<>(); - videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); - videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); - videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); - VideoResource videoResource = new VideoResource(new FieldJsonMapper(), videos); - - - LOGGER.info("Retrieving full response from server:-"); - LOGGER.info("Get all video information:"); - String videoDetails = videoResource.getDetails(1); - LOGGER.info(videoDetails); - - LOGGER.info("----------------------------------------------------------"); - - LOGGER.info("Retrieving partial response from server:-"); - LOGGER.info("Get video @id, @title, @director:"); - String specificFieldsDetails = videoResource.getDetails(3, "id", "title", "director"); - LOGGER.info(specificFieldsDetails); - - LOGGER.info("Get video @id, @length:"); - String videoLength = videoResource.getDetails(3, "id", "length"); - LOGGER.info(videoLength); - } -} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java b/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java deleted file mode 100644 index 9283cfa698f0..000000000000 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import java.lang.reflect.Field; - -/** - * Map a video to json - */ -public class FieldJsonMapper { - - /** - * @param video object containing video information - * @param fields fields information to get - * @return json of required fields from video - */ - public String toJson(Video video, String[] fields) throws Exception { - StringBuilder json = new StringBuilder().append("{"); - - for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) { - json.append(getString(video, Video.class.getDeclaredField(fields[i]))); - if (i != fieldsLength - 1) { - json.append(","); - } - } - json.append("}"); - return json.toString(); - } - - private String getString(Video video, Field declaredField) throws IllegalAccessException { - declaredField.setAccessible(true); - Object value = declaredField.get(video); - if (declaredField.get(video) instanceof Integer) { - return "\"" + declaredField.getName() + "\"" + ": " + value; - } - return "\"" + declaredField.getName() + "\"" + ": " + "\"" + value.toString() + "\""; - } -} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java deleted file mode 100644 index e242965e3660..000000000000 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -/** - * {@link Video} is a entity to serve from server.It contains all video related information.. - *

    - */ -public class Video { - private final Integer id; - private final String title; - private final Integer length; - private final String description; - private final String director; - private final String language; - - /** - * @param id video unique id - * @param title video title - * @param length video length in minutes - * @param description video description by publisher - * @param director video director name - * @param language video language {private, public} - */ - public Video(Integer id, String title, Integer length, String description, String director, String language) { - this.id = id; - this.title = title; - this.length = length; - this.description = description; - this.director = director; - this.language = language; - } - - /** - * @return json representaion of video - */ - @Override - public String toString() { - return "{" - + "\"id\": " + id + "," - + "\"title\": \"" + title + "\"," - + "\"length\": " + length + "," - + "\"description\": \"" + description + "\"," - + "\"director\": \"" + director + "\"," - + "\"language\": \"" + language + "\"," - + "}"; - } -} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java b/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java deleted file mode 100644 index 2bf7a73c1f1b..000000000000 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import java.util.Map; - -/** - * The resource class which serves video information. - * This class act as server in the demo. Which has all video details. - */ -public class VideoResource { - private FieldJsonMapper fieldJsonMapper; - private Map videos; - - /** - * @param fieldJsonMapper map object to json. - * @param videos initialize resource with existing videos. Act as database. - */ - public VideoResource(FieldJsonMapper fieldJsonMapper, Map videos) { - this.fieldJsonMapper = fieldJsonMapper; - this.videos = videos; - } - - /** - * @param id video id - * @param fields fields to get information about - * @return full response if no fields specified else partial response for given field. - */ - public String getDetails(Integer id, String... fields) throws Exception { - if (fields.length == 0) { - return videos.get(id).toString(); - } - return fieldJsonMapper.toJson(videos.get(id), fields); - } -} diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java deleted file mode 100644 index 2ac34dd0d0a3..000000000000 --- a/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void main() throws Exception { - String[] args = {}; - App.main(args); - } - -} \ No newline at end of file diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java deleted file mode 100644 index 9bc078b571c9..000000000000 --- a/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * tests {@link FieldJsonMapper}. - */ -public class FieldJsonMapperTest { - private FieldJsonMapper mapper; - - @Before - public void setUp() { - mapper = new FieldJsonMapper(); - } - - @Test - public void shouldReturnJsonForSpecifiedFieldsInVideo() throws Exception { - String[] fields = new String[]{"id", "title", "length"}; - Video video = new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese"); - - String jsonFieldResponse = mapper.toJson(video, fields); - - String expectedDetails = "{\"id\": 2,\"title\": \"Godzilla Resurgence\",\"length\": 120}"; - assertEquals(expectedDetails, jsonFieldResponse); - } -} \ No newline at end of file diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java deleted file mode 100644 index 0453e8ffdf66..000000000000 --- a/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2017 Gopinath Langote - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.iluwatar.partialresponse; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - -/** - * tests {@link VideoResource}. - */ -@RunWith(MockitoJUnitRunner.class) -public class VideoResourceTest { - @Mock - private FieldJsonMapper fieldJsonMapper; - - private VideoResource resource; - - @Before - public void setUp() { - Map videos = new HashMap<>(); - videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); - videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); - videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); - resource = new VideoResource(fieldJsonMapper, videos); - } - - @Test - public void shouldGiveVideoDetailsById() throws Exception { - String actualDetails = resource.getDetails(1); - - String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178,\"description\": " - + "\"epic science fiction film\",\"director\": \"James Cameron\",\"language\": \"English\",}"; - assertEquals(expectedDetails, actualDetails); - } - - @Test - public void shouldGiveSpecifiedFieldsInformationOfVideo() throws Exception { - String[] fields = new String[]{"id", "title", "length"}; - - String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178}"; - when(fieldJsonMapper.toJson(any(Video.class), eq(fields))).thenReturn(expectedDetails); - - String actualFieldsDetails = resource.getDetails(2, fields); - - assertEquals(expectedDetails, actualFieldsDetails); - } -} \ No newline at end of file diff --git a/poison-pill/README.md b/poison-pill/README.md deleted file mode 100644 index 8f673ad49cf4..000000000000 --- a/poison-pill/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Poison Pill -folder: poison-pill -permalink: /patterns/poison-pill/ -pumlid: JSZ14SCm20NHLf82BExfXiYCJGOX3NpYzkDZRllsgTwjTgcmnmciV145N-rGdFMkbEZJ8OxMvo2rkXWSzE4lRxka7huj1YGyQN3UGMjgpdkh6Gdwlrl5QAk6_G00 -categories: Other -tags: - - Java - - Difficulty-Intermediate - - Reactive ---- - -## Intent -Poison Pill is known predefined data item that allows to provide -graceful shutdown for separate distributed consumption process. - -![alt text](./etc/poison-pill.png "Poison Pill") - -## Applicability -Use the Poison Pill idiom when - -* need to send signal from one thread/process to another to terminate - -## Real world examples - -* [akka.actor.PoisonPill](http://doc.akka.io/docs/akka/2.1.4/java/untyped-actors.html) diff --git a/poison-pill/etc/poison-pill.png b/poison-pill/etc/poison-pill.png deleted file mode 100644 index bfca5848e082c8fc69e6e7f4d5aa38af13ab27dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15833 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 Szj%*bpdhCzTP*YR)&B>iXFe1F diff --git a/poison-pill/etc/poison-pill.ucls b/poison-pill/etc/poison-pill.ucls deleted file mode 100644 index 6d20b1974dfc..000000000000 --- a/poison-pill/etc/poison-pill.ucls +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/poison-pill/etc/poison-pill.urm.puml b/poison-pill/etc/poison-pill.urm.puml deleted file mode 100644 index 5c2b9fa2be31..000000000000 --- a/poison-pill/etc/poison-pill.urm.puml +++ /dev/null @@ -1,71 +0,0 @@ -@startuml -package com.iluwatar.poison.pill { - class App { - + App() - + main(args : String[]) {static} - } - class Consumer { - - LOGGER : Logger {static} - - name : String - - queue : MqSubscribePoint - + Consumer(name : String, queue : MqSubscribePoint) - + consume() - } - interface Message { - + POISON_PILL : Message {static} - + addHeader(Headers, String) {abstract} - + getBody() : String {abstract} - + getHeader(Headers) : String {abstract} - + getHeaders() : Map {abstract} - + setBody(String) {abstract} - } - enum Headers { - + DATE {static} - + SENDER {static} - + valueOf(name : String) : Headers {static} - + values() : Headers[] {static} - } - interface MessageQueue { - } - interface MqPublishPoint { - + put(Message) {abstract} - } - interface MqSubscribePoint { - + take() : Message {abstract} - } - class Producer { - - LOGGER : Logger {static} - - isStopped : boolean - - name : String - - queue : MqPublishPoint - + Producer(name : String, queue : MqPublishPoint) - + send(body : String) - + stop() - } - class SimpleMessage { - - body : String - - headers : Map - + SimpleMessage() - + addHeader(header : Headers, value : String) - + getBody() : String - + getHeader(header : Headers) : String - + getHeaders() : Map - + setBody(body : String) - } - class SimpleMessageQueue { - - queue : BlockingQueue - + SimpleMessageQueue(bound : int) - + put(msg : Message) - + take() : Message - } -} -SimpleMessageQueue --> "-queue" Message -Consumer --> "-queue" MqSubscribePoint -Headers ..+ Message -Producer --> "-queue" MqPublishPoint -Message --> "-POISON_PILL" Message -MessageQueue --|> MqPublishPoint -MessageQueue --|> MqSubscribePoint -SimpleMessage ..|> Message -SimpleMessageQueue ..|> MessageQueue -@enduml \ No newline at end of file diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml deleted file mode 100644 index 3bd0f09670db..000000000000 --- a/poison-pill/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - poison-pill - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java deleted file mode 100644 index c24f503ddbeb..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -/** - * One of the possible approaches to terminate Producer-Consumer pattern is using the Poison Pill - * idiom. If you use Poison Pill as the termination signal then Producer is responsible to notify - * Consumer that the exchange is over and reject any further messages. The Consumer receiving Poison - * Pill will stop reading messages from the queue. You must also ensure that the Poison Pill will be - * the last message that will be read from the queue (if you have prioritized queue then this can be - * tricky). - *

    - * In simple cases the Poison Pill can be just a null-reference, but holding a unique separate - * shared object-marker (with name "Poison" or "Poison Pill") is more clear and self describing. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - MessageQueue queue = new SimpleMessageQueue(10000); - - final Producer producer = new Producer("PRODUCER_1", queue); - final Consumer consumer = new Consumer("CONSUMER_1", queue); - - new Thread() { - @Override - public void run() { - consumer.consume(); - } - }.start(); - - new Thread() { - @Override - public void run() { - producer.send("hand shake"); - producer.send("some very important information"); - producer.send("bye!"); - producer.stop(); - } - }.start(); - } -} 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 deleted file mode 100644 index 049a9cbb27a0..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - - public Consumer(String name, MqSubscribePoint queue) { - this.name = name; - this.queue = queue; - } - - /** - * Consume message - */ - public void consume() { - while (true) { - Message msg; - try { - msg = queue.take(); - if (Message.POISON_PILL.equals(msg)) { - LOGGER.info("Consumer {} receive request to terminate.", name); - break; - } - } catch (InterruptedException e) { - // allow thread to exit - LOGGER.error("Exception caught.", e); - return; - } - - String sender = msg.getHeader(Headers.SENDER); - String body = msg.getBody(); - LOGGER.info("Message [{}] from [{}] received by [{}]", body, sender, name); - } - } -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java deleted file mode 100644 index cd2d2da6ac90..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import java.util.Map; - -/** - * Interface that implements the Message pattern and represents an inbound or outbound message as - * part of an {@link Producer}-{@link Consumer} exchange. - */ -public interface Message { - - Message POISON_PILL = new Message() { - - @Override - public void addHeader(Headers header, String value) { - throw poison(); - } - - @Override - public String getHeader(Headers header) { - throw poison(); - } - - @Override - public Map getHeaders() { - throw poison(); - } - - @Override - public void setBody(String body) { - throw poison(); - } - - @Override - public String getBody() { - throw poison(); - } - - private RuntimeException poison() { - return new UnsupportedOperationException("Poison"); - } - - }; - - /** - * Enumeration of Type of Headers - */ - public enum Headers { - DATE, SENDER - } - - void addHeader(Headers header, String value); - - String getHeader(Headers header); - - Map getHeaders(); - - void setBody(String body); - - String getBody(); -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java deleted file mode 100644 index b12b201e4cc7..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -/** - * Represents abstraction of channel (or pipe) that bounds {@link Producer} and {@link Consumer} - */ -public interface MessageQueue extends MqPublishPoint, MqSubscribePoint { - -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java deleted file mode 100644 index a37904824e1f..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -/** - * Endpoint to publish {@link Message} to queue - */ -public interface MqPublishPoint { - - void put(Message msg) throws InterruptedException; -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java deleted file mode 100644 index 7e3974a1a399..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -/** - * Endpoint to retrieve {@link Message} from queue - */ -public interface MqSubscribePoint { - - Message take() throws InterruptedException; -} 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 deleted file mode 100644 index 884292bd28f4..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import java.util.Date; - -import com.iluwatar.poison.pill.Message.Headers; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class responsible for producing unit of work that can be expressed as message and submitted to - * queue - */ -public class Producer { - - private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class); - - private final MqPublishPoint queue; - private final String name; - private boolean isStopped; - - /** - * Constructor - */ - public Producer(String name, MqPublishPoint queue) { - this.name = name; - this.queue = queue; - this.isStopped = false; - } - - /** - * Send message to queue - */ - public void send(String body) { - if (isStopped) { - throw new IllegalStateException(String.format( - "Producer %s was stopped and fail to deliver requested message [%s].", body, name)); - } - Message msg = new SimpleMessage(); - msg.addHeader(Headers.DATE, new Date().toString()); - msg.addHeader(Headers.SENDER, name); - msg.setBody(body); - - try { - queue.put(msg); - } catch (InterruptedException e) { - // allow thread to exit - LOGGER.error("Exception caught.", e); - } - } - - /** - * Stop system by sending poison pill - */ - public void stop() { - isStopped = true; - try { - queue.put(Message.POISON_PILL); - } catch (InterruptedException e) { - // allow thread to exit - LOGGER.error("Exception caught.", e); - } - } -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java deleted file mode 100644 index 4e665b44f0d2..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * {@link Message} basic implementation - */ -public class SimpleMessage implements Message { - - private Map headers = new HashMap<>(); - private String body; - - @Override - public void addHeader(Headers header, String value) { - headers.put(header, value); - } - - @Override - public String getHeader(Headers header) { - return headers.get(header); - } - - @Override - public Map getHeaders() { - return Collections.unmodifiableMap(headers); - } - - @Override - public void setBody(String body) { - this.body = body; - } - - @Override - public String getBody() { - return body; - } -} diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java deleted file mode 100644 index ac961e706f59..000000000000 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -/** - * Bounded blocking queue wrapper - */ -public class SimpleMessageQueue implements MessageQueue { - - private final BlockingQueue queue; - - public SimpleMessageQueue(int bound) { - queue = new ArrayBlockingQueue<>(bound); - } - - @Override - public void put(Message msg) throws InterruptedException { - queue.put(msg); - } - - @Override - public Message take() throws InterruptedException { - return queue.take(); - } -} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/AppTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/AppTest.java deleted file mode 100644 index 8c15bcf0fccb..000000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index 17bd4f89e819..000000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.slf4j.LoggerFactory; - -import java.time.LocalDateTime; -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/27/15 - 9:45 PM - * - * @author Jeroen Meulemeester - */ -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 { - final Message[] messages = new Message[]{ - createMessage("you", "Hello!"), - createMessage("me", "Hi!"), - Message.POISON_PILL, - createMessage("late_for_the_party", "Hello? Anyone here?"), - }; - - final MessageQueue queue = new SimpleMessageQueue(messages.length); - for (final Message message : messages) { - queue.put(message); - } - - new Consumer("NSA", queue).consume(); - - 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.")); - } - - /** - * Create a new message from the given sender with the given message body - * - * @param sender The sender's name - * @param message The message body - * @return The message instance - */ - private static Message createMessage(final String sender, final String message) { - final SimpleMessage msg = new SimpleMessage(); - msg.addHeader(Message.Headers.SENDER, sender); - msg.addHeader(Message.Headers.DATE, LocalDateTime.now().toString()); - msg.setBody(message); - return msg; - } - - 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/PoisonMessageTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java deleted file mode 100644 index b1500569563c..000000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import org.junit.Test; - -import static com.iluwatar.poison.pill.Message.Headers; -import static com.iluwatar.poison.pill.Message.POISON_PILL; - -/** - * Date: 12/27/15 - 10:30 PM - * - * @author Jeroen Meulemeester - */ -public class PoisonMessageTest { - - @Test(expected = UnsupportedOperationException.class) - public void testAddHeader() throws Exception { - POISON_PILL.addHeader(Headers.SENDER, "sender"); - } - - @Test(expected = UnsupportedOperationException.class) - public void testGetHeader() throws Exception { - POISON_PILL.getHeader(Headers.SENDER); - } - - @Test(expected = UnsupportedOperationException.class) - public void testGetHeaders() throws Exception { - POISON_PILL.getHeaders(); - } - - @Test(expected = UnsupportedOperationException.class) - public void testSetBody() throws Exception { - POISON_PILL.setBody("Test message."); - } - - @Test(expected = UnsupportedOperationException.class) - public void testGetBody() throws Exception { - POISON_PILL.getBody(); - } - -} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java deleted file mode 100644 index 7b5982a3d849..000000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -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.Mockito.verifyZeroInteractions; - -/** - * Date: 12/27/15 - 10:32 PM - * - * @author Jeroen Meulemeester - */ -public class ProducerTest { - - @Test - public void testSend() throws Exception { - final MqPublishPoint publishPoint = mock(MqPublishPoint.class); - final Producer producer = new Producer("producer", publishPoint); - verifyZeroInteractions(publishPoint); - - producer.send("Hello!"); - - final ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); - verify(publishPoint).put(messageCaptor.capture()); - - final Message message = messageCaptor.getValue(); - assertNotNull(message); - assertEquals("producer", message.getHeader(Message.Headers.SENDER)); - assertNotNull(message.getHeader(Message.Headers.DATE)); - assertEquals("Hello!", message.getBody()); - - verifyNoMoreInteractions(publishPoint); - } - - @Test - public void testStop() throws Exception { - final MqPublishPoint publishPoint = mock(MqPublishPoint.class); - final Producer producer = new Producer("producer", publishPoint); - verifyZeroInteractions(publishPoint); - - producer.stop(); - verify(publishPoint).put(eq(Message.POISON_PILL)); - - try { - producer.send("Hello!"); - fail("Expected 'IllegalStateException' at this point, since the producer has stopped!"); - } catch (IllegalStateException e) { - assertNotNull(e); - assertNotNull(e.getMessage()); - assertEquals("Producer Hello! was stopped and fail to deliver requested message [producer].", - e.getMessage()); - } - - verifyNoMoreInteractions(publishPoint); - } - -} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java deleted file mode 100644 index 2b0b3bd172c6..000000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.poison.pill; - -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/27/15 - 10:25 PM - * - * @author Jeroen Meulemeester - */ -public class SimpleMessageTest { - - @Test - public void testGetHeaders() { - final SimpleMessage message = new SimpleMessage(); - assertNotNull(message.getHeaders()); - assertTrue(message.getHeaders().isEmpty()); - - final String senderName = "test"; - message.addHeader(Message.Headers.SENDER, senderName); - assertNotNull(message.getHeaders()); - assertFalse(message.getHeaders().isEmpty()); - assertEquals(senderName, message.getHeaders().get(Message.Headers.SENDER)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testUnModifiableHeaders() { - final SimpleMessage message = new SimpleMessage(); - final Map headers = message.getHeaders(); - headers.put(Message.Headers.SENDER, "test"); - } - - -} \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 0c03909de269..000000000000 --- a/pom.xml +++ /dev/null @@ -1,497 +0,0 @@ - - - 4.0.0 - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - pom - 2014 - - UTF-8 - 5.0.1.Final - 4.2.4.RELEASE - 1.3.3.RELEASE - 1.9.2.RELEASE - 1.4.190 - 4.12 - 3.0 - 0.7.2.201409121644 - 1.4 - 2.16.1 - 19.0 - 1.15.1 - 1.10.19 - 4.12.1 - 4.5.2 - 2.22 - 1.4.4 - 4.0 - 3.3.0 - 1.7.21 - 1.1.7 - - - abstract-factory - tls - builder - factory-method - prototype - singleton - adapter - bridge - composite - dao - data-mapper - decorator - facade - flyweight - proxy - chain - command - interpreter - iterator - mediator - memento - model-view-presenter - observer - state - strategy - template-method - visitor - double-checked-locking - servant - service-locator - null-object - event-aggregator - callback - execute-around - property - intercepting-filter - producer-consumer - poison-pill - reader-writer-lock - lazy-loading - service-layer - specification - tolerant-reader - model-view-controller - flux - double-dispatch - multiton - resource-acquisition-is-initialization - thread-pool - twin - private-class-data - object-pool - dependency-injection - naked-objects - front-controller - repository - async-method-invocation - monostate - step-builder - business-delegate - half-sync-half-async - layers - message-channel - fluentinterface - reactor - caching - publish-subscribe - delegation - event-driven-architecture - api-gateway - factory-kit - feature-toggle - value-object - module - monad - mute-idiom - mutex - semaphore - hexagonal - abstract-document - aggregator-microservices - promise - page-object - event-asynchronous - event-queue - queue-load-leveling - object-mother - data-bus - converter - guarded-suspension - balking - extension-objects - marker - cqrs - event-sourcing - data-transfer-object - throttling - partial-response - eip-wire-tap - eip-splitter - - - - - - org.hibernate - hibernate-core - ${hibernate.version} - - - org.hibernate - hibernate-entitymanager - ${hibernate.version} - - - org.springframework - spring-test - ${spring.version} - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - org.springframework.data - spring-data-jpa - ${spring-data.version} - - - org.springframework - spring-webmvc - ${spring.version} - - - org.springframework.boot - spring-boot-starter-web - ${spring-boot.version} - - - org.apache.httpcomponents - httpclient - ${apache-httpcomponents.version} - - - com.h2database - h2 - ${h2.version} - - - commons-dbcp - commons-dbcp - ${commons-dbcp.version} - - - org.apache.camel - camel-core - ${camel.version} - - - org.apache.camel - camel-stream - ${camel.version} - - - junit - junit - ${junit.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - com.google.guava - guava - ${guava.version} - - - com.github.stefanbirkner - system-rules - ${systemrules.version} - test - - - de.bechte.junit - junit-hierarchicalcontextrunner - ${hierarchical-junit-runner-version} - test - - - net.sourceforge.htmlunit - htmlunit - ${htmlunit.version} - test - - - com.google.inject - guice - ${guice.version} - - - org.mongodb - mongo-java-driver - ${mongo-java-driver.version} - - - - - - - org.slf4j - slf4j-api - ${slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.jacoco - - jacoco-maven-plugin - - - [0.6.2,) - - - prepare-agent - - - - - - - - - - com.github.markusmo3.urm - - - urm-maven-plugin - - - [1.4.1,) - - - map - - - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${compiler.version} - - 1.8 - 1.8 - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - prepare-agent - - prepare-agent - - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.17 - - - validate - - check - - validate - - checkstyle.xml - checkstyle-suppressions.xml - UTF-8 - true - true - true - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.18.1 - - - org.apache.maven.surefire - surefire-junit47 - 2.18.1 - - - - -Xmx1024M ${argLine} - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.6 - - true - 5 - true - - - - - check - - - exclude-pmd.properties - - - - - - - com.mycila - license-maven-plugin - 2.11 - -

    com/mycila/maven/plugin/license/templates/MIT.txt
    - - Ilkka Seppälä - - true - - - - install-format - install - - format - - - - - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - - process-classes - - map - - - - - ${project.basedir}/etc - - com.iluwatar - - - - java-design-patterns - singleton - factory-method - abstract-factory - builder - prototype - adapter - bridge - composite - decorator - facade - flyweight - proxy - chain - - - - - - - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.6 - - - - - \ No newline at end of file diff --git a/private-class-data/README.md b/private-class-data/README.md deleted file mode 100644 index 061cc9e7713a..000000000000 --- a/private-class-data/README.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: pattern -title: Private Class Data -folder: private-class-data -permalink: /patterns/private-class-data/ -pumlid: RShR3SCm243HLTe1RFwx3S4eeSB4uf6itmpGlwkZ-nOZhS7b-ZeoLtm07E--InwrLR3JQScMdSu9edLZeiCNBso3GtPh2pFPBM1YF07BvSBaHeeHRJm_SD8VxkMphvhw0m00 -categories: Other -tags: - - Java - - Difficulty-Beginner - - Idiom ---- - -## Intent -Private Class Data design pattern seeks to reduce exposure of -attributes by limiting their visibility. It reduces the number of class -attributes by encapsulating them in single Data object. - -![alt text](./etc/private-class-data.png "Private Class Data") - -## Applicability -Use the Private Class Data pattern when - -* you want to prevent write access to class data members diff --git a/private-class-data/etc/private-class-data.png b/private-class-data/etc/private-class-data.png deleted file mode 100644 index 65c343a5faf910a047a495a3ba76cffcbaaf03cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10791 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/private-class-data/etc/private-class-data.urm.puml b/private-class-data/etc/private-class-data.urm.puml deleted file mode 100644 index 990b53342521..000000000000 --- a/private-class-data/etc/private-class-data.urm.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml -package com.iluwatar.privateclassdata { - class App { - + App() - + main(args : String[]) {static} - } - class ImmutableStew { - - LOGGER : Logger {static} - - data : StewData - + ImmutableStew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + mix() - } - class Stew { - - LOGGER : Logger {static} - - numCarrots : int - - numMeat : int - - numPeppers : int - - numPotatoes : int - + Stew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + mix() - + taste() - } - class StewData { - - numCarrots : int - - numMeat : int - - numPeppers : int - - numPotatoes : int - + StewData(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + getNumCarrots() : int - + getNumMeat() : int - + getNumPeppers() : int - + getNumPotatoes() : int - } -} -ImmutableStew --> "-data" StewData -@enduml \ No newline at end of file diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml deleted file mode 100644 index 3ac0cf53220d..000000000000 --- a/private-class-data/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - private-class-data - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java deleted file mode 100644 index 37ad524c836f..000000000000 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -/** - * - * The Private Class Data design pattern seeks to reduce exposure of attributes by limiting their - * visibility. It reduces the number of class attributes by encapsulating them in single data - * object. It allows the class designer to remove write privilege of attributes that are intended to - * be set only during construction, even from methods of the target class. - *

    - * In the example we have normal {@link Stew} class with some ingredients given in constructor. Then - * we have methods to enumerate the ingredients and to taste the stew. The method for tasting the - * stew alters the private members of the {@link Stew} class. - * - * The problem is solved with the Private Class Data pattern. We introduce {@link ImmutableStew} - * class that contains {@link StewData}. The private data members of {@link Stew} are now in - * {@link StewData} and cannot be altered by {@link ImmutableStew} methods. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - // stew is mutable - Stew stew = new Stew(1, 2, 3, 4); - stew.mix(); - stew.taste(); - stew.mix(); - - // immutable stew protected with Private Class Data pattern - ImmutableStew immutableStew = new ImmutableStew(2, 4, 3, 6); - immutableStew.mix(); - } -} 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 deleted file mode 100644 index 3ad4ee351dc0..000000000000 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Immutable stew class, protected with Private Class Data pattern - * - */ -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) { - data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers); - } - - /** - * Mix the stew - */ - public void mix() { - LOGGER.info("Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers", - data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers()); - } -} 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 deleted file mode 100644 index b08a409c4888..000000000000 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Mutable stew class - * - */ -public class Stew { - - private static final Logger LOGGER = LoggerFactory.getLogger(Stew.class); - - private int numPotatoes; - private int numCarrots; - private int numMeat; - private int numPeppers; - - /** - * Constructor - */ - public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { - this.numPotatoes = numPotatoes; - this.numCarrots = numCarrots; - this.numMeat = numMeat; - this.numPeppers = numPeppers; - } - - /** - * Mix the stew - */ - public void mix() { - LOGGER.info("Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers", - numPotatoes, numCarrots, numMeat, numPeppers); - } - - /** - * Taste the stew - */ - public void taste() { - LOGGER.info("Tasting the stew"); - if (numPotatoes > 0) { - numPotatoes--; - } - if (numCarrots > 0) { - numCarrots--; - } - if (numMeat > 0) { - numMeat--; - } - if (numPeppers > 0) { - numPeppers--; - } - } -} diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java deleted file mode 100644 index 636d3a36c3df..000000000000 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -/** - * - * Stew ingredients - * - */ -public class StewData { - - private int numPotatoes; - private int numCarrots; - private int numMeat; - private int numPeppers; - - /** - * Constructor - */ - public StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { - this.numPotatoes = numPotatoes; - this.numCarrots = numCarrots; - this.numMeat = numMeat; - this.numPeppers = numPeppers; - } - - public int getNumPotatoes() { - return numPotatoes; - } - - public int getNumCarrots() { - return numCarrots; - } - - public int getNumMeat() { - return numMeat; - } - - public int getNumPeppers() { - return numPeppers; - } -} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/AppTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/AppTest.java deleted file mode 100644 index ef80e87cb6bb..000000000000 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index 6e337e5840af..000000000000 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -import com.iluwatar.privateclassdata.utils.InMemoryAppender; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/27/15 - 10:46 PM - * - * @author Jeroen Meulemeester - */ -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 - */ - @Test - public void testMix() { - final Stew stew = new Stew(1, 2, 3, 4); - final String expectedMessage = "Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"; - - for (int i = 0; i < 20; i++) { - stew.mix(); - assertEquals(expectedMessage, appender.getLastMessage()); - } - - assertEquals(20, appender.getLogSize()); - } - - /** - * Verify if tasting the stew actually removes one of each ingredient - */ - @Test - public void testDrink() { - final Stew stew = new Stew(1, 2, 3, 4); - stew.mix(); - - assertEquals("Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers", appender.getLastMessage()); - - stew.taste(); - assertEquals("Tasting the stew", appender.getLastMessage()); - - stew.mix(); - assertEquals("Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers", appender.getLastMessage()); - } -} 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 deleted file mode 100644 index 6ac5b834f705..000000000000 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.privateclassdata; - -import com.iluwatar.privateclassdata.utils.InMemoryAppender; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/27/15 - 10:46 PM - * - * @author Jeroen Meulemeester - */ -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 - */ - @Test - public void testMix() { - final ImmutableStew stew = new ImmutableStew(1, 2, 3, 4); - final String expectedMessage = "Mixing the immutable stew we find: 1 potatoes, " - + "2 carrots, 3 meat and 4 peppers"; - - for (int i = 0; i < 20; i++) { - stew.mix(); - assertEquals(expectedMessage, appender.getLastMessage()); - } - - assertEquals(20, appender.getLogSize()); - } - -} 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 deleted file mode 100644 index bea71ab152c5..000000000000 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * InMemory Log Appender Util. - */ -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/README.md b/producer-consumer/README.md deleted file mode 100644 index b3cb56af12aa..000000000000 --- a/producer-consumer/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Producer Consumer -folder: producer-consumer -permalink: /patterns/producer-consumer/ -pumlid: PSjB3iCW303HgxG70Ezx6zTO2HKso9_a-c7VtUX9y-vA8nkdZTSPiVm3O7ZNeyUPttGscXgiKMaAz94t1XhyyCBIsFkXPM44cpe8-WvODbiIMzcdfspXe7-jQL9NodW0 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate - - I/O - - Reactive ---- - -## Intent -Producer Consumer Design pattern is a classic concurrency pattern which reduces - coupling between Producer and Consumer by separating Identification of work with Execution of - Work. - -![alt text](./etc/producer-consumer.png "Producer Consumer") - -## Applicability -Use the Producer Consumer idiom when - -* decouple system by separate work in two process produce and consume. -* addresses the issue of different timing require to produce work or consuming work diff --git a/producer-consumer/etc/producer-consumer.png b/producer-consumer/etc/producer-consumer.png deleted file mode 100644 index e8bc573b388fe73e5a88d0f690d5c22cbbe8f700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27122 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 Ux~Sk@72)4ykP6o_CGU9rA6j$#g8%>k diff --git a/producer-consumer/etc/producer-consumer.ucls b/producer-consumer/etc/producer-consumer.ucls deleted file mode 100644 index aa1ee80c05d7..000000000000 --- a/producer-consumer/etc/producer-consumer.ucls +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/producer-consumer/etc/producer-consumer.urm.puml b/producer-consumer/etc/producer-consumer.urm.puml deleted file mode 100644 index 05539a55ea42..000000000000 --- a/producer-consumer/etc/producer-consumer.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.producer.consumer { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Consumer { - - LOGGER : Logger {static} - - name : String - - queue : ItemQueue - + Consumer(name : String, queue : ItemQueue) - + consume() - } - class Item { - - id : int - - producer : String - + Item(producer : String, id : int) - + getId() : int - + getProducer() : String - } - class ItemQueue { - - queue : BlockingQueue - + ItemQueue() - + put(item : Item) - + take() : Item - } - class Producer { - - itemId : int - - name : String - - queue : ItemQueue - + Producer(name : String, queue : ItemQueue) - + produce() - } -} -Consumer --> "-queue" ItemQueue -Producer --> "-queue" ItemQueue -ItemQueue --> "-queue" Item -@enduml \ No newline at end of file diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml deleted file mode 100644 index 893d7a4ff0d7..000000000000 --- a/producer-consumer/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - producer-consumer - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 8ee4340d2437..000000000000 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces coupling between - * Producer and Consumer by separating Identification of work with Execution of Work. - *

    - * In producer consumer design pattern a shared queue is used to control the flow and this separation allows you to code - * producer and consumer separately. It also addresses the issue of different timing require to produce item or - * consuming item. by using producer consumer pattern both Producer and Consumer Thread can work with different speed. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - - ItemQueue queue = new ItemQueue(); - - ExecutorService executorService = Executors.newFixedThreadPool(5); - for (int i = 0; i < 2; i++) { - - final Producer producer = new Producer("Producer_" + i, queue); - executorService.submit(() -> { - while (true) { - producer.produce(); - } - }); - } - - for (int i = 0; i < 3; i++) { - final Consumer consumer = new Consumer("Consumer_" + i, queue); - executorService.submit(() -> { - while (true) { - consumer.consume(); - } - }); - } - - executorService.shutdown(); - try { - executorService.awaitTermination(10, TimeUnit.SECONDS); - executorService.shutdownNow(); - } catch (InterruptedException e) { - 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 deleted file mode 100644 index 7fe79089efb7..000000000000 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - - public Consumer(String name, ItemQueue queue) { - this.name = name; - this.queue = queue; - } - - /** - * Consume item from the queue - */ - public void consume() throws InterruptedException { - - Item item = queue.take(); - LOGGER.info("Consumer [{}] consume item [{}] produced by [{}]", name, item.getId(), item.getProducer()); - - } -} diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java deleted file mode 100644 index 2d4c5df48e5a..000000000000 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -/** - * Class take part of an {@link Producer}-{@link Consumer} exchange. - */ -public class Item { - - private String producer; - - private int id; - - public Item(String producer, int id) { - this.id = id; - this.producer = producer; - } - - public int getId() { - - return id; - } - - public String getProducer() { - - return producer; - } - -} diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java deleted file mode 100644 index b81285a63afd..000000000000 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Class as a channel for {@link Producer}-{@link Consumer} exchange. - */ -public class ItemQueue { - - private BlockingQueue queue; - - public ItemQueue() { - - queue = new LinkedBlockingQueue<>(5); - } - - public void put(Item item) throws InterruptedException { - - queue.put(item); - } - - public Item take() throws InterruptedException { - - return queue.take(); - } - -} diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java deleted file mode 100644 index 0ff27e4d24cf..000000000000 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -import java.util.Random; - -/** - * Class responsible for producing unit of work that can be expressed as {@link Item} and submitted - * to queue - */ -public class Producer { - - private final ItemQueue queue; - - private final String name; - - private int itemId; - - public Producer(String name, ItemQueue queue) { - this.name = name; - this.queue = queue; - } - - /** - * Put item in the queue - */ - public void produce() throws InterruptedException { - - Item item = new Item(name, itemId++); - queue.put(item); - Random random = new Random(); - Thread.sleep(random.nextInt(2000)); - } -} diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/AppTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/AppTest.java deleted file mode 100644 index e7f7870f79ab..000000000000 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - - } -} 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 deleted file mode 100644 index 4c110cad2a68..000000000000 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -import org.junit.Test; - -import static org.mockito.Mockito.*; - -/** - * Date: 12/27/15 - 11:01 PM - * - * @author Jeroen Meulemeester - */ -public class ConsumerTest { - - private static final int ITEM_COUNT = 5; - - @Test - public void testConsume() throws Exception { - final ItemQueue queue = spy(new ItemQueue()); - for (int id = 0; id < ITEM_COUNT; id++) { - queue.put(new Item("producer", id)); - } - - reset(queue); // Don't count the preparation above as interactions with the queue - final Consumer consumer = new Consumer("consumer", queue); - - for (int id = 0; id < ITEM_COUNT; id++) { - consumer.consume(); - } - - verify(queue, times(ITEM_COUNT)).take(); - } - -} diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java deleted file mode 100644 index 5f756c9386c2..000000000000 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.producer.consumer; - -import org.junit.Test; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -/** - * Date: 12/28/15 - 12:12 AM - * - * @author Jeroen Meulemeester - */ -public class ProducerTest { - - @Test(timeout = 6000) - public void testProduce() throws Exception { - final ItemQueue queue = mock(ItemQueue.class); - final Producer producer = new Producer("producer", queue); - - producer.produce(); - verify(queue).put(any(Item.class)); - - verifyNoMoreInteractions(queue); - } - -} \ No newline at end of file diff --git a/promise/README.md b/promise/README.md deleted file mode 100644 index 37fd214b705d..000000000000 --- a/promise/README.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -layout: pattern -title: Promise -folder: promise -permalink: /patterns/promise/ -pumlid: DOqv4i8m301xNW4FYDLJvIl2rYHYBDcZWtmVKr3jDZkxUw15IhyzM6lFHcdzVaPCVm8ONkNWEFELJbQ71ccKEWIuvuKhXJT-S6laVEWsCO9C7GHz2KmRmav0KVzUqgJCtsydROjV -categories: Concurrency -tags: - - Java - - Functional - - Reactive - - Difficulty-Intermediate ---- - -## Also known as -CompletableFuture - -## Intent -A Promise represents a proxy for a value not necessarily known when the promise is created. It -allows you to associate dependent promises to an asynchronous action's eventual success value or -failure reason. Promises are a way to write async code that still appears as though it is executing -in a synchronous way. - -![alt text](./etc/promise.png "Promise") - -## Applicability -Promise pattern is applicable in concurrent programming when some work needs to be done asynchronously -and: - -* code maintainability and readability suffers due to callback hell. -* you need to compose promises and need better error handling for asynchronous tasks. -* you want to use functional style of programming. - - -## Real world examples - -* [java.util.concurrent.CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) -* [Guava ListenableFuture](https://github.com/google/guava/wiki/ListenableFutureExplained) - -## Related Patterns - * Async Method Invocation - * Callback - -## Credits - -* [You are missing the point to Promises](https://gist.github.com/domenic/3889970) -* [Functional style callbacks using CompletableFuture](https://www.infoq.com/articles/Functional-Style-Callbacks-Using-CompletableFuture) diff --git a/promise/etc/promise.png b/promise/etc/promise.png deleted file mode 100644 index cdb43eb6b49a11b317d7c8abbb8ef3fd43ec3779..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59210 zcmb@ubzIc#_AWdYScr;(gwiD-N;9O=or-{hBHhRU(kcQX9fHIVGJupwx2UKz=+G@v z4lUiBHQ;{q+56eQ_nh~ffBfh;aewbv>sr^kuG>#lS%&B+#Zd$TK_n+Dsg6J#a6=&W zTOZyJuNYECsUZ;Kr{pBBYCedYLLa$#)@Z|*V?~rrK|}Pb;w>&7gHx)f1Zz|29#bAA z*#G?~-Q%OyQ#6MUvRpd+?EBkChcD7RefC(#uUjj!OTVgsUBRxiZ&hq{%q=aSCZN7? zXme(=v}C|}4DB@FC2V4C(%fjKc?fe$vhRKK_i|X+tAnVMJFTO`$Cd{RN7`mMX` zu}cw!e|*COC9L!8z)-cXR!4|mAo}MzCO3qaZh{`Lw1Q zUxr3Lf4`2J&d^rN)kyWKK#h$uo}jj#7`kg>VZmh{A=o|Al^Z!*xw0HU9#r5sbj_)! z!qfA-`Iqn8TYe`_7&9>;wY9HUTNiQY@K7QPsy2C8jGOMitUE_xKHE*gEY@5Xjx#oP zxpYaQq`Te(=8Z>I^%=~$uNDhhY`X;ArbPF3u+;wNa81flZZ52xXiV5?S$~W>1%=hj zpje)vAAf#XPL-aD5A)zvJtQ&J&5qoA<%GoYud;J?emV_Wv2wQ1?A#MYTF0H8w7J*1 zQX6``O-&dad88C@J>|2tb7i5F9MIsZHM9OKjPmG5Va%HQj!8;C6a- zg)>Q5xJiSPDhs+GlCkbg@P*q=a?ER)k&#S=tSD4jN*d?O=4v0JJ7_^%#Gr!emybV8 zIj!~Qhix;h2iWI-+8O#}u;W*Y_R-#IUBkJ}W7xU5ec0`%ZZ?oGcU)||RaP)QP+8sf z)bHns<0vJ$BPhor=kk%UKnX|lsz49JZN9XT}iKU6Ui)t4&?krCmc$33+B_iJ2+zx%R zlFj2|#*@RtED3g~0!8I`rRY=i43zvnVZ9tTRo$4{eHH=NgnHqf0stZ3)Ks+O3 z<$Yd{1wH7N|MjD!FDdbbTd!ehs(oeBl{#eWGgXnJE9$CmH0i!F6KxF#3y0lVv*WWo zoJ2l0@{#*`N=OSF5Yv#o(~~nBDmNt&$rWus?s)Fp;?zK8cz!;S;4P_7%D4M3L`M1y z4QW(VNXN!fsut^e)LHcu$Vp3IElDL2eptt34ecI zTR!Tw{`T3@F}m4`Cn5CguawB^k6Am=5&w=MuT*dh`Efihy=1h${3#J8*6YN_%r$)G zu>)(PQMkZuztl0pdLIs!n`KV3WI1j{aM+Y$`AVJhpK=UTy1tU~H=gR{r9~rNaqsSM ziAuTgwS3RAUK_t?{R-acg2jW)9t%Q724rVjbtdRJ&|_l+xw+govvkfTS{fekir3Ri zw&3<#59DD^q^SpGF(TEql&HhMj&e-b@Q4pE$BR zld3k@Qm!&o=*sq7xAz%~@VADpVmBUy8nJxXoNqm?EURE5{?LE%@TX5~EOOGa)A=UF zYC-~C`4(DAju+dyN}@iTNK-aarDrjH85wE(VD*g7^Jwzca;HvGj+mv%72MiFdC5;R z5^Cxi2m|d|+N}izYgIdMtL%pPnHAp{Sum?OCVm?9=q-E(29}&#TSt&lr$&5y4 z9BDW)(i_XOH6I^%ZY{awHKr=XcJ;(WM49}+EuG_eMeHEz;YP&!O4s*O9^5ax3{GHg+107qhc2dEe^H$hJ}V|Q1W{$1dGj= zT(8GlLMq)m5mR!IKT6G}+f5sDOr?bUa~W8Hlw=awvIyLGoEtm;)C z1oegGerGeoMXV`~=iW%vjX+rYHaBKtg|K7(%f3c|*(sHbn%oVtziQ?MUrKSS2rlCFi-sC%vDxHe@=ok8yEf z^-AVu*~SWFJ>+7u^hAPs{kI(?wwnA(KK#%T+}5Aegfs@ z+j(<|s0W^JTkS_~=rk;8vY^jgxiTyB@z2*~Tbhnb zL8~{=UU;SPXQRgjR~CA!xWnFmV4lZrE9>*0YAR}G@8=IHifM7MRy*Z%GX0K|N!uwT z?>T?}`~Ltl9l&T@-;X`=P zzN(LIPVneq+&Uzcql-)sL<|de? zU!{_x*OXkyrbXcP^OIt9VP6phKQmqPslkLFv$InZNKLI`88tO7N)2fw8{4tzX~G~X z)}#cO(ZLcm0poyA5v=s4BeQRN!$MC@{V*-P^JpW4c1vDC!wA_h^%NO=j@HhO`~&aI zfC!IuT>D7fiDVh#^;yq+Bk5r#0yr8wGv3y}fyspa+ zqMNydUN(%!?l(OqcY8(WL(VT3;?k zH_v0q0eHwUTRd{D^Fb`DhIDNJ{u%rKdPb9$3oX{nM~}vwBNv42%w$54cOD|$6#Y~#V>oMGyntjoXP4&+N-CZQyHX9)Yefgey zuRW^Dh(|3ozcHw!`IeVsROAhJ@%j>Arh*~{c@UMK({u`v_MFfnoJ zDmgWP?f9*ZT0j7ET{)ov&zF*t4zql{rTL*cJ#7Gh1ynEqwf=l1K{Z19kXk-h&mk8Bp)Ac^%k@l|_9n#lV+ zR4QDTf0&uRsx(pQ1H@VrT%7ynG7lFv$bTWJ(An9q+BeqaL05NAOaO(^_M%yIBU3?% zZIX}`wyNp`uYiKs>$8@=nsqk`xD4JUQ3i{uI>K%N0CcJ(UBPW*%z zciePcfPRBq*u1oqQu1d=02KTl8n4Xo)gkTPiV$JVir;&FSne)0>BzdMgdyOlN7Xh3 zGE2Pt+#+TYe);y>xbU#kwE^-H$wauGM+X{e&r=JtBw^le*9^KBOBs`JW!nvBb(!+< zxd&5ee`23*OFyomaeKz_Zf{Yx%>X+cG3DiN`B3l_JTEM~!V$JcPPu~ga0_(v38WYE zuws%UqPY7dQM4`bN=w2ZV;c`XUZ32p3$8|^ntRA*OFlWtIM*-Sl=6>=m?1gCa|PMs zuj{t>NnAb_%Zq%W30EFVpAt5>_SoiT*GO$`I{WbKY=vcX)$g&?JIxNrt$#YoMTFnr2Y1V9RVH+x z1cC2aZz-yPRiS6}rlDb2_iGZ&xfWm80Rf=VR$UH5&1l{ivVjyv&3>A4a?cu>U_W?y zi5T@M>mhxK`A01|S?hxPE(yCGZCG6sWMpoMY(Kb9IT3bYUS}r^wRd=XY!8 z(6H{2Z|_If*Qv$a9z-BRB5#)!$PA4-5C!r%&E9~N-KZGMmlTkaLQ6EiYL^}wx~!$2 zt??phZxET=&d%ud!@Pfg>iFnT<4h*WabM|i@6RLN>eZGhl#E7YhYpsUqgU#DJT~;PiTlS$k?SXS3A3wh;i#j&;@{wdI5|Z=yT8MW>`lT|uC!f;qzWwm@6hQ#B zjRXbM`8CZan$eTj=8?9E7o2kSn5z5V({p=pFq5CU;_&l3?z%ev=_7xx!mA-^I)9$o zr1bC`q*A`qM5zQE7bn+{bQjHa6csCHLj9pScUi)gd2BtTan&OIU0JCv(1#lvbKVVB zd?_s=M7m?=e1HD*!-h`ug5sv0u7MI%oP7WS3l4W-j&zBEPiw5(fuS+uXZ**VGVmo@`tq zx}xIaP_>eX@RX&Ml5`-KClCZ-`No3e=N5T*+6MBOgGk9Pq0*GrS2~k?Dp2)VDYsQU zzKM%4Gh4`G72}0jC%ba{(L%mmin8L#FH_Zqx3}m6DXZ!TAnWH9Q_BiD*pXk`%G6(q zYhgU?&dps3xZiWDG0j{9;o7mlrsXlIt8_${4y+{F*sE1K& zyte2(+L1#nuMjI{_uY2wtE`BI`u^x>Gt&avX(8J?@hz%(wra2^ zTUSO!Wuw15O4#F8nQ_y8Vq&4SeXypaC%=7AW-BsppRa#j$za%KY*EJx1km}tnArQ| z)(r&({5iiSlcwvkP6wrnKIQ4}r4N3hin9IWmZF=drf$OgTZ{LYt<0be_4c>kazt{| zzUODRyl*(78ToU?Nw26;|DOiRcY>Vi#u-w(%im{Nf)b_V>lIAe^E2B^OMkXq;H}?W z{mCoh>S)}Vu1$q3m*h3G4pTSR9|(FLuocvANFVzmO0! z3k{n;T4JR;lCD8s@L*W_ZkqCR`dw@5Z?m(FuUTgYDlt&m>qzZJ%L?&KJ(t>%-sIjSubM2Lp!O$D?2$|Lm{x9X ztY!O?ADdr(RD5|+p=$mj87S z`n$X2y);OBZB3k43^M|Rh@9ftquM}TUi~n?87Gu-- zE7z{I+TPDAdUKhbL&<#}6CiwZU7F5u3tb+{!p}d@Z2fNaC*MdakBMX0{h3>2E`kRL zC+xVhvQ%1&B#N*aFSKcR){{Bv?!lykzF#i z7mbo#Y-(J5{Fn)Apr`kJZYcG_1;?Tyrex`8F?Sv5I`3os9PGz8AfOU(h&rp|8EK%K z?evcEU@ZbA8VqkKYngb`|5l3wexi*U5%qoGW*ehF{d;DW2R?sGT?bb!QCnJ z;=;uhat_$}&j!s$jORWBFvN)-^sFib&NV)Mx!j4|9&fG2Nx3I7`;oX2V}O&K^@TMHM; z1ad`%Hv5w~Rjmy4GT0k>0DpWF+tR`+=*+i9wKVSb8pFUyXJBsoCT;POIXxQS{(Wq8 z#0Ya0{o3)^(#@G)sFD}ua#j&(#B>A>Wz&C0hn#5WDYYvF(PyUKuwuL^Se+}xg1~C819wN5proJ#+dGmBVX5&zB(seaZYNx ztc#PDbH;5h_cm>9OorUTwkXAZD3M`u-?SUQbQ>utr8I2)Hd?6DyNrnH71{Y|DgUGH zK_e}|y88JAB_xn+oMH0IS`3u*CsWA@EBjl(g0o<$&m|PrVmoeXwmlJ_Wvq`C0)SS_ZC%E35UBjmgmft zG{sgMmPNn#F*43<=MSB%t!iRkKvN`r%aVU|6XwcN_8N93(@&qK1F@bF-b<>;x1L$E908-rjjs{w;$!{x=BrjY+X@-j-bEebE-8uP`Ivn3a;A{yIFo@cDB! zGqa1~Qpb)}L(+P6)xT}1a%CX?O7+jW@Vub&z5S*3Pf5PKdS%vD0^tmTk@_$&Adb@m z<*vnL)vakpaQuKEI;17?^ADckAEJ+qu?J{QPllZV??}hl^f|5xvV0ih$z0>*2h;c`1@gY`}QtC9sC zL%gC#PjSb@;UPHDiRFkH4Q71DElVNlMAW6}uWg&(ARN9IQPKP(H`ZhFHR6(M90#?# z?Grvxt;^vn-+a4!KcFRgz2#C)v1NB0X5n|W7iO4%35G^k=xvsqq51Vs{^g~cj}Oh< z`+O6ME&7rXKaSsf7>a5aW9gXen3HH~3N#r-IGH?A{&Q>i0sEDiq$G(A=yEB>3G_88 z&NgtiMq5x&uF!p5T(GB0s<0ndEw(-ngd;xrq-(h1DE&w|{vijf9VkAvq!E_S?nWLH6Y44`6OW<0`ZDYfG$J+>Cnw%4<4Sjc;HR5c^rWd zKb!7L|Gmh{)6iah@q8{k)}?J z&XQt2`@evRy6?(>tLx|EH83!wqovb$bJ9gtTpahf{b_-`&-muei>N38w~};UUvzeM z-7B>*m4ryvK5ta5EHh>FXL3HvhiPe*fN;OvQPCf?E08^qC(6aG$%LK{zw2e6^J*em zTIM&E6;8o#Ls|%JuKx0N&Tzi3SZvm-uI@WQg%1gVc+bub6kAO!1TdfwB(W2Ff3LPq z5z_(91Gfp^^-Amx_1lb-610cK4j>S!Qsx45JyvrGZ`>VcqIomrNdWP3op+piO2?7> zI~LKaQT{y?F?mD3FhnTtdK?AzXINu^Tg24dFLZPTw)kJ@XvB$@o6s98H;lqzhkg!Y zp+_jgIhU5;_%&movK&h@|NAMQJ{}V`RZYk+`CClm<0m0O`=GK82|sYgRXEMg4OO#Q z)PDTj4FAN;A3yRFNU?K;_V>RFp-dHayuLG|(^PC$mpUtXO*G5?wL|NJp8nSmSVvKJ z7>f2zES7;e`O8;aWc=Hw8U?#WXj<4JjkIXIP6$H+0 z^OE6Mx+3yCRpZT6hsk2?>JJ}6g52i0Bchb=H)WV$S-Ht!$oGwG@O5XZB;|<z|x>864eYi1?&0X$82A%tPqgz^KF6K z`86OM(Q(J#PCY=Tsl8am6@AL0wf>moL{@;{R>LnIU4nJR~}e3peuFtaYqE zV;n0N9-1%&#i2=L-S>}vg_SO5*G24QqU+k!kqN+WU{ekV-E&zm{;F`nK*|AD?Hlv1 z^h8+Y59!IR%Q%Jw1-T;_sr!;Z)ve4@C+)n+Z3%JPT3UxRJ0fIDk4b4t5U?xRh4hDlt2&9zg zPANV{mIs`nvP^^*VbtWLr=kp#d{}Sj1NVg{X-7Zp?Rn%DFi&p4<^&}|jMaB9R32Cu zaZ+1SG%OWtyN(<+ktGtTyf7t-LdHPjiS|nNRb;7_=2A<;BpK(-SZXfxn_gTY#T?G5 z7m&KY_tYbyi)oBoGK>kKdQ#Z6A767HBFOf5>ujAu%+4t_6UXiQAQ)OqK(3wWJ8aRx zJ~#I!oH}}|sljG-Yel!*Ve$vgtjcxebcTMkl(qf3N>p$#{c{x}^6TsehfF{?mGLx> z{^dV{QJkpL>;(!?2$hz;|L9j;xA}IH3mqK?QVlE@(39%9P(pqE`ZVaeN_>O^VCOOE zm!2RF${qS+`&yu_yi+fSQEZIq8xWK^RmQ_5r`!&^BNdb95`?rxF|exoPYv` zF=T@ghPBV!e}JlAiMjY{Y7n&~7!2k9}^{xxvKcKT@u#@4oJqXBoW%E%~F| z8M=o*w7^7YhEfDQB{dt6&|uDHe|DmmQjtg}0w?a9JKdYfy9nr)gQH1or!i;E^b}N$ zK|v14cPxG0QJp`uSnMmjQrn==gO22ciIaf<{z#4lN-l~q^7HFbQ_HLcBqtl)pSP?J zI7i!Ea)pNnb=p-_%fmyxA+o7k@axBq+TqMXZ-~j+rrsUe>TDhyjP4hN(kkrrZC;x` z7DFs+)liXD=u~TTo9{L^YktXHiNn)Zn3?09FM7L4ryTnu(-<$GUan;@XDPUZoFXST z)5yAcWyM-*C7M8>i9=gK z-K(=(Dfp(O+yyPidN8>hg9E;q2m%U2!-HBPLi;!eANlJRpMZu7BoaM9I966lU9IO{ zpz3W_r;B5u-VT*r#8WhPx%`is^oIN^Cq8D@%KXn{|NfNP^=rp#blx3^xLM8iYj++F zdYW;1cSaLGQt16F-PlTMK0jHF&)tk2bANp+{mYCe=kN)PCD%vm*P@=HI(41#qb-~! zaX;RQYbQMj5QxNQJo_`epdAKc!6)I(Bxwz|I-2utPjqnB-!*;7R>(?U!V3xy1cK+_ zMK(6v3rR8W_`?WK`UsTIC_7_kT$!D*xG~K!bIK>(YI?SIz*s>FbjG%};$B2Nf6lll ziCCq)iV1I27yHP>WAb&TRVXNq^U_w;>Gjgr?7R%jnBKleM=SH8cIIgZ>BYfLd4PQg z#947It$`Z-X#2!ugeMa5=vuxOd>(6z~qZ14DE2v3b2EG}+h@~ySJOSd`SqXS}7D#&wD z_Qw2$JG#zxc6toi=ohDGD&_7ZP6C-y-x!e89WR*g$5^#yOwZ9AC)iOdTkgDI3{^HL zlVtA#_W`J^a&Bpf=*W?D7st2xB_%h1;1H@xTMB6ok0)!-zP3>4Y#nIP->S2kHYDZd z+fc51p*$4vUD+MOkL$VK+V9?_@A_x=2w-jA>O6SS)UxXeY6H+ydtL;;Z=e}g+qx3-l$BhPc z8W-`nfmTSGEqtgtuvw;1F~COPpvD?)?PPLM5q6 zRn9x4N{Ms6^m@8uo@$!z-xoe_#a=RNm3eKuFhEhi1OS5P%GbI&zqH!=XJ%N;mGTeG zoA>7p*Q@$|LYF3n*TUS$2=i-_F4YbSk4#R+hJ?_xxgoxt9GO|NwkHhI!-;ZoFZQ)3 zltgd3EEJb~Fd9}DHsf$wS&!1cA!fu*`#!1{uLyPYMz0w`r_pKV*3|g8i2L;EQ(0NrwI)KuiL3Fg9{z9Jk(t+pQWjl zh-8ntG^2Iht+rqv*+z$)RKb5cUZrqvSP!Hsl-!>|eoB8de0Qr(JpSO1>vNYv9Db@g zC@X2a)=f7V$|g*u<%&#wfK@TqknRz%I58Fln%i16i+gKRINN%#@&rzE-R9yV>>k8nFRs$Y`uguPCWPWF2P2xJj?1QDJvEZ> zr%e1DMf=k)`3EL~CgjruB#ujQ;7bj};b!k+WVUkWpF+(GWEDdE00#CpUFczvV~B0g z|KWFj;=ae+XmLw%%9j}kdL|^^kbuADXSbTB!4MeDDO6f?~dM7;2Zvf zZ7tEt1K71zmGb@jZ$)IguNS0_yL416^WsTh#6y;M(aJP@Ak2LJ+#A?8nV^U-ExpD5 zkO8Q;KO59XoPuNMvCeFCROON~uf`$c@z1ZRpOEix-Yo?(ggORZD=K_#YyeUvskQoP?5=aSdfx zzc={y3DmZBcA`*hrhLL;HJOD`tgGv3wnk*fh`0)ur!ljb8Yl(;fw~F1p<%pq>%J>3W6EcM@jOh$MUnYN z;lg$X(|~s3GSrzkve(bdHpNOobbPd%xfpFzNuCCh$&Z7o3<&dJ@_Tn}#O9jO5|GgG z+|hBHkB93(yBT4Im-QYyCP9vusr!aO7;H@q1cKvbVQOmGRNwfQq^)kU)bWvz8ezx~ z?Frlx3y0ElcfP%`aR9U}Uo5j#lIiM#{8PqHawjvV!!AE#)UumlWoFBuHpF9!8@-re zrmKEe2Qva{n}2O5vvV!DGcEMdz-S;4l2?CnKZ!qt*ny@$eg?lFjyU^#$wz$i&=v zh=-j-{}eAMXjT=OPf|LBHfKI5Pzc3NufnB2-VpOr*-8VExcNfg1yh2YiLf9;<^22q{t?OJ+_2LD&t{cm;5)xJr zc7d&jI1?|NbpHHc5l7x~a-F1{oIJ=})ARisLiX}53W$POe&6_odc zK0ub?v@G+~?kDD=1U$erE+HElt0~_UaF9#GKgQggt>5OIvnr43vED zT3ZLYO0<}~D7lDHyD8k1USe_gI zLB*<$>koJ4HcYl9egbCC;WukByt&wVsVBo}_O+p96z4bwbC7GJ4b-*PHJCs?+E4hF z&<)&POGtL9_Eaev0EWxXmec2e+{C7C))wGzxx~!B6vf0)UlzH}*AsMJ4U<$LYj67X zCAnPEHJq@ATT|jy_b$2Ch4IX^N<+UDAg0<@*C&?@!!h|C9iJQh99=?>xd_CGPbAq#>6FLE6xJ8bfOyuF8Tt&|sbd+G*8Mus+GZ?0!X0?9kd z6Ur60|AI&va#u2><8pJpG+URRN%4&pRQ=$OkXIOgbN9eaYNO;shm;uH4avi#jIeSG zI3R}?l{xkLl*$wXofnuGm|ITl@g>>wyKVJ^=_?E$?LpbXZesu$7^eK=QBgQ^K3q6U zDlUO67WVIVJ`So;T?Mi?RJnOv_M{+=K}m7feQ}ri?Npz(gbp(0Y)F8r4w72zQl(vT z2xY=zbFXVa0qTD5Man=-xVvz{YiQO%FI#N$&25l+v}Zaqpz+P8ftD6Oo`~ry0$tpo zo*IRYI}twg(5T}NArX+)tj%BVmCt5Pm9`k1*uqH3cc>#lM~?Si6e9P$7f{{bNcF=; zb#imxJ5E#x$}WTb>ucj)BqSzy?f|GM9r^Lkfk_cLE{@LVW!>0@Ngn>9$YoyVyy|c7 zx4KqA{ag^4de;!M)vh(!b)neG-*Ehf=Z^c1u1z7Zw)johcGL)qizYWKGQWoMFh%K^ zD(bQDHr^;x%ZtS89`PL?XI&`cICH*&U!a}`e`N65A{Fx+A{&-Q;E*xvRS}y;+K+YN zd7}(4Duqoz4x9zCE6UWfrym#q=&;IOdEPJk@pYIz|LN-@<$>vDtxV+P?=9`19quRT z2_h9o^YH1P@4dpng92?V0YU9nHVzIYZ~P!n((guKBL36b7-wQ7bU_{q($eNKuc?}L zOH{xvi=AUUm#MW-WRt^pFHd5x-j0e=)@k3Xt@Uawb~Dz=L%WfbSB%T-SG`-oG@P|Q zUOlAGCChUDJO_jdR?yPwE=>ud!ImT}JOu@9PoZltrnRQVt|4-+b5Un6q3pxQe6=Xw z>W0tXKebY(^Fz|!Jqw73WUW6KF(kCqyZ?NNz#ol=sJ*gKd=8J){wY8FN5b(DFLviQ ze6r2FI|c7dkXNfyDk_9&X(0?gG~XRW#LSht*XAr;@Z`vOd(h`a?Ri58wwOG^ueMz;4hnv1xCBEIc!ULAl~IR%xCjFQSX-gxemXGcb+rlbr- zbH}oj?#2DbRnnk^(4_9`>zku`@EpMl8PXv!K4k%vGrq(*S+pdSLc^met!If<_y@H83#B z9ilv!VQXvqZhGS4LG#lH#Dutr?0B%4HFFEJnxXvK1XmIs9*a+Du0HK5lozwySyJ*1J28P8{8GIse) z8uT|t+WwC+g4d6=F+gy5CDsXfaAw z=d`sMx4yV$*v+*A)zMjFcvhnl+o8u^US0qN9SHUoRn&&zB4>-Oeg4ut512QM8;p(!reb z?<^bv_K4nTKgq}A?=tCL$w5Esz|u}F!`S1$8{?WlvCMYSabjW_$adh#zmM|9FoczD z0c2@Sg(Bv0diI+GWB|Jt=iXR!&QwAW?&*n%6RXOcSQ~X%BdXeRw1NY0yMo^YizA7<=v8 zTPp(G@dj=A*MbhijSm~eN!$1i=O8Gn5P>3pK# zx|-Vj!+i;r3(ZwJh323nM@L27v@yS_`UW*Sz!{M}-E%!Zlxp$V6I8|#2K4G!lF#0e zeF)&{Z;ad`=jIj9tIKX)mxX4KLgC8x_FiCT0U1qU0T1}O0>hbGQwSrrnHG_svULgZ zwd7LP784Ya(6w}KiAQVY#24Q;dI$EO0@JTk6YUk9*|Af+6z3Kf=P5YyCuaI3_N;rY z*s)d{v$4k9KAQl8PtQt09|-dG$0$C_IpJm>!rgcRgF`7VIq352n-Y^g&Rx}92bO3;z+$7GlA^oJq0FdN^{hY#A0J{4Wpf(3Yea; z+XXrpOMU@y=9Ybv*~K~s3CfI3YCz+H>&m?i1w^}83+j^gcMvTUUJdIyFH#mWeTkbp z6(DWIROhV5vO^SLYAmx%)watPu-1kz@peI#`5Gchs;RXme#-Q#q#%UtuW-%>5v<(F zvrHB*#8xOuNun3;cMX`yfaDDvIM0gchBa3yb&D@O?NCo3=ccOK@nFN`Usb<#3u+LH zB$Iu5SN8VV(Uex?dxw#uorNir>D6nQVx`&WMuX4BgRJDOta0jn>A}~$>FSa{L1YUN zQ%iQ=Sh;6V!RowZKG17ZwFI=?%B;%b@&$=Z(7PJAm!WVWv6MNPy~Bb01Lv+>3wwUH zHP6W2Pf}k8sS=+xpdk6NEibR&z1PN-O!@}Po&vw@Y&mCVpLo4s@F2h8Mi(S|Ze=oR z566qxL4P&Zk2ONMBT){U`7}78?)c5Sc|L3QIiXn*q<~V)o($J?esMDmJ`}>8b>*lIB`F^mq7T%!9%HugLGfKaefsnq)#~r1<~f|-N|dK8aML|Ce7ONf z+f?oVdgR&K+S2Jkt4DW)-U1`V#hq&X`n801aeL_q{^GqGk_*ADmhuw>wl};`c}GBWE1zL*ZJl^oyLz*uMK}^#pSOGxRbKOh}mpR@Lxn}Rw4*t#p zvxV13fw3d{hI%SM*0#uPb{sf5jvfo|#z}{jQee2DCDV(M@GVMk z@3_6UN@_aD=!3;JJKHa%E>vxXZCt}`LPMB`8hVWd?Z8llG!uA%;=}ra`Kv^xeTc*p zED_CqJWh`Ty+9YDz(nzPrO{Wh$y0|<3q)k4@aay2v*(_NESuJEmXzwE!Ax+1E+V7IR z20tk@=jt02;x4~muG(ob-WYw|KrM8`{WXuM2NNSGZJ0RFjbUInq4flNocas5p-m%9 z{zP}Xr>E!m%AjYOT=-|e3ntB$>MZC*N=oomVxnEvcYT!+J7kYg87$AAKR@kvkXeZG z;@(NCpV6D;bNcq<`OE^BM9b|hzsb$Xrorz=qXHFvVhXvOavJp6BTwZ)kIZwW{{~DX zSkL|3f^Jy#l4`r+09ic|wpkdvJn?NtG(d9hbKnQ?c&TDRRSQz_Tep2rP_+3{g+7^w zgZHC5e*xe)l>3WIVyU0P!XgGe2M3`v=Xvzu!w4KcIR%qF;#%>8j8%{1-FfeYG#chq z_pcYaZ>#nl>2#QU40=sy$ZM@q!af06ynen!q^$jg!0gW_qK(fY%u`(vv?>^!&YL zSy`Jul7nr7^6&1!=0rtgw3A0st;@(!;+ppOAlCTB@SccJKIQAg-oy#xE0XJ-=R=g+ zKXi8T1D_9YyYtu{`Xs^&E|D8QuD3E?87BCIY;9?2rRZ_WkpKd%;_4of(?(Ldi6h^$ zF^h~r<&hT2ALv2(`o6*3*P?r8VNXo_otc5*Abj}j z-iLP~MOrQGa9ex(Sr^hoy}h5>lMG2IkK(z#S6X{tDanWig}iRDG$xJnSsES9>`1)1hO1fat#u zn>0r+l!DqOoOvf-1lt6rZ6-A2<#eSwkR!pZAdonp^ni+`z-C9(Y95-N{e6}>`eNer z8rAjnKjufNz(ou$9}p-R%@+(pRSdFS??>2sm6j7H zixOXm03n8HpFk!=I_cmGi-SAH63F&v(5*^JLp<4oP2bvg{iAgT?fE&9Ij_3N$;R^y zKHbs*?YhJLyn#2gA8TqtNe}G5b>sE%M1oQrXxl94(V+YV4e;}MxKjiy@a(rIszCo= zYA*z#Fr9b_u8%;6le9FW>PO6~FkV>KXg(_jUgd-V@u1r5Y&=^F8et~JH4%3mN01D1 zDc66Ac+~=8n#u}k7~sKM*R|~T)=w`RrJNv|k$8u-Sa$t+LV{!fypyzvCa%c&42}ZY<$X6LRxkWRs+=WwrlsB!48e_0hX@d2s0Y`6E>P{ zJh;jbDve=)OQ7*6DJ+cRh#diV1*!mGCyX0yHz#vW+ss}8ri+BBD~v=XnrlBc{X|4m zR58@YDx;bve+}>Rr!`=jQVFzsfX;%2zN9beOB#G$!NK9Y4l}N?_OLNpEBh!7j^Psu zRltzq3Z{I}a-#bYI(SpAqlyaL5CSK7qDLV$@%-o z9>|`8*HaXAbe32LV)^|q-R?Pn(S_8V7h+ZoLC( zMSq!tZJz)eR|RYu=xV5^+JOcXRP09ha+OLRZaD#mFi4~QI$~lb^6V2Ne3wo11LDI; zROBYajnmUQlM8qX_pGm6&hvMAau)T#Zv@>J#?xClZ*^*#GVqOozVa1+yegvwh0RR0 zlJf>nh)nQnKphX}Pz`%0KX_LBQv?Qn)_nd(8`>k|ThMvnJ&_4W7d?MZ-)kgTv& z;@dA?>CEVGSo3hw&Uf+iC)a}yA?Aqn9-)qI4{9I0_UfIQ64CqE_>6<~8sadMcIC(r zLad+o95GdU+sO)Cx_qMWp%LhWf8f{K?@WU}d~oOYCrA)L@k`RI5(b%@A0AlLWK@lR z{B3g5zqkDn7Y#axKkF~yTf^~r(A#_t9Mmjw>@BM8Ic{KP)>Uj{^WKw|h}~9GLt z@7&z!!&@~k9nX-FO+uB@9Vbp6(i{~Cc4TVNiaZ}h%c+1)W_&;Iw4X;)ELahMLVXX` zviaT(*mNFS4mM5Xg+zZ0dtaL1RU&cZTFq#K;KG;^Fwv!VC7$Lfw%g;}R_A_z{{#%q zATENgT11*P#GN;yx693MXii1o-W_5_|C<3;nNQF$Yt(hNQskZwefI5=FKE8mL499} zf)Y>9mtJ1cetya~ZUn@}TH*1=iD^zTqG#Iqai&~8K0U6>AM1kc=Rq(X9S;Us>!SHz z19k9d)yNii?qCLZKub$|t!4jHXoDuKf}|2-ecEpuuqAM;*Ix`hhRbzK<>hHO!j{1| zR_eJ^8^$=$I00ma2zk64q4h!K|8_Z0rps6|Sh91s_l&VpXkK2i5|Gfg=aald3t4E2 z{D0mLWPVN{Bb|0)Ej8`gqxmcqhSNtdBo!xNm^8suJg-{tp|DmqhYrVJcl@wz?yha_ zmm5|c?(ZpA_x;U-&~W@;To;sV{U|wx;$^&zOU5~tmURrCkYh!hMPTcgL3!TL7(m-V zCDbwhKN2O!*Qo95J+?%*hJ2^-{%E}>jjl)D1t&0!c9Fo*r6kdDWoOqAjFp3@Xa zR%mDxKi?EMGg1Ruyg&6$6Xbu+4K@A%jh}qQ2>bTvebIl^D@F8KzkfX8k6T-l8EW?@t#OHw;z<3gZ-}+) z4V%%uckg_`%Voe9H)0D>(80kK?r8DxRrxtjVP$PC-Ve8z6z@^dZ8y3eNfBY4K|BlW zNuI^b$kWfCD{HR;X(UT{RzB@R<-vm`UwmLf!qDg0#DYF(F|W?vV!$sGT@imJB=wr0 zLd<6nsT`+h8wZ8TEuTRF;SYPxrX0g}QPBkT`P=DPS)eaC4e`q8A&Tzg=I%pS+PK7} zNbTB1)fk^lht8VsiiE$75(1ZSa`mNxs@7k@D1A-Irg{5gYLWyhvRqB#E+LLNqE76C z;&!g-bxxO8M$lh}v>$=f8J+E2CMs?uh7>Ffz;|9 z?>)z}-(kqJsyJ$=@|edrvWssoR#tG8wY6~cb~>zN9Vt&&B7bk<{i?&Rqp>QFL}hc#UZi|!8UD=35t+rt&@{co>H$%YlS#zM-K1aZS}Z? zNX-Vn((2W*@lr7>U)to@{9jft6KHsmPA=qJ`3I}{H%8X;EG=5cTu)Sd$v=6_oK1{V z+b={}^s2F-*aK?EfacZyKCPIg>|84&Od?y~~JQ0)s`AzXW+8vBc_n|c=SLI7~%DaBh{ zx@n^D`^f{d2R1LB!fKD-B)?r&>*~2Wb?sT9oPOS5b?yg$c8ODCQ3;W@j~%w5ZM(>p zSHLr32-hFf19=U`1alDN6saVrz%2B@O@jAJ;8sCpbbaDBct8Lf0HtHFYOAq)Ws^~% zLddBD8pF|#uBt2>hJ62iwkim!FaBrVcg z;I=`iEUwRa#;orGFZxMfA?^`xM8BV>gT~y>qQ%r^ai~ z5}3&izO9_BI!%jqIN`Z6Wu`1-Qf8QUr^l z8L@SIv)B{~YwL>F*1>QEl-EIiHnvo_WeM`s62sqUJz~dV*4_+Y4doo`!n$w2il9Av zf(X6XYqL=z*dWV%D4S^SVz5y&GN3&l?;L11`SvQ+=haYb{4;|3h3B?IAMkCx!^J1- z5~tk1{n@2jk~1+fq7~}sJPFzfK>Hyx(}6p8dM^sXn{gQkbg9P1F$G@MTGv z&w{mUmezil-!gQ*nGZL!9IHJJR}`+FJxj{e5G=tbm+3fj>((XM1C?-Sh6>m_GSBitZc0 z8+O<7Gz-mcveDDO*v>N=W9LM(zruH{@l35qtEBsWd=e*uB+jE6pL6tFn(+MW|Dx=> z1F>$~_bFMCm0e_KXG>!IL_;;V|xmZjjxYLFL1tI8|S9TWS@=HC{-$FpQqM4Am-7pT^zg6 z$Hn0oJ}M%@Y5MU-iQ18b9$hEwZl_2!Ms##-60Y(y+-lCb$D8j%AJW(t=!bpvMCRyz z5KpX26*jTPzH~A4c5Lfp%ada>M)}B;d-8W(3(vzTi=x=Z0S%3Ko$BZw zna>G+^0TtVhONAn&-yKg^W&(>(U!Un_8lE(Vr zf6_|YZH$kXac5w36!nyi-TcKp7Qzbr-6s1+y^l_7Z)D=+YwW1h&np@I%}|6IH8LwyXtbFhHYl}DR;OBC+C z>Znx6H}HI6nwYIH9KCninTD4* z|MvJtOaU}+g?|(^kny=6F3k5HsS4Ru|2JKLwKKI+%-bV z`5~ffIh6Hzi3^#d*TInWq&lK*6g%fPLT3|_i>(i1-*So5Fp38T6_t1L)1keN%EuVv zA%O78W2;`!Qr^GQ;D>s;E57_%Nb~nvt#*bKHX7OSjlw>diR%a%2S6n&!D`C z2eVPkO>&OYa@v|Inb9M+&eaNFYmAocJLx<>X{&uV9n*88U88#D!&wfm`?^H)R~%Er zg0qn|L_}*|nO{Gho_>_%ciW$FJ6J6_5x1W1v6-qfE7DEg+r!I}-4T21d8&5Tzvr6@ zTBPIA=G}YKK(YuA58s?(u5;Z(WqDw!s}axZ_`#DaeQ&(nZ*(XK=c;XkZ&k*6jR~stb*8b6I9Y^bT&XmGXez8^fSQxDa}oMTw%{#dCjz6uZ7%#?l8~uf#wZVg z?KyE6z{xZ|$Yz)XL&~!5A&0YC+=cN=EE?E%l7{gS-A~D2HqrDzX;XogD>~l2E>Sug zFQglM0eBsqbc<=qF0UDuz6X41OHcpg`Lpi&S3R9`f410IF<*IACY__4hKZhQ%J%Ba z_gS_Q<_E9V9~l&Q7-*9pvp&&?MEccvvSaj3hpxKG-{UeT#5` ze;J8TJ`wamu~KkIz#%rj|H|D~K2f@`Hfs80Tsl*`#!)G@4~<;#R>VXO%)px~yrxdE zm4@D}Bg(&gQ&;PyiTM!5Is&N3h<6f5Y5leC&lv; zvgztVAxRZ5SVLL&d?SfonLqGGxrB!P6%(4ilar+fw{N)_DDp<-KU}^^_P*2ASy`E; zU0+`QmZ+)*(Ys7)T*usJk;X4hd$vFO&H9XapWZQWX_gwcQO+}Ykt_Ayd0oTcab(~< zGON$9pBD#3YPTP}z5igs{`M1dYwkR1p2|$z+M2^At72K}$dky(l3M3IiK!1gg$!ND z_zKC7H8r6yN2^jEBPo$`Q))||UlB&3^p4e@Pnm@x&40KE+--YhD8X>KdetO%VA^9`S45kI%npEY-I@4N0~WLiyB zR++UTq~-gK%(rEaHsP;_cs_sO_wy9Xa8TDjFoG~R|MqQn2{GC8HU6^;A{yckJvNzh zIo$nswuf$hi7@}qXHs#aQfi`IPfa{+8SZYe!1+wcifCBm@BjFvcEg2kv7v;R{cc7_ zj0E}-?X7Mx-iOk$^NH=E*|r-#SHVaqnWjD^Pv>jm2`{yT(!(0rx#}s4w=*EWHo=S6 zS1)*yFj?!2!FCmSpW&`X;P;xU{T51un?&Jqa3qY=_!^=@vd59;K9-hdYz5|0`H~Mw zQ;N_fez8US3pmy;AhnM;OCfm--nq7?(^C z{!ufScZT2(YRGEDPyam7Z;bC`f1Erm*`jR4P!I``f|T-Du>j0Dx+6F7(h!Vebv--! zJ{T(Yx4pZtSL7tXp-+A3-t`q(|B=hLyV(kYW8>u(?uRLFPnv_}BFK_&zA~Xavrg;W zk^7OZTtyIitL$)Xr2cK+efuB61jvrG)c#l4s!LcOihAPVEukASbO}3oQQ<3aeWh`tnQ=1Is2f7i^kVsG$aS^Dz{X+=sQWO)T!vAQE#3t@3{d^)UFwk`^H42Z#SXy zk+nVqRvehof_8n+aO-thshXxnynZaK4Mn8t{ZGOCj_4zlbn7K^-H8%!In6T94){nv zUaMv2@|>S-ic1y*yD>}+vU^@3?z_|*y0Om0sy$kG?~y)o?j9+)3=zsGNy?~ae1tXB z|Fc=wO!93f`6+0H*lAhWxmj@$+vE(yIpIbNLaNX0y= zJ5URSzNGI*jV-C!XSC=(vM0y1by&gv?^0b{gCjAYK8^e0XB8S+S?8j7<;I(f$e?=f zB|+-W?r>5zgU?lVg?h?A5(F}nczVf&O#9NNCLNS@WsQkHEP}0TW;3v|Vxgh+JF+;+ z4*8^BZyDifxfvKzCVHiGQMUcz=)J%yisgKVce+!xJT)wb^sy|)?-K68c(cZyp6Kq+ zg)}FecQ3t_lF|yMe9B4%&9lLh_z$98*q<|6Srzf?>=*V&N8|3JL<3&A)06y;q&M0e zQjFXErlPqy(#K;ZvsW}6R=(D`bkLjlr5JAB(-P4!wb9ZX&plhh?ipbB&i6<}$oC{JL74z^8F0>fQUqWK(0uGhLZZmy z6BS?d5w-iLX??F=)rW_X*ft@<>t-lY8FCM1UAlxac?{052&`&{rRDaht1Sjc6r$^e zPkT!$x9rx`$cC-QIWOKtnCuPPPgswYqE2)&=t>3zoWQ^~P0f0k?@c*DhXv|^qs_@` z9rIlON>%Ajc5-rX3v@R~O`dAk0jaOA$uP3A64m?S_+3zCZ>{rni3l=&r(D9_t04UEx@=2~inEdumSqUNF5h1JZgs$Rg};L4&$0la5+Ys(PNDnfw`9)7Odk|8 znwn}^pP>t<$HjpYz@9D8B6MEv%YyR)+va^dYpiY)(5I15#&Cj>2`#(gL)O%tL2PY-e&pn%}14B>*51z;q@vZ100u66+Y#gF_3F?cnPXbra zA}xoRQf)qsXltMSHpU^|!0~cxBnAS-pq7dL}D-Wh`Ya#Pb9Cnfk$%R$9I~C0OXL=bN>^E{@xT z&VB_Z^H-w@cL)~aJ7vnZwvw3P-s2oONG_+oQaQw?}rccCMGrpcxeUEM;S=TPS(f{4oj~LQ&+^q zWKC}GNrVvx%QPI+D)c6Ghq&95Q~DGIIYCb5uZZNtQk zrz2MPWKv7^94dlbgw$8WBEB=($$rIH52-)=aWYkJ_-t;BN`W-7P^ac&9KEkRO$VgG zuT^D_hN|pDKT}qsje8=EHf4pAE)C_WV(Y|mT&7@nVFP4``}gf2O3S5gVrDgWH$yqm_+55wm>Kvf^m#6mcN++t z(fm;0Y^S`SyyyK%NNpB*VRzwUq0WSH*Js(5 zA+xIUoNDm)SRbVj5g~)bU=jhxQEmD%?fGK^)I-Uyg;s9)kT(!hmP^))uiW}))MQiq0N7}S~%W~oAPP%TGENlW!& zAFQ90m`nKh%$5F~!kx~6_c7L!?F+kmr(4$~{o3&vvxdOrFV5&9v<|vh17GA`7KTkw z7?zzg{9cbaI9znp{^tCoKWe!D-Z*?|YTW)GqFiy&Zg>8>gj*>)@(8$RFeAJrKu>z{ z^Tn^Vq9Z+Zd3o;MRKhZ%8J&^B4ev8H!`Vi(Nzp#Q*VT}drK9B%4|n&%F3yh}-#u!D zgJqXUO~WjVP!~#M!u`EzC=aEv@$5;3M?Dav1OPxp^k2#A(`pOTXDwkJSPQc7TZ zFTz=(fiC%WWQqM3#S^(6vQr#3hvqR2#)|_t;TNQb$hklO`d1ld)@stdtN*OZZ18O4 z>4hnDzPyfSUtq%?xbMlu?C)b~ruJ}I_*Tmm>O4TjxDBy5M>)}M|7dEhDNEGQ>+Ja3 z;Req0=Wk@*oE@~@3Z0R$+}&xrt{EnVi`p|*VTI=I@Y~x+(dJoSRwF7aD570%Yj#@gHOT))m?X!x#jn){kqsT~_| z-n@@C3BpNv_K(P)Z_m7iL1HD9m6E8*=rNw>C-V8mgRxwe&oJIxlkW7c_d2%apU5@s zm52VV`Z41QN}J03eAV4P`aGgvg|2&95#*_E)s@>jlu_mH z47Y-UIyAm^X+5z2@fku*RqcZ?l7;3+JzAwkb2DEmew`i}-7eOxyK6Ra$ZVa3jj-Gq zJ7|pm>*MOk1xi;_B*k+wGCxbpn#&4ARB7)9b=YiLj57eQyjf-zOav^Oi<%ixQW zTpFVA80L)eEO)oOXHCP@M&vF%>Fax~jRg8E@$(~>5IH*sa+nGt*F9f zx;a)Bqf*29SB;YQ)LY;i@J)2dikYtm21Z0gVBwHS5;fVg@K2VRnlAMonMS~XZ>z8- zG!Cg2Wj{!hIC*%o+mgyz{wF0Lio*!!Bf$6M|H(=yZg^QKRKeA2o86I4wLC`k*p>{_0Qk7SQVqXJ-IR{)!#q(hWYwyAu*>khac@eOc=|ulBoE9 zJ&!izQ9?rMhc|9F_=?c6UM}0+851+J9H^WE|F?3g!n4ULiW?$*IW$+S2jWDX z=zgz|r=%F=kR%tA2zBzHMJy+`4>98{9)+Neh_H^(u( zw`8+P`NBU6mO(gM#fCeV=Od+m_lEO=bWQBggF7lOcEgCb9^47ZCV^QdZ{X zligut4c^bZ1Q3v?a*4BEtGM~anATXKjXN^YuJ*Ab6@Q58!W|_cJ>Bh7NJ&EOf^qFC z^EBdA+}m^XvC>@0*F4|YAAc$MK2_ge?k-T~Dg9n%?8P%aBk*$7&n;&P-s(%czUO)1 zj!(*thA5}=W^!ix%NIfSL#7cIw*J?c6)ppntLBm8GfRQwH`=i#wMP0n>P>R&i#c># zb1y>>RHatM1#c-r83c4n^a&KOvx9@B6cwYgI5L)$bg>XH=jTN?C-3t?xmz;o*^XVi zHsY|p;XYXt8(5ym-F>nAZmbS&A<(K|YOE*?5oCsA0(q30+SaWHZ`uz#{CakGA7Vv_ zOifXq!9_b6f0qo0Ks9w&QhIZ8%*(3FZwJwGZjQOGx$Y`ONnBj}v^No<%kg&eXo)DK zPadG0KL534IW<)kRlTOx_oTtZWRfTnG3KcfZX#zou z3s=>x#z2%YMJY#x8rO`E@MXrT@X}=U{OFPx4o=Kir6<)R42>E`+%+?1?XINg(y)^6 zi`{!)e5o$0LQvG~o;C!P}j+Dnb2*Km0qmpF%==a)p zx=u@NuW06m#ROZ2%AW$f-s;VzNyYt9Eu4C=Q#vBQ@1+{Q=);H4Zn>1_@bx9c;PKd| z4ehT?>2*%kPeW}jTKilaBwxGz?_wmIw6wJAjJNf)G+Xcs;1$UNr`x_B*c=vF5)2zW1``s7`M4R7ZEyd1D+)&g8`x<)x*O!& zU(dfLMEvWmrqe)A_L#cVWOjMkY?lWKK~AD=YLYVY8(_s-4TRsegCL$;idqawvTx+= zx5p-g(B*7q){%|YIN3dX_@OoQ#TyOJK4LE;W>Ntp#M$vb;S;^DqO9z)>=5rsn71$- z92y?po%zDm*g_*iO9`qc0h~xx46SPjM|%!V4r^FM-a8paUx}9BMxpMv3x2i}6*hKM z)Llpr_tTVy?R-eNiQ5b~0zMNEm>3%;z($IcjNYR(C|%#eiH>qOyUqE5$NEYnv9G)z z*JVcRE3Z>Bds87wQY;25M^k#$2Nn&183`F(#^CnDrJ!%cXs1hyUL{TrJ5P{`+huHj zx!pL8zK&sP{u4PdZ1nqgL^h#|Bmp@7QwF+I<0XcH#a22xrvTs)qmE|D<#a<`EMAJ-~IXXbB_x+ zUJ#Grrk~@Hr&z#CS)|pEQQa?$eTsAgLNl_hzx&}jbu7!ZD{gLlrRCQNkeb^9ZTk|E z>&Hh%#LsOXE;r)<;7mupH>jWqZIV01wzK}t&DDyE%Al=mRReUS;3;`)nldGtkpQV4 z3X0o+SrvCA7%(drCwJqkmD~dn9$V!dD2-70R2hSvt|cGPh`xIzE>0eC-X-3DnOwZh z%)I91RcQGQWVLcWFQTGE);)PRY}f#IE;aVqbw{}Jiiqt+z*6_#)7t0qnCW;Gm0LUC zollvWAAplZS=RpK!4Qgtd2sC|`?44}FUjUe(F2j}FK>UN+C1Fo53)wo$Q}JkrwDro z29(@dbLep#bJcLy(D^0`b`m}c8Oa~kp$E>hUILxSvM}zu%X#eN1PwCovz6?8UtgyW zRzB$$CkkXU5tT0g4$xm{KYy|qxp4&%Vl((*qyY?~zUyd$7arMuq6%Yq4Z3apn$+!1 zoi}^aMK_G`AFr)jhL%GGH8G~CTUDGavh>N55q5^+%O8|dtk0}?_!QPnMUJo3@3x{( znt3Dh4rHAzEm}stg{!envP(bHVsc#AUESOUc(>mUSY)dAU-W2o_trKJkj0lY+U@zr zpS8!=wU5?GBHiK%hPPSljCEwpa~5{$ic?5toA;!nBNgjO-I|6xSEa@4wDHN2|b z{L2^e`sxRrd|88QP7EnYLA+f5k-`4?nYWHc-pAYiiCW%tbcxV~;Nv@lj5SBLPqn`E z)rvN`V<`opLa)(qh)vmjwXP>Y zPHy_(fsD(1tE;N6o_3q#s-Jv|vRZ#)%qNWz+`m!!0`CHn9BIY(*^I;4b7+&9UP(`A za#2(m0e~?oT^-I=3s;f*{nx}fOcU&(wY zF%m(tkl84>fD*~d%9_M$cieD3lxrx#VQM zZ$_g7i!1>y`*Uc$>etC9jhdf7N;!C^N>v~Ip`;&wO=Rcm@8V;`kwp?+CHnv&@%Uxp z`OB;L0pa<6qP=HlNY*>2TSxCG+;=j>=C3{0m-;5KY@|OWw#p!C>bTEo?HlQHwSYSM zGmx+;lVb2jAR@RQy)xUr*k4M$*vfF-U;fb%lL&kp6s!tyqLckyT(|>4OhAG#Wlttf z$@^p>(&Nfa44JMQ(5m`8@t98DlFOT_*R3x%N>>#rxyC@?E?D-*j~`VAtMAZ9@}nXv% zg6{lE%LkxG14CBB-peMs=@#U54PN5ME>Z0yfxx%Pw-u6H`Oo5f=HVGj1#<-hv)mV2 zX!oOH>## zORSa>J~>&X-?aYgO#A!fPtZaqeMeJub?m8g@H(%%8Co^Wsw+E7smQHXnDpv1v=5<# z54@2)x_Z$He9aDFvA!I};gvZlQ7W@)^D9EzN%ucJbF;K!hC48+j3``}U!&kBWIQ?q zq!Q5BIp`Uo^;tu(d=90|pM|`U?jUA9>i^5Zp<%S9+J*Uw#t$0dnAF!Fh1En-0fC#r z@V#wkpUQtfToS6er{48TpM8kHJrdYJ^M5!$71eB3p!+GjUMW4noZz1}Xme2Gn zXLDb7W)bSr{;M77eeH05ZXgbap?xt%p#uFVCK9`|82O0&!E-UxG1NrI<-Wy}y*U8! z!#G+$;M`SHdy{hy#*f>SGOmM38miwZ10>7UX2AO=eV)b0q26PbtWL`rbdVY2ciopP zOw&u=eYf}Z!P3{`h~s14cOUg^*sBwM+O`(z3ZyyERq!>Gl$MIIW8*lkhB(!@gtQpE z^^iN7M_7?StVZGx_h}~`Idazg;4?hNgI>I^m)%3N2zO`7&{3sB{kUz zx<4F{jyXRxVWLzL?EX{Ule0JXG#NgI$w4ru4Z9dYzk=W*8t{TQl2@t|rfnHwh3RZW zKcl;lo6W#*JE`|F0cNFT>d+l7jt4wb;VtLGW6_L^EEsGU9?;Zy1}qx9O_U!aIm#2C zg(Cn0x^q7wsd7*;j2d z{WQkZ-m@BDGOm)wS6z_DBVTi^8}RycX3w*^QQZQ$!Q69seQE2ZbwbtQjoMfFwJl}& z`C%qx1NK8mUV!elHGiEU2wDMBWGCviJZSjBklNR_cn-Xd}X{1LiRf5In{>>#g z!U-ifl^vuuoTiAyIBN90bh|N8IH77N?t;$Nq;bfvpU((~ZGU9!MJ}Adp*qh1l<}V6|(j`^iTizu>l2fjx-*uokv|S1x)(N^@C1j$|U_He@kSX?^Dwkk~S{F$Ziy*W4A+)khaH$3*v9+ zQjwp0(!S-WHiq|Pmg4nIqlzW?^nIVet7~-^;*%}y73HlsSI~14fiNL)il+I+4)zv9{cd|?qgscv@}S> zBRlaue!14*a&c~_5(l0!1K>c(&j)Yfp*ua&1}M=Ohx)A7<7-rbl70F%TAUp*B*eFsbUjC1tv{o9 z6I+|y^goW=2U^eSfdREEUD$USyDY!86FK)c_Ow;Gjfvl#9<_a@VXW{B){O9f*DNLn zdCg$wwIub<&d%GOYdPj%V>2gvzZCsX_gw)MDvu0sA;<0T3u%0$riQ4}j@y~$h91{R zQ*uLynk0#T&`PE+%aBbm@D0Ta@$d`#bi3Z$q6`n9OpRGRnxn08r;^6-kx!N8uzncwW4Z`}-fMd5Y3PuHG`mNs+dbTF|%a z*R)o@M#AUk=XtoUS-6v$BmW1?f69VQ!E^5()kFOy!-YQ0-)rJ>l8?ccH!T3ShERpE zCji~+<;%xe%f{D4Ob=*crB{fvE6`q>85lGQ$B57^<6-39;xjJC6uR|c`59GSo?lZ; z$GFLN^C8LdjJNv>-A9C4S@m2 z_bxB}{ri?ypX33%EJ_l_ZqVkrjH1nn0sC8G=&!HTF@r_>0E>3T2>?8(`Wj*GdEV|{ zUuR^rZCXAQG&D&iM;Bu1;lUsO2=X^ohDlr_6O+>7>})y$&G^5cFZmgK8RI3C$EV2O z#hAIG9eE7xuUk*qXAeJjc7|wWx(Wa5UH<;;6WvSLuUg_6b%7G_$t0=gJV&lAzm7=1 z{IJILJ}FA#QgaPoNxtk6$aQfn9CnykSu0CR;hW#~pssi~3eiwgXTCK=eO9y3&-QDp zZfL9_LQE;<{G``g?RmNkHLl#!t4tfW@HAzKv$q7IbYcW$1~p>M~k`9ltiH01v20Ue|ShY zl!MCW)H05i{2@(NR(2GdpV}(2y83?iwfEd+h6&V=_fBq`B_t#mlxPf&QLL1G8@v{x z!Z@(sk|7MmnWJGorUBj)b3Q_3IxD6a>S%O>UaYE3Uff`Rx1~tQA)G|r0Q682F)ZG4 zF(?TaZx02b@=5)q;-+D_4kO8&2f~?xRo?d@T;=PfUhH_78fDu%~ zXzojWebm&^xaluuZpeAfSSaZPWz~MGvW;?w%G_JTk8+uMC01HS1~?2VD$R*nzG9SY z>Fx1}iCqkW*=d#GPShE}D1WWZgyafB>basOc#)Dl7;(V9a9fpsU zFk=%E=y8KNldt>X9sNjIea?JSgs!76fYg8!7~>io+g$X{CRUfOxem{uph^I)gP81^8#&B>b8K?%R3(jW5banTu5fqX|Md6 zxutYF1Gywdc5rMh5jQbg zX)$6-OxSc5_m^wYqt92$b2C>kRx=+P_C+R{E5lLyQr{D7PJk#@brmR0B&4A2WC#{feFaw2V0)E45NVa9SCy!Mv(V+n^-= zC&O~yhYX4+bB0abB;ArIM-`;x+~AiX`Az{UK|Q&jLf{EN#=ACnnMx$L2e zgFjRV7Hr0AB#M3c6ILNy;_&YqK5Q=hohChAOH;EyG5pEv>S|Zxz0&A?DV6?6$#Pci z3_38;l@L_Er&3k#Gu!OTDPKGoib1ByeI}X7hjVm@iI6*%6e+11l2-OJgK({!CPxK^ z8H@LsJ(LVLY zO%YQr8iLTAnt4Eekd_;d32r9A$&PFIJ_No$t8jEDK5{I{KTJ51|(1sUyb4 z_2=*VX@x)GK*<)8(*-wQZg})CJs8KQ7@8bqq~wRjYLZ~M#E6_=0?T1huR|}NVhvjK zm(KJZos<>j@()ldVxWo}7xNh?@W?>)sEholbGcvRj2}H92CKxztUiISQmoE$oi!e!=+hE@%V?Nw5m`JMWOQDkA3q-iC&o{iTrI}bmrU3t#FjJd?ZNn+Fu1M z?zO51wrEw37j*Mq_}>s(+zOX ztKN@tVWSm;mSamE`f%l((&khcEnhzU;6s_)|q{90)3MC=Zq7UScHYulFS<*4c7HXL7}uFK5`e>hc>*A71~`N|?DAv!BauwEX(_ zO0!5Yh;gC)>k~z|p)Ih2-}EALSw&yU78`6&5KJWyqXy%|iE9UHt&LVSE*o~TkRyYO=JFQRV#W`73X8k^{ERDOBzn0~lb zF#pkHxXxFjaK(n$X6GuZ%< zRPV+tw1fjxLdO8O`bCX?_Ic-n#DeNsNVfO$R%g!UFsb-E}?j3rm0 zqt|g{w$Yr7o|l`V6g&4)I=xpNQ}ZWgvM>w$w&pc^wn-#ElAf>!>qi6iG*YCQy|6K2 zxmlw@Df?V`U!)t-IbgiVC1F36l*C$zl_a`CDwUB0H(13po!BH?8J5b2vx8b5zVUml zv&}$e2TXjj;;jl!MXSq-*q0io{r%I?=;&x@Y;0^fgB2%S@SkH<7`5}S`^Xk9VFYIi zKtzv{^e8z`o|M=uFAPCGz++F)PEhshf$%%YhHD-DQ4OLqu2jj36fj>Wwq}e=hBu(x z$=cIIt6!uBOmKj{LTzkdrD0-X!u-jW4#*aB$L8r|C( zlIQ!>%lV&x9_PCIgO-LZPrWzyzT=Hs&uF5M1l^w#%>GdW!0O3zE!R2HAH+SqK_5Y( zzQT}>M-xT+k$NTRGBOV^hSqn9CT5RcclPaBJq8>w;5yytsH2=*tO^0uDJfs7pa6$; z(i%{0fH-9_j6_A&!J;dxZ^p#*wGgPKG&9;t(UbMH*S7jf8&Vz7kHX4=NmKcBlm+jSY8?Bhb5c-2h4oz3k_+ z4mz#c=T;G-wrqeiH}()aGE8po%qv4XT;qZH>lj;{I#QC=34nNj=<{nwBC3(7)P64w zuUV?-o0Quf2#&!jiMc&%LJ+!ZK5~jPJ;%Cnh|>z-A{}jycvxKAGhl1Bx2Ls)KK(S` z^M|_PPFwR2^-T}#I#48_gYk%$(IPe=VC;Ks00v(G=_b(s4|>Gj!nK-v1OT$|8URya zUPXgQv~b`q)w=F0-K>~>so$rB8!B6HNwGq)6p*ZN5d3J-{*+{5I9LwK2a7WwO!n@-hi z+|$iXuo+3C@JpCuhX8+3ZGP$TQW(4MDGv$czox%WmlNf1zcPjArLdy2V0?0oI{Hm0 ziv_F@ox$z?o0o?Ud_ZDaOlDk0*IU@fYT;A}f0Mt(A(QYL^*42f;l%f-s;IzZ*Oq$o z-%jK2|B$1QrT~=|)US*@B6L!$;&EKTVoIr__eL(eF!p$k(fdk{nlX~pPN8Ya)xA0l zJJZ~4p2?$L@3SYy5&Uu9?Py00nfb~`>xNuDR;D$MBZHkv4`1=($K$9qmgs>)q5;zP)~RyL)vg&-uJg z#Vc@kFsC7UYg#DfO$F|9&iEo0dCF+1v7&TmDIDnbsr50#s{G5^TSofH_RJTw@KjqX z?!VWo5|s~s+(xFoc|-X<4S89a<9;m_THDAEkEnp{hA!`)_iU~W%gZP9;&Ln}2~DRm zlL>u73xNc5XKwE^1n;V$B`0-o4LNXd}ftP!*F;M_iDCnyinHF(# zdA8sXUpeSp+ zh0!!HX%!R?${?I(WmPmWv7B$k6sNRExaF84bg_FE2y@cX(V&(?$uwZT3$#(6+FDUF zGigA4>W*~D#k_Vq)Q}>Ho{uI17E*RiSfVE(5@4or+Yf_52KO~ zs0b#}$DhUZK3jxrai_553O<8l;k1V-87RD|lF<+7r z)Ka55BJ7#gXwS2qhfG=7-a*^m7w$E%?1hEDG)V5v^WN95jbS?H!Y>vIM|P?OXz0S6 zL!HY;n!=}wgnyse94(||^bK6{neFs8xIiRheQB5URmqf};J&|dk8x(~VwhaY0*TO@ zqfBL8PQ+Cbsb?&w7eyn4EJ=MJ zIAh|reD>7yPtQEyV%_9oje_(TMheBSO4@A zL2r*Pj2W-h4V^R+E_O0t1jVN9LFWm`J080o!=RkFvkUAJ8X9K3 zqLrvH5bDM~y{1#|c8BR}(I27i*8Kcg3t{b#vQ81YQa+O~j%WDvqN1K4DH%CV7(q$^1`yel(f$`?ofjG!FKiA;tPaI;BoH(VS(kU@WdbS zY#dXQL6r(m?eDpXPm!F7yT~e~eYeNTUr=l_# z(RQV+r?9K$!d!>+KhFgXvgYBF)wz1R=-xITK`Ec((0c|yf@AWJ{_$|x_TV~q&lj=8 zN(`s9HUb;wW6U<4{5byM=pdu~$A7xaQU4uiq`pJc`pca+IkYGm`W=HLwTlV{2ZMeIXjliZ_xOp+~{larJ%wV@6)VRBjy94&kI|5svht2 z9825B3l<$*od0;*`*CrEZY~(mL73el_rCePUW*q*)H%xak6zt^TNy8zk@|K!bHR`= z05Pwrsjas5L7mHv(D+sB*0#WV%af(XIE_L4_C{8aAg2m$QF`ncNQ3Ju>45l65c+*< z@_vW_)jgx2?+0u5|7K){w%OI!iJhM}jVe}H>#VP=ROyKzyz<(dM3@t}WaFM(Ar+vRF=k z!Us(RjC-KORDup(cSo?H0-x&+FN^Kt^SguD?o_rbN(@9%T3X$crLu(@Y|IoC`w*0% zsf#cthEeLzNvB}_7RW%qpVUor8?ZN&WD-^rBlZN-dQ0~Y6|-kwP~M@V58H))E&_f7 z5^%hWfzzZn31ZV1Ezqoo8w_xWI9g98Y>wPZJ3kHipo?}sdP`Z&m{&EjUnZdyhI0)}`YF?8N^0+s>v}H;WsHM5{ zc_TKB19VL?Af5LRro)Cw|HP6dNcQ$~*uhA5x`5tE&oVUt6BEE&=<@RtwZ#gBK#;X9 zj*v9+gf1nE`tRjS7bV9eHR=87IHzu?m3EH+$93^*+yD8Hj$Ka#sbh4X{8`H!#M-KT zPmsD4-)nfg{$s4H>|pKUU1|BH1MQKAdlF6$)(Us<9;zAqwupXaJjdMWOIxA#?csw> zrc+3n%%n!k4wu?J-Z%y)B1GG`X6>(MFh1QeMvQVjFHNwA3pDLg3R=ta*FJFp80oKc)r#t)A(a8dt=$-~_73 ztKa{tige+;tRj6p|E?m#Rs~NjQBW1)Urby@Nd~2c&BS5BCFj%9>iYsHr(VCwdU0Wd z&kyt&>^Dd8-VL3sb_TMb3L6`Syw3(xiuMlkFN%Wz$gspNuoYs0YIuDf z_rL z`X})Lr?YBM^E2^|2I80-v;BCh!8(yrb6Yl5Y~Z?CO?)(fy}mt9_Cg71h>1(mzW!^J z#3Gy$5QU4~;eNj8dks-a>iXH4_SntV8KKtKhlc_{x@dTB90)wMo3wgw0^y>dBn|4v zTl*{2H~8MY%VyRhxSJ|<(tOJiJpz}Qm|BSQqpi@rV_wd0l?tiOFhAF@X$#G;ovTu} zLO^9A5(=xhYpG&@qI&wBG#fZ`-@e7#+SZnUiL|jm1I$$y<$LB z;4lt>JE{&*q4Lg0;uHGA*JOgU{>ykx*I>4(5kA!tqAUKx?CrbIUKgXZ&|CICk3m5t z*rel9^}V(DqnS-5Ab{=1lal{_2F5b^H+Atq9tPIZ^UcYg-d=o+zvK@9WBg6Qq^`B2 z8Ud{ph==|0Y4y~uBm)n7`CAUN`_hd^>l2lvL@=tDkQXTU_+-ZC9^RItP;ifpQ5ngFb7aSA$rr-2C&i&M z(>&9hpvuqdkgxJFxakI=YG^DN#y>Q8edqF0q~{UImj4OzE;+WA^ttuO7y0+`O0ge> zwK|9o>yWxkQ1PvI*>apuPvG<&H~7h_MPSy=s1JfQ@w?i`L=$nJJe9kVj>Om1bsdV4 zg~W>!Q<%ToHu2Hy{dhmCj`XjEIMGf+$2EAbe7UVrTg3coM-$z;A2&G~gGB0D_Z|%^ z!jCkiDO)RdUr4kYagBby?iKsVOTZMQj4)UOFooEb_VbrLe@N+k;IKiL1FBIA5b_@Jd`SdF!9& zqNptXf4xzEfy}G4vSEz>L;ud&o1E&!uz(q^Z*pkT&GGng@n&Co1orXagy-ne?t-#K zmFP|J*}G)zb=!0w&5h?4Xq0%n_^V%XZ&yg5CIcHDGSeETHB{%70Wz-hP{LdVU#H)b zN+g_=&W{?hr`?ON(AEE_6F9x}BM&B!b+==W|G!qzw#G1KDa+$$i?;{Ee}@c_FVv&gf*Ja&K$Ud)T+n{Sb*TUV}~4;5nIIcNS)=r zZ_oJ7kd2MP{wQAUhi5jsG$(tf8%sPmWo~9T!<3jZUxT_kI*=E9TtTnI)q8dGjmcLR zav!)cB>R1V*xHA2FSy6H#JDR1s=AJj(8x*$TCGpv*m~P zW&JNgcU%rcRsY#PY_}*Nlp|h>kQ?8DZu?bm!k61JRpiz~e}F)ubTxu^cyYHxOgCJV zWp@S=B;NEg`&ZICqA<{awEMoG94@=*pxAC7T9NjBPsrDIS<7@cDLm=`J_{jrs>z?bk3{m~voO}{8#nV{4vvP= z9?Zvra8mTN_si|qWo68`M#crv|F5;b49K$Ew#Q*WIz>uSLP;s5`O?Zlt@ryCjru_^(^tzw_*U_IW?Od=cQ)Qs}fzm!( z)azF(^?QMP*HtiD1#b=bbTEsFo}k+wUz$xXD%Gw9wASzXg{b{58m#F*isv0*CV;wUk%Q@X}g*03KbE0o5(Fu3=pd zLiLs+mLB3cL2@$!92a55$zjvvzG8I;dXymL>s(PIf{}Qz?7oR0mX#{9X<$Ux=DOwp z&jUF1a5}8u`_;37DafQkk(VnO=4HXS%&*@w`6^a!R1|8o*L^Y%InUmDKe zEjnM;TL;Y249;9}X^S?d7dd8iTgShi$-{Dy0ZRn;-MRe3At_=uCm9+HNSK&c>yh}i zmtZ*W!#uHQ`Sc!-wnpQJgudxQZw`e(Zw}l^4(;;WFa9wS(jDiuB@(=7)N)+orSq|c2 z6^z5Z54@^+cjXS4Y%kB0y6$+j^WBcc*8nmD~s z4Fct0>QZ*@*()j!y}JX)R6f@rHvdxh3zeA9f~-91IQD0HOuv zUtJM8D{lbS0&Oa^rz1sTVQ)7#1I7O=KQvr@ED_&)@tpc|ORF|7Z* zoCJ*5-Mp%l-T_xIErO}~4$8|0%jy2rC|AZhFkTNG4yJ}rSA(DZO`e4-F;%UwsoZaO z>lMHTXGn~0u;{gO8zxF8*=fSFtcyj?R8c=lg`Ar$ch%;AYj_SOHkD0$6BBBxB{0H3 z7Gv%+P6iUvr-X!D+~@Jjg*ngh&HtFn)p_6bPcQUk#;{z-rFdG;R)ema;^i6Sg?`Gw z709LNM=d?T|6ejslthh^l%eZLemDDi?V69^rlm>O_#XFnB6OF=5y=@U7XX^sF5{E9 zGVwCq*gO*r=e7G$pPiLk#t&tDHUl-E1`eN@C@DlUfM~YhgFzE)w!*Zo>qKPA24pNM z(ELp0-i7!zdAd4p)jl$cT)b>>Qw!xEZ2IV21C;u-7(5E)Lu+4qsOBfmmOGq&if65#(ecAFFLb+4M6daJn zppB~jvb2se8M(RPk4{;LQ%(A|NB7&s$?XtZ-UViJqhnI33y?s>+^3(qN|_^cKn4Vi zNAeuWt63;HxR#*i>w|+(5)UIhoCCS$=jp*V0xhA5lQLmt@f;sBV`4ymrh>EL%6_j6 zAnVzTIkoG~Fs-yb<#m8t0Pi@NTOBORE~wI4nh8v+7*pMhuNH(|wcGMuJ~Bn|F=Dn= zHS@N=<%+K@w?hS8qYsyDZKCgi{uVJux=+8gT%@_u(8i~&~GFLA#EAYlLSkwtg^S<_jCMdk6f8JU z@d$s_t2If+4Lj%3I!S?S{*KJH31Ag5ZnGtf+zyl2v z+{f$>3#w#9n*~k`Cge3y%dnpP{mGEqqwa9f{s#hQ;3as)RRrJ+S=;XJvp!n!=kLaH zJ{4IC#J?i_F2~5o1*T}vz>rRq58n5Hq0*M6^}RjicCY9v5XOiHz?-8~-^GwOc|2Oi z_IJI35VoOi_ongx9*t%b*cUuzHsb=FCN}S*D5vSaZv||Y`$L}FAZbJJ<#hE)2QnNQ z=be{ggB7&qW=3Xu@}b)R>GL955Z3iev-FO! zHV&SR;qH8uiyIU_944o7dS$Mt*Zw9J6qi;80028oPGxHa3pX|3-|0RiZrfj|E@z>#txU@MmIggR6u>EN9KYW>Jo?m0FRdK7MEVA^#BSo`KqMfo?>6$ylMjp z8|#U%9p)Rm|FjfS7seLe25dVC$B=8^zyQ5FWsk+=bCSK-#0uCi)N9m@E=05mkLH zdIC-sCqRi%8$b+<3c%!3GOIbOp+C=)07|9y@TbgBNH8!9OCF`eF;sar3q4}S|Cxq? z#eop{$Ur+6!cz=P$^xIXS#{1+Jt?!M6Eysn zLm65}(A0UjBwBKrkM$v*HV0m*7*tpzY<}N-4To69tDTJ}h?!XXoVFQpw@dFwu7Lbw zHUZk_UbC%P2Dk)o0U87Ia=(H&qqniK3e*nYa1nu-2}h18kAN*{SHH}AV>3yBgoH<= zNx=`s#OA*I>jGL}14ja6lG*p5(e8KgpX<9km3S&JdSkG=8uXrUneG zfm0p0JRZE>T5`-)>FaMZ2FfRjB2fxU_rVeVrZj_FMvqTeXfFw8TuK7Pr z&T7*sb|ym53J*Rza1NO&NNSmnEiZ+O0h`AHB*(X=rCVoC!21T+iv0j{VV(mD0w$S$ zLI!|BqGtTpRD7mvW~u>Cf+UP4w4Ys!`0wQ@T$xT4`ggaaPgL^d+>nzKY$hFf`GxO( z>Y#rUK;v=YjS#T__=sZd8qd?6oUdzk*|&3`QS>j{GG7nIugGX;O~A{D$>%!jQ^ao z-yjjrkcAeR9ZH}_2?w0S8fX&8|LeOI{8wvP(AoWwS!1o667{(7=v|ak5BShZ?R6G& zpPrO`HyreC{onY%JGML0<|+3Ci60mod&O+7j#oMjh8Dxb{#20)&Yb&wz$(WQh`E4K zM5C=C&-@h_pSL{;f(6?OT=IztqJWY;-(O)09(-alqrQAaRaH)I$gMPcel-=-o51xg zB<8D6%x(|UO9{SeYQ=Zc^mHD_SHFHng}%<(^35a*33&wXk428|DV&u-nk0-!PD>e( z&uQCPPN$a_JyEpkYe4qF!GeEr;%nN#kGERtx$Ne;!9x#Jr3W@OQ=kKYKg30{baBPE zt?2;_$i1fGXOs}PZG0dp0Tn!HIb7#Jm9P5+&X=>k zu1>GHv487qD1S5Gia6cSfoa#6>1mbSq1!hzXs=gDeik)($9ArR6-Y>im1&W!W%P%; zA6s0H*22TX=`>0Zk7QZ)@nyO3QM;P>E)uawte&EJEsPUCbHvIyDacEEl27I0=@En` zNri$EM*IN>9)_;pi}!-*X}zuQM@AKe!^?BjJytI7v0j52HdX`}0^nVx_b!k*i}Jk$ zA-u>lbU|*ZiHV9JZf_|m2Cs$sxf5)D--8(g@cT?1e%}{7iacaoD-D@W{rH7nqP6V2 zx^U-YWR0>XGL_SOr8^!c_xeW9f-Q9) zaJM}=(k_>A$TM%BE0dp*0*5603jz!b*jzrRqd`@ceXiti62Cw z+J61|?(ZLtgcYQyu9C~k_#D^zeaA`yrz#BR&2fLtg&vT=%>oI<`vvUI!!ycml+f3& z_jOZJQhp^ThCs_aw5E4<2cFRq&+{KOVsfcS=C!OEE zk%4&fx^{$Cxjk&Cxj8?(y55WSd(@Cj>-=6lU9F^vZtSWJMWnw^PaRzd4cvt74<%V# zTG~*iQW^D{GSy*Qo=GiA9$7Ytm6vG*+`tAsEbt86wMDzJm6$WWwHV%NfLN<=A+^m% z%R9&P^tv`rDle{OTng5%FLv9UYxJw;8}mmYD=UYLO{_u9jdbZRzJjf_z#t%iqf?gi zoa2Q_PA}>%SQfvuXy9h}&=Kmtuz;uU#ReDrv(e$^tVR$ku%j&^wnG}KM!W9#JZ2Oy z@Svb*h)T|yXqq3BuUNZomqD^R9z_9PE72%oL z_?8qL5Z8W{@*H3C{t%VOX>@n}wV^32#Ya(5V~OZ>7oQyW zpj1Tk(AwGpuydD7WP(jOo;6Kxwl(aochZa$xPJhqm65D%v+cnemp2}tA&!<&Nd%!P zQc|nw-q&yEs}-zgU+K$ngV&zZA#h*ou`{yN9()u0{uEeCc?mo;ns$Wnn+<1XdZ&9; zYi5KB8?B1J+7-11$IIyGBSZz=pAd&_<&y--kL8y6sp6A#AN~+>k2Cl4%cH7}nOIm0 z0&rFeZAC}7$>AtqyPtcWM+$tDO(Oz!VA_nO=kqm;!nXsTN5QeUSYJnBP`VJBQ^Iu+q8sJP;+HjNPg#6xd6A06Gc0 zzrHU&{w}xd<3n#gS^kBk66ZMcR>|{Lc=FdTL9@;r75EtWfXmZyj?tkyBsF5lDJou^ z?BS0REn$>d5-a{|vv#m2D=TqNi=<-UNv$mSG>WCO1A$9X^Js&M=}0Yzv`^^gDzLDR z9~K(k;&`1QoP5 zS<10q3^sQKx{kWs3vT!|ZYL5)2M4&hDv!S5;q}v9IrdUv`0O9~Y7WDX@VzSfD#|a6 zms^+K5s@pWim%4bSJNv>QiaHTNq2;3-z(e5tukB%N% z&RU+pJo$)${^XY|)w31r)I!S2oV9pQ=SMP|XyC)q)@P1^H+=J`j79$QD0$JYuAp~I zDeJ4FTR$efV0J5G$P+6isaDoc2B^~CSu8hqUMwf{f$ugVk=d!+;A}8PldbOL8N`=y z9xdN#lIA-aAui&ddr{ByczZh!EMe!CT91J$ah1iPohCN>Ta~qqtO6X#Rz`Hp0{LuP z>5;F^US5wcHxruV<75Zjf@!op-x_QO2EaZ)o2HGs;Pn#Yop0Dq zhf-yJApxQ#&maf#{EIiRLHP9f>2hCVq4@2)Q!Pu z$=(->^N`zhV&w5Z&K+s)YknPtpC}f}d$iMV-YI+obp9~ht+OwmsY6)ZJT3Q^5d;(T%M<3ECmzlMj0 zhg|;UaZ-bOQ(7!Gx-S*kUH7wxB9Y*D;D@Uq7jb&-d~*6uL$z{5RcOK%Q9dYkMWF}z z&0^0dFCo}BZ$y}44I9DK0siY)VSMnOVGs6ZPc+@rs9365Op%4KG9UJ5?SS7}!2R)$ zv#Da;9eQ@_RR9aiqk7~&7!*GJuuEU}3j2}1kFIjwP=Muh?s#St#^%G#PXrN>yLu-F z3=E9-l))IKWo{A`9212fhszLVFn23==1O<58956ryLK7|u#CrOJW5e=u+~?8t=|6) zTPugihd!x0jSdF7;oiAVAED5#^x$9ynz9P?eEIz;X@f75i|@0l_^_b^>XMW9Hv1di z=~1AE&P^TRvj;at$y1cvCCMN8XV(6qD(EPz`SyF-k%}J*Kb)WGaSDA)h?f` zK^CCoG|^VK-I)bTnq8=5|yr9Pcjd4 z+FLHqwN*)%MSR&LE#tvGwQ+hfCq|v%V7X=BPmDt#Y1QL@hDyaQq20l>;|DyVNwznq zx?4y|D50=Fom%r8elGctip<%?wbtetruu#FGqMH%^eODWKCM8xLcE$Zrwn| z1$VZ(-!=(+Hm*N-`o1!XG4pzlY47!%6KmbAS&vkuqVEnE0ZJ&X0DGIv;6cDQJM=Ig zsyIEYi)T<=D+I&;T4*Yx9d?dJ!t|DJh}n#?T^O ziK>f;oZNq|(ybg^bm_FmFRN`fW*xspYExI|el}pi+}{=9@G@6Qmgt+eSNvCHP?LZP z0%nAYpMQU&WX?7_={W;QH(r%dr7N9q;I;<(s-r0$e;?VG78e+2S-XOiEx5RpOFlbNi{D3 zA@CT&^K60k1B|m|JZkIgtW!MB1E#KVS?*HXKo=LMfQRxdlgBP=CE3Q=Oz(x~hmv}z z;|OzYfx%}!M45~X`t_=B<-hDrW5B_?w;YM*UKd(SS8Ki0M6&I!fjLdi8gmQ$2vm!} zfiS^BwcRyuY9Bie3OrpvW`q{!MNVU?#B!hDe+4DX7a(Bc#Vua=B{d=CR8+EJ4A>7O zu0TKX3`ReYGlnxwO(pc>@J082@S-sS)y3grgM*-NLQTzlwH1n|XBwBgBhDhG$b)6+ zU^L5TUam$ks-vfOP-CO-xHt9b?I6LpMlf>+Fkw~JeQa!9Xdq7=*wUi$KX}9{@AadwOkd5$!tdQ3HSdr?kAhkMUnYHUdGu zm4kw<(D9C(iZuW0I3G?7Xd+~!5}jE&EMKm%g6AV-sSVCe{`i|0%NXSQAnj#GvM17} z@sFvSg5d^p$xfcSl>S2eln=q$`80a-%!!wvaQ)5v{diwf|P1!Iy#Tf%0||pZo}C81GH{I zOtKK|ICiw@Ua*u)ty6T^C@hi4@iTC>{f;e|)J-<(P2pGp8&9V{ zTueUn!_9JOJE=Wh#sa&|5E9y%Ncl7G8O_qAYzW*8g14CbFUaf%c`6wh->#OdOeOIg zz#1nfDws1(9yGZKDxJ+Z#ae7(p-8~e9QrNi2*F19)tj#Hd{FFe%7Qpej$u(!s>(Mr zbaf>S6nfnqjuan;8mFv6vCGx{CUUaL)-X7u%rkyVNu`sbsWS|V=EYlL4Gq&7Xj>PX zs<(qOD0p3O?6V^LCr5Imp|%>|zh`>k5EHMk4FV?@d3ahpB86!Z6g3@)7dYV=EaRpo z5y>p3ys6UiA6+-&j1wJKz905gQQPcIF<89lZ76xuJq7h6q#9F6|I6oX5XID8y#*w2 zg2)Of)THA`{}!Zd>|$3SNY!fUK}~>02yUZJej9Y0NZPIXMa9w?xl-0W?A2d(kzlJDgm=y$x|U;-Gfw$yQE6m<6zn`pgv0NQdR&9+f@Q$J7J=b1^4 z5cy3LJ;4^jKQg>+c#(SQKdH)$mC>tPuNs6q)9i&ZK=*X{nS1_F@Us#QwZ?W@n%>T; zSdzgvCtE}#sYMzWy`PQWc8w)7`nxZ2yF03Z3b0V431|vIqx%jh5Jm7ZG)@$?NmG+d zaS~Jp6lCI`EA{=spcW#ldfL?k-T5IEKbsr0LK6y}P!{Lp*n)6QO!vMrDXsT0zji#F zJ)!N2l8OmRrqw$~0`G-XBPPjlD2-SmF9T{zrbjK?}rb&a{2#mC3xr>k;_*>$FFl}6jqguG`kqjM0o>u4rGR&#?E;jQ#L;stRxUsRo z=HrL>v9ZJ209CPcX+qI-$0slAH?(!s6me8#z?v_nJgff{hwxuOE{!TKKGuocax*`o zfwPN!p@!HPQan(#ey=poX1ZQ4MdXsXyIi-%OX$Xg+Wx)_@2zr(}XFM?2-|U64r`ZH@sYC52yyLVb{uR`(Z1hcv~=hmkZ}xaf{A z*4nQ>n1Cvp^#1O~CF~=Kqyo(QetK^Az02Dt;heX~Uleu1<9yofGdGB2ea<)@F4uiN zpgSl%KaL`F$H1ubB_@w@7nH+Iiv5!&y@kF! z%_ILj=8M|jhX_H{#IUdma~I7NY|2Cb4>Mdc3rEdSIXt2$z-lksXZ8RA{!%e4qTKZE zm&k|pE_;2809*Yi$%nsX`@~qYvs1i&V);r$^d$p~B1t11Lz8{xd!m7>WUz}HDy?pw zUk5#*z?L2tlB*6^v~B&V2VI`U7@83}F2Ds{&X2oT>Eu~rqSC|PFYE^A6<)isS4vwJ zT+eRm?BKnV)LGdpXkapmZ*{97|D%Q6S<_8^>Z2p9tr^1?IbVhVN<&`0d&*DCt4(kN zf$Y=Ji(oMK?08d`eY%5k<)h6BZCU$}c6MqT1iNGCx9VP4>(<4o0B1n0Moy*Xg{R{1AP6~rd&KDho=20`}RrE_mK8dMdZ&RJJ=uWnYL}v*UH@-KEBg- z%4F3LLxenVqlPk+oK~fo`{9DK>9+VW0)PYGc5;i?9q5yV$4xa~$7BY9rw%AWe)oEM zYruL4L$@Lk#$pvz2~4%?EMHMQ$Wq05J>gsy8=N*N@wBdmaq32p6SN&qAw~1=Pp_)s zse8SPEq$~@j(ES7!1yzI(Q8Avw}>3JzXy&(g4?gMatELZoa-;%yx9ejVjQ3~U^$Cj zK3v{NDS}49a0Rb{GgDo{HV8g^v8V6Rzt>wr82VKWCA$o|b(l}N${Ak+!6+hq0w%+s zn3G{z`$ZQkY{#swu)z5i=O(?DVKk`Gbz6xce!j%i#fA>3jxF%~Ai zANlRK{FBc+!*~X-boz6ny#94AwEjL9OcNV zMo7=$-9Jjp-)!YdT`*uQZ6`hs8x0#puxD7KvHyIF3NPa81X>*^f5`dr^@=hG3BFH& z&UK+`S2+u)-f0#`{zU`KJo)05hx;28lx?*)a-Y<5TdouI>&kh!-B+*_SRI|5&=G%K zgYt~sMky(gnWE4{#*`Yui*Gg&TEGAv(`t@)w$Ux7-sxHHAn`_|FjQzL#Z)PtfU{5o zeJv==YMJ=?!}$-DxMC9+BO=fWI)GRIA&(1#61qbA()%^Uq@K^942!F2ieHT)P7e$O z{Hx)#ZBJbuZ8n-&N_u*5fkh4r7njjQ{ymUK<(F6}SH4p7oVQ$Ub49+`8Kt41*a9`? zV+MvHtGUX|M$G^=GEdBNfGch;80YJqnp;}%+8{SW*qr_NJXO~qb*(-ZiUkL*4G~H8 zZMO8-RsPJae1}&4ry?6auh=?NJ|JxYYSKkyjyw7)L-WJ-4G-f%-k5x_C@v@sXmDo7q5_B*$m2666cTXk$}jHILhq z+^`1eXmoeHCl&fz8PUGfQA|9aI6HHa;Qv55o);;OkAnP)|Nc@x-KY8Unu9&1|BE7= zDGd?!z)uZyk0rOiy|J`Kq?90(dMvnR{=nq$Y^PJRjBk~pJaF)HSTh!RtSUp`JC0i) zFf@8USyZz}ptkiplV;lL_Yn;|ZQ=9aCnO;WK^}Og8%trq&35M7n>`Ex9SkFAbm`vj5*S215(J8Z*N82_63LPLa|VU3 zYe4D^254M+qo1q5h2}*3Y`HE(+)&_*t$>SxGW_yRNTm-nZz`34eyq0N4FC29q1Qw- z$j@)7vIvfPXf(UXm@o6GU8+n%pPr9b{J^=bR2Z(D%@Xe|sCiq{ItW_rgnC#Hpwi@2 zfseCX4{}F-nQhuH$~(XVR)OTing8UC651^GwF@5UPan%d(mg{%Xj0Ff!PDvD9{!ts zXXeQqtl74ee3dg@R{D2CIvps1(S2V=DhZ8t$moz^n(3AkUi}AUOrXvMbj z(^mpW)(ed!*3SM|nIH5H`K|$FQJpAdL+@R_zQsMcoYQn@S4?jwnl_V8c zl^J)m#+-tT-BP#f=}G{GV$l0AJQ=z?s$$gq%4DwAYm#dV#vA8@v^IT*TZvNf;#fGW zxO_(k(}>!Q6zrr1?aS%1ko25XjTr zJ)HYn3b5#Xr7CxGPXAp)kdow2g#$D{U+`)n3yLdC&UuO6@|m0M6{Af#Kuv#ZnSq{YOaw>q6FKE%~)k;S=Uz<@Y)7gpyDxj*K%7vZ5-s-ce7mhGt0)%jqdGS zkch5w9d?qlh%pFXFd=%lzkqnE)XZq|@oQ`gGa%VBJ}EL3w7YoX;%Z0B4+`at<*3*# zO%p}ZLZ9{dN`DU`x%P)UK2f_9_90s5%oli66SKR-kcv$SQV&?kz0Ze_a?Oya85&xx5Z6`39$b1@dY_G+=9L7{ z@ZL%OppF<&PJJH+nyd(D@Mj+@6n%A`$l+kX0jDmu9q7cb+XX6nqb5=CEqhZYt3Pqw z(SkZ^YZXsPy>P$SAV4FJc6>)cf1XkWHu;B!`i2n|<0%>4v?aMc7q?XgZrrKoslrm5 z%83<(?#y#6$J31<3Og=6B2$>3tmT4gVC3bWKorRt&$1MtTm&vRpJ`{P?$3yq3xM8fu;GKE!hB>sPRx*syP2oVLP( zyD)5M-!dyR+J8a$qE1IqyFqv4QdRg}-eMsoFRAqv_w7P9%iLvY%7l;De))0ASK?j7 zl@T3jLg6dzETmf+a>n*KC@&Ro0TH+lpaj6sayO}B)ZqQgmoMX`0BwIy$gw0P7qLH{ zhjPCoaQ=D`1<$$1`)G@|z+_A_v=iDwfVQ@i7_Xc?E^SFYo6=gPZ62n*knZ z58^`@qMH7itA0!`i=)6pz-F&iW)MC1Qv8QliDTx(4{a2Ns~;-30LyAeBvYiq_wW32 zh`jfR!wbV5@xXy~jGldbEh}?p=Nc>_7bEZZ0fP1$6Q_bjoWXwX&lwM~d;kqNK$!2q zb;KyJla0|d(vO|yu1<-*7&d->fou!vk%IB@jj+&H|L-m09+o)wa;RCU`B_=&m`z$# z5Yl9~5A#9DLN88ZkQ=|ra!1sjr*o+w>iOflpYPX(Vg>u9_Ka8TOUaqiN6W|ff%mfQ zC5N2#GpKYyvI+748I1zvJ2#9A6Y7xT?)>l$l94Lab#?obw0dj4+vqJBs{{%N2BXt6 z>Mcn938?<1Yhe-Ph7Apq-;c6b2=~7pg}E|nC(ZW2g?IZd$u_=CA0|1W=num0+y_V- z0=fUL*A7+8{&LmwQObp-zoYdm`JtDm%_@m5;D9Q4z{-Lq%gCRXx&$B7T4o7Z?QFDw zOpM>52>I>}K_WwZzojI$Js*eL+Q47@pTEY&H-~rw2L+LJI9gly9MNewOGsdNu7w7b zlng;b>pk-<8``256&DqK{9)lQdS83STdQNr*hedT&d+fenFbMlxF6BsRyGADC(}V~ zuCKT6%oE3nxLu9S%tZZol|4y2N(K@$%J1IEYLr7HpwDh`=;3}SWF_737GA$|KEDh^ zS*OVbS0jU7Hiva%fUTV!u=z)ei@cqO^}h!hQiH#*=!A{?PWBMDOKSTsFeesy_N3Xd zU_j?gx5b;9X(X9FvKZGYLa;mB9@7F5ef9`ktPN4Opn;5ZDv=ypbF!n2k7!0EiNCwO z4Nc1gfG|;f{1(tsz4_AsX)O|zW|g8kpxfKqYj)c6bb39c=yeXdMc@XbTpOroT;=7U zVfur2IGvF_|A|%UN>CfG#8#rDnx>=lb=W+P2)Wfv>2oh3oM7LtkhDY93yDvbdY{TK;I~0 z1Ag{c1;}jc@U3Fl&r1gV_>vcQE^d2D@t;P2=zEXdewU4B>xgQ1%mOUL9 z%x1yaC5tmm3OXH7xrpl1Wtmv^xlQ8$wo|5270DUeUX+zVJ?770y>p8E25zHz86}^O zaD#`pt@ZVl!xV)H>`i|?K5O<{%tXiXvZvVAQ!ih>oWga;aX8klGbDVn%-ejcu(AI5 z(+^fn&GnsD!l)FYqdvM`Qld(+_yVK6e39ULnj6P7KJE9$qG=(1G=_tyaTR~m88nR+ zYIBLqt>ts#s@H%){2ws9!kU!h@M}d6dwoMS5+;L#n9-u z)rl0T7{;fAw8MQ%Fk(o@YS50Ul2{nd`yxD=vk=*pRuUM41s_EWlWB{ zQa|7(fnv)>^o2_2-g>XHK9LflI-h~92Eu_^43>MdbU+XoQYyX`|mSlIb$N}QD;k4nc z4Ovi^9Pgch#)m_WiaeBAc3_ac-6rOB%vMh>Fk)y$3PJRs(&Ft7svQ4EV5?pF&aGRkVuSnGMHuWo2ljd z^P1!1FNh$$&VbCU==~?Z3SC70>s0<)yNe;D+I>93mX1U}NNQga5Vhy&(J; zI0`s({%(oi`4`c)*?|1F3PLYsV*E3(e!~jzdv=n5T4`%DvVv6JJAhaV6G7&% z#Kpz6gd{kTXR_RyM9Q_A6=h|wwISK(`kzk;NyZ}x|9F&m+UTJOLK~a#f(o1*u@vsA z`}>=pj4xA6Z=aZ0N>n+}W2E+}f|Cr8tbKVwvfe<6 z$R1N?d;R_g%s(HjFlq>(ftxG0#6ofIm>3H2h#vxGiWut&;Q08XZ{YYm%iKr{_mv17 z3N1bl<;B|DH#Z(+p6gvaK#~c;6i7y}Jq__F$#GcVwmnSzSp}{XE*5Tj`fDIk1xBHn z^6>D0#0mq<%ETv&cD>(8{3e3ql@oTpbCeVsZe~3=xc=We5leT>1-gcLFjbQdcT%L^ zqUY)PRMJ#YaT=52+SR?9@Kr}-4?;dvk2;W;Bd(PFL)p-(NQ35@Sm8in8wjMI-Vb*N z!Jl5dsJpwq5*39#`?(C7LMz4E5*ts+Q$Z7th_C(wD>UEre#Ib2{P#d>O39Lgwej<6 zJAfLM*7^2QOD>L50sZGfU2%fO&A~h#4V?Ohess z36cW1>H6)5;oi@QpD?rY-y1i1xB#{kY%n0H@cWvn<2+k7Vg)hSb8HT(LxfEc# zA_yCerJi77K30^5CkI`{^0%lxeT8b~Sd^$j;Bqh<-zr~=)1A@KL$fF_<>a^F$G`Tg zsPw~k$~c%YVx@e5Jj#fo1el&H>Tv}Fk-{p2fo@>n$$O4neeb$rt9hzcp}42mpIs;a zqKqj;hK5{2p@mQ@Lb6n-LtzE#Pf*56p#t{CCa+&ZAwIKyFM=IqfglE-hld)*19&x| zDwrfni_t6^*(1Q%Wq!ka0Hz}^%E^n6#iLO2&6NYhz!q&YlK;DD2R;q;+H3|{NqU}K z9t(Vm6cGh^2WSjvp5z>iWcv7v*Vc2dzxT^6mjP1ABklPV$(H2ye~3cIh;~&yxtV7J_KZy<6%-Q&Wi4%-jrYoG$4 zn_PD?xu1F0l88PBoL9hK&g(5|)BeW@wAn^3g#GQ`lF!(5NB?o^*rDm^RLQ&yWib2L zq{uG8Z94oh8zKM)^HQH2YMu6a0O2JR9d!@nlysVYenM)qLm=!ka-QRbeu{)_9j|tR z=c$V20Cxhpri-(+=x`q3DU6h;Aw1Xz2oFZI8;e$?F1Rd;MsOP`%w6E98VU46|MlDc zZ|sm1L$#d2k^Jgnu3}rwwiVF-Wbi~V8-ntW-e!!5s&vLQ0`UDlxTK+XKVG5%_GwBGy!XJ~R@N%S&gF?A&Eax`3Lk2l@yAl!jVf221J$-Q}|D94vg=)xZ6(kJKzoMW6C7UuVNM|p%-v3E(okY9gv#;_r?srmBKXZNgd?Lewxl{EL z89?Bc`}$I~qPHOA+3N6~1^@}Rq&5)qy85Q%f_6XPI92R#*23t)(YW+&{infm3W;;L zfba;kOcN3N@N)Mipi_2NiF8%O1-bm;?x)bNOfr$%wKZXni^F#xU*+bC3qwRk06oXS z(7L2>vpxA*31nTn^o{7dU0T|{>oWqUqRa0bzZi9pcFi$C9&I|o<Cf&M$X zU2#Sp0Z2sKgC4EM-ejL-xzFTs0IC3Qmeo|5;@|hQBkq%{f2VfJf+(HXHipSQ-v~w* zv{60T7v)L;XQ~@MH>zWw9+GSd=YXq`Ehh)ZG?=!TT|i|2XV%8OQ=n{mUFpmJ`Ms|b zrR#bQ3kyrNN?zV%X?R>@`+Q37L<(D>KfQK`4ec%|8QHt`pjq}BUq0V|f(4s^|3AP7 zT*_21QuF^4$!ziiY$9W{XWiGPeD@nH1^)i|(giRM%HJQE2moHd@BRLXCrEg}U?;YH Uu`S0(0|kDh#N - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/promise/etc/promise.urm.puml b/promise/etc/promise.urm.puml deleted file mode 100644 index 8aabc1d2a943..000000000000 --- a/promise/etc/promise.urm.puml +++ /dev/null @@ -1,79 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.promise { - class App { - - DEFAULT_URL : String {static} - - LOGGER : Logger {static} - - executor : ExecutorService - - stopLatch : CountDownLatch - - App() - - calculateLineCount() - - calculateLowestFrequencyChar() - - characterFrequency() : Promise> - - countLines() : Promise - - download(urlString : String) : Promise - - lowestFrequencyChar() : Promise - + main(args : String[]) {static} - - promiseUsage() - - stop() - - taskCompleted() - } - class Promise { - - exceptionHandler : Consumer - - fulfillmentAction : Runnable - + Promise() - + fulfill(value : T) - + fulfillExceptionally(exception : Exception) - + fulfillInAsync(task : Callable, executor : Executor) : Promise - - handleException(exception : Exception) - + onError(exceptionHandler : Consumer) : Promise - - postFulfillment() - + thenAccept(action : Consumer) : Promise - + thenApply(func : Function) : Promise - } - -class ConsumeAction { - - action : Consumer - - dest : Promise - - src : Promise - - ConsumeAction(src : Promise, dest : Promise, action : Consumer) - + run() - } - -class TransformAction { - - dest : Promise - - func : Function - - src : Promise - - TransformAction(src : Promise, dest : Promise, func : Function) - + run() - } - ~class PromiseSupport { - - COMPLETED : int {static} - - FAILED : int {static} - - RUNNING : int {static} - - exception : Exception - - lock : Object - - state : int - - value : T - ~ PromiseSupport() - + cancel(mayInterruptIfRunning : boolean) : boolean - ~ fulfill(value : T) - ~ fulfillExceptionally(exception : Exception) - + get() : T - + get(timeout : long, unit : TimeUnit) : T - + isCancelled() : boolean - + isDone() : boolean - } - class Utility { - - LOGGER : Logger {static} - + Utility() - + characterFrequency(fileLocation : String) : Map {static} - + countLines(fileLocation : String) : Integer {static} - + downloadFile(urlString : String) : String {static} - + lowestFrequencyChar(charFrequency : Map) : Character {static} - } -} -TransformAction --+ Promise -TransformAction --> "-src" Promise -ConsumeAction --+ Promise -ConsumeAction --> "-src" Promise -Promise --|> PromiseSupport -@enduml diff --git a/promise/pom.xml b/promise/pom.xml deleted file mode 100644 index 05fd4c3ee2da..000000000000 --- a/promise/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - promise - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/promise/src/main/java/com/iluwatar/promise/App.java b/promise/src/main/java/com/iluwatar/promise/App.java deleted file mode 100644 index dd40ec15b450..000000000000 --- a/promise/src/main/java/com/iluwatar/promise/App.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * - * The Promise object is used for asynchronous computations. A Promise represents an operation - * that hasn't completed yet, but is expected in the future. - * - *

    A Promise represents a proxy for a value not necessarily known when the promise is created. It - * allows you to associate dependent promises to an asynchronous action's eventual success value or - * failure reason. This lets asynchronous methods return values like synchronous methods: instead - * of the final value, the asynchronous method returns a promise of having a value at some point - * in the future. - * - *

    Promises provide a few advantages over callback objects: - *

      - *
    • Functional composition and error handling - *
    • Prevents callback hell and provides callback aggregation - *
    - * - *

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

      - *
    • Count Lines: In this example a file is downloaded and its line count is calculated. - * The calculated line count is then consumed and printed on console. - *
    • Lowest Character Frequency: In this example a file is downloaded and its lowest frequency - * character is found and printed on console. This happens via a chain of promises, we start with - * a file download promise, then a promise of character frequency, then a promise of lowest frequency - * character which is finally consumed and result is printed on console. - *
    - * - * @see CompletableFuture - */ -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/master/promise/README.md"; - private final ExecutorService executor; - private final CountDownLatch stopLatch; - - private App() { - executor = Executors.newFixedThreadPool(2); - stopLatch = new CountDownLatch(2); - } - - /** - * Program entry point - * @param args arguments - * @throws InterruptedException if main thread is interrupted. - * @throws ExecutionException if an execution error occurs. - */ - public static void main(String[] args) throws InterruptedException, ExecutionException { - App app = new App(); - try { - app.promiseUsage(); - } finally { - app.stop(); - } - } - - private void promiseUsage() { - calculateLineCount(); - - calculateLowestFrequencyChar(); - } - - /* - * Calculate the lowest frequency character and when that promise is fulfilled, - * consume the result in a Consumer - */ - private void calculateLowestFrequencyChar() { - lowestFrequencyChar() - .thenAccept( - charFrequency -> { - LOGGER.info("Char with lowest frequency is: {}", charFrequency); - taskCompleted(); - } - ); - } - - /* - * Calculate the line count and when that promise is fulfilled, consume the result - * in a Consumer - */ - private void calculateLineCount() { - countLines() - .thenAccept( - count -> { - LOGGER.info("Line count is: {}", count); - taskCompleted(); - } - ); - } - - /* - * Calculate the character frequency of a file and when that promise is fulfilled, - * then promise to apply function to calculate lowest character frequency. - */ - private Promise lowestFrequencyChar() { - return characterFrequency() - .thenApply(Utility::lowestFrequencyChar); - } - - /* - * Download the file at DEFAULT_URL and when that promise is fulfilled, - * then promise to apply function to calculate character frequency. - */ - private Promise> characterFrequency() { - return download(DEFAULT_URL) - .thenApply(Utility::characterFrequency); - } - - /* - * Download the file at DEFAULT_URL and when that promise is fulfilled, - * then promise to apply function to count lines in that file. - */ - private Promise countLines() { - return download(DEFAULT_URL) - .thenApply(Utility::countLines); - } - - /* - * Return a promise to provide the local absolute path of the file downloaded in background. - * This is an async method and does not wait until the file is downloaded. - */ - private Promise download(String urlString) { - Promise downloadPromise = new Promise() - .fulfillInAsync( - () -> { - return Utility.downloadFile(urlString); - }, executor) - .onError( - throwable -> { - throwable.printStackTrace(); - taskCompleted(); - } - ); - - return downloadPromise; - } - - private void stop() throws InterruptedException { - stopLatch.await(); - executor.shutdownNow(); - } - - private void taskCompleted() { - stopLatch.countDown(); - } -} diff --git a/promise/src/main/java/com/iluwatar/promise/Promise.java b/promise/src/main/java/com/iluwatar/promise/Promise.java deleted file mode 100644 index 6b321e1962ab..000000000000 --- a/promise/src/main/java/com/iluwatar/promise/Promise.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.promise; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * A Promise represents a proxy for a value not necessarily known when the promise is created. It - * allows you to associate dependent promises to an asynchronous action's eventual success value or - * failure reason. This lets asynchronous methods return values like synchronous methods: instead - * of the final value, the asynchronous method returns a promise of having a value at some point - * in the future. - * - * @param type of result. - */ -public class Promise extends PromiseSupport { - - private Runnable fulfillmentAction; - private Consumer exceptionHandler; - - /** - * Creates a promise that will be fulfilled in future. - */ - public Promise() { - } - - /** - * Fulfills the promise with the provided value. - * @param value the fulfilled value that can be accessed using {@link #get()}. - */ - @Override - public void fulfill(T value) { - super.fulfill(value); - postFulfillment(); - } - - /** - * Fulfills the promise with exception due to error in execution. - * @param exception the exception will be wrapped in {@link ExecutionException} - * when accessing the value using {@link #get()}. - */ - @Override - public void fulfillExceptionally(Exception exception) { - super.fulfillExceptionally(exception); - handleException(exception); - postFulfillment(); - } - - private void handleException(Exception exception) { - if (exceptionHandler == null) { - return; - } - exceptionHandler.accept(exception); - } - - private void postFulfillment() { - if (fulfillmentAction == null) { - return; - } - fulfillmentAction.run(); - } - - /** - * Executes the task using the executor in other thread and fulfills the promise returned - * once the task completes either successfully or with an exception. - * - * @param task the task that will provide the value to fulfill the promise. - * @param executor the executor in which the task should be run. - * @return a promise that represents the result of running the task provided. - */ - public Promise fulfillInAsync(final Callable task, Executor executor) { - executor.execute(() -> { - try { - fulfill(task.call()); - } catch (Exception ex) { - fulfillExceptionally(ex); - } - }); - return this; - } - - /** - * Returns a new promise that, when this promise is fulfilled normally, is fulfilled with - * result of this promise as argument to the action provided. - * @param action action to be executed. - * @return a new promise. - */ - public Promise thenAccept(Consumer action) { - Promise dest = new Promise<>(); - fulfillmentAction = new ConsumeAction(this, dest, action); - return dest; - } - - /** - * Set the exception handler on this promise. - * @param exceptionHandler a consumer that will handle the exception occurred while fulfilling - * the promise. - * @return this - */ - public Promise onError(Consumer exceptionHandler) { - this.exceptionHandler = exceptionHandler; - return this; - } - - /** - * Returns a new promise that, when this promise is fulfilled normally, is fulfilled with - * result of this promise as argument to the function provided. - * @param func function to be executed. - * @return a new promise. - */ - public Promise thenApply(Function func) { - Promise dest = new Promise<>(); - fulfillmentAction = new TransformAction(this, dest, func); - return dest; - } - - /** - * Accesses the value from source promise and calls the consumer, then fulfills the - * destination promise. - */ - private class ConsumeAction implements Runnable { - - private final Promise src; - private final Promise dest; - private final Consumer action; - - private ConsumeAction(Promise src, Promise dest, Consumer action) { - this.src = src; - this.dest = dest; - this.action = action; - } - - @Override - public void run() { - try { - action.accept(src.get()); - dest.fulfill(null); - } catch (Throwable throwable) { - dest.fulfillExceptionally((Exception) throwable.getCause()); - } - } - } - - /** - * Accesses the value from source promise, then fulfills the destination promise using the - * transformed value. The source value is transformed using the transformation function. - */ - private class TransformAction implements Runnable { - - private final Promise src; - private final Promise dest; - private final Function func; - - private TransformAction(Promise src, Promise dest, Function func) { - this.src = src; - this.dest = dest; - this.func = func; - } - - @Override - public void run() { - try { - dest.fulfill(func.apply(src.get())); - } catch (Throwable throwable) { - dest.fulfillExceptionally((Exception) throwable.getCause()); - } - } - } -} \ No newline at end of file diff --git a/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java b/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java deleted file mode 100644 index ae90a927e2e6..000000000000 --- a/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.promise; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A really simplified implementation of future that allows completing it successfully with a value - * or exceptionally with an exception. - */ -class PromiseSupport implements Future { - - private static final Logger LOGGER = LoggerFactory.getLogger(PromiseSupport.class); - - private static final int RUNNING = 1; - private static final int FAILED = 2; - private static final int COMPLETED = 3; - - private final Object lock; - - private volatile int state = RUNNING; - private T value; - private Exception exception; - - PromiseSupport() { - this.lock = new Object(); - } - - void fulfill(T value) { - this.value = value; - this.state = COMPLETED; - synchronized (lock) { - lock.notifyAll(); - } - } - - void fulfillExceptionally(Exception exception) { - this.exception = exception; - this.state = FAILED; - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return state > RUNNING; - } - - @Override - public T get() throws InterruptedException, ExecutionException { - synchronized (lock) { - while (state == RUNNING) { - lock.wait(); - } - } - if (state == COMPLETED) { - return value; - } - throw new ExecutionException(exception); - } - - @Override - public T get(long timeout, TimeUnit unit) - throws ExecutionException, TimeoutException { - synchronized (lock) { - while (state == RUNNING) { - try { - lock.wait(unit.toMillis(timeout)); - } catch (InterruptedException e) { - LOGGER.warn("Interrupted!", e); - Thread.currentThread().interrupt(); - } - } - } - - if (state == COMPLETED) { - return value; - } - throw new ExecutionException(exception); - } -} \ No newline at end of file diff --git a/promise/src/main/java/com/iluwatar/promise/Utility.java b/promise/src/main/java/com/iluwatar/promise/Utility.java deleted file mode 100644 index 41e07be4593e..000000000000 --- a/promise/src/main/java/com/iluwatar/promise/Utility.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.promise; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Utility to perform various operations - */ -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. - * @return a map of character to its frequency, an empty map if file does not exist. - */ - public static Map characterFrequency(String fileLocation) { - Map characterToFrequency = new HashMap<>(); - try (Reader reader = new FileReader(fileLocation); - BufferedReader bufferedReader = new BufferedReader(reader)) { - for (String line; (line = bufferedReader.readLine()) != null;) { - for (char c : line.toCharArray()) { - if (!characterToFrequency.containsKey(c)) { - characterToFrequency.put(c, 1); - } else { - characterToFrequency.put(c, characterToFrequency.get(c) + 1); - } - } - } - } catch (IOException ex) { - ex.printStackTrace(); - } - return characterToFrequency; - } - - /** - * @return the character with lowest frequency if it exists, {@code Optional.empty()} otherwise. - */ - public static Character lowestFrequencyChar(Map charFrequency) { - Character lowestFrequencyChar = null; - Iterator> iterator = charFrequency.entrySet().iterator(); - Entry entry = iterator.next(); - int minFrequency = entry.getValue(); - lowestFrequencyChar = entry.getKey(); - - while (iterator.hasNext()) { - entry = iterator.next(); - if (entry.getValue() < minFrequency) { - minFrequency = entry.getValue(); - lowestFrequencyChar = entry.getKey(); - } - } - - return lowestFrequencyChar; - } - - /** - * @return number of lines in the file at provided location. 0 if file does not exist. - */ - public static Integer countLines(String fileLocation) { - int lineCount = 0; - try (Reader reader = new FileReader(fileLocation); - BufferedReader bufferedReader = new BufferedReader(reader)) { - while (bufferedReader.readLine() != null) { - lineCount++; - } - } catch (IOException ex) { - ex.printStackTrace(); - } - return lineCount; - } - - /** - * Downloads the contents from the given urlString, and stores it in a temporary directory. - * @return the absolute path of the file downloaded. - */ - public static String downloadFile(String urlString) throws MalformedURLException, IOException { - 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()); - BufferedReader bufferedReader = new BufferedReader(reader); - FileWriter writer = new FileWriter(file)) { - for (String line; (line = bufferedReader.readLine()) != null; ) { - writer.write(line); - writer.write("\n"); - } - LOGGER.info("File downloaded at: {}", file.getAbsolutePath()); - return file.getAbsolutePath(); - } catch (IOException ex) { - throw ex; - } - } -} diff --git a/promise/src/test/java/com/iluwatar/promise/AppTest.java b/promise/src/test/java/com/iluwatar/promise/AppTest.java deleted file mode 100644 index f7df415e8547..000000000000 --- a/promise/src/test/java/com/iluwatar/promise/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.promise; - -import java.util.concurrent.ExecutionException; - -import org.junit.Test; - -/** - * - * Application test. - */ -public class AppTest { - - @Test - public void testApp() throws InterruptedException, ExecutionException { - App.main(null); - } -} diff --git a/promise/src/test/java/com/iluwatar/promise/PromiseTest.java b/promise/src/test/java/com/iluwatar/promise/PromiseTest.java deleted file mode 100644 index 6e17b97947f7..000000000000 --- a/promise/src/test/java/com/iluwatar/promise/PromiseTest.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.promise; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -/** - * Tests Promise class. - */ -public class PromiseTest { - - private Executor executor; - private Promise promise; - @Rule public ExpectedException exception = ExpectedException.none(); - - @Before - public void setUp() { - executor = Executors.newSingleThreadExecutor(); - promise = new Promise<>(); - } - - @Test - public void promiseIsFulfilledWithTheResultantValueOfExecutingTheTask() - throws InterruptedException, ExecutionException { - promise.fulfillInAsync(new NumberCrunchingTask(), executor); - - assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, promise.get()); - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - @Test - public void promiseIsFulfilledWithAnExceptionIfTaskThrowsAnException() - throws InterruptedException, ExecutionException, TimeoutException { - testWaitingForeverForPromiseToBeFulfilled(); - testWaitingSomeTimeForPromiseToBeFulfilled(); - } - - private void testWaitingForeverForPromiseToBeFulfilled() - throws InterruptedException, TimeoutException { - Promise promise = new Promise<>(); - promise.fulfillInAsync(new Callable() { - - @Override - public Integer call() throws Exception { - throw new RuntimeException("Barf!"); - } - }, executor); - - try { - promise.get(); - fail("Fetching promise should result in exception if the task threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - try { - promise.get(1000, TimeUnit.SECONDS); - fail("Fetching promise should result in exception if the task threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - } - - private void testWaitingSomeTimeForPromiseToBeFulfilled() - throws InterruptedException, TimeoutException { - Promise promise = new Promise<>(); - promise.fulfillInAsync(new Callable() { - - @Override - public Integer call() throws Exception { - throw new RuntimeException("Barf!"); - } - }, executor); - - try { - promise.get(1000, TimeUnit.SECONDS); - fail("Fetching promise should result in exception if the task threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - try { - promise.get(); - fail("Fetching promise should result in exception if the task threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - } - - @Test - public void dependentPromiseIsFulfilledAfterTheConsumerConsumesTheResultOfThisPromise() - throws InterruptedException, ExecutionException { - Promise dependentPromise = promise - .fulfillInAsync(new NumberCrunchingTask(), executor) - .thenAccept(value -> { - assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, value); - }); - - - dependentPromise.get(); - assertTrue(dependentPromise.isDone()); - assertFalse(dependentPromise.isCancelled()); - } - - @Test - public void dependentPromiseIsFulfilledWithAnExceptionIfConsumerThrowsAnException() - throws InterruptedException, ExecutionException, TimeoutException { - Promise dependentPromise = promise - .fulfillInAsync(new NumberCrunchingTask(), executor) - .thenAccept(new Consumer() { - - @Override - public void accept(Integer value) { - throw new RuntimeException("Barf!"); - } - }); - - try { - dependentPromise.get(); - fail("Fetching dependent promise should result in exception " - + "if the action threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - try { - dependentPromise.get(1000, TimeUnit.SECONDS); - fail("Fetching dependent promise should result in exception " - + "if the action threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - } - - @Test - public void dependentPromiseIsFulfilledAfterTheFunctionTransformsTheResultOfThisPromise() - throws InterruptedException, ExecutionException { - Promise dependentPromise = promise - .fulfillInAsync(new NumberCrunchingTask(), executor) - .thenApply(value -> { - assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, value); - return String.valueOf(value); - }); - - - assertEquals(String.valueOf(NumberCrunchingTask.CRUNCHED_NUMBER), dependentPromise.get()); - assertTrue(dependentPromise.isDone()); - assertFalse(dependentPromise.isCancelled()); - } - - @Test - public void dependentPromiseIsFulfilledWithAnExceptionIfTheFunctionThrowsException() - throws InterruptedException, ExecutionException, TimeoutException { - Promise dependentPromise = promise - .fulfillInAsync(new NumberCrunchingTask(), executor) - .thenApply(new Function() { - - @Override - public String apply(Integer value) { - throw new RuntimeException("Barf!"); - } - }); - - try { - dependentPromise.get(); - fail("Fetching dependent promise should result in exception " - + "if the function threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - - try { - dependentPromise.get(1000, TimeUnit.SECONDS); - fail("Fetching dependent promise should result in exception " - + "if the function threw an exception"); - } catch (ExecutionException ex) { - assertTrue(promise.isDone()); - assertFalse(promise.isCancelled()); - } - } - - @Test - public void fetchingAnAlreadyFulfilledPromiseReturnsTheFulfilledValueImmediately() - throws InterruptedException, ExecutionException, TimeoutException { - Promise promise = new Promise<>(); - promise.fulfill(NumberCrunchingTask.CRUNCHED_NUMBER); - - promise.get(1000, TimeUnit.SECONDS); - } - - @SuppressWarnings("unchecked") - @Test - public void exceptionHandlerIsCalledWhenPromiseIsFulfilledExceptionally() { - Promise promise = new Promise<>(); - Consumer exceptionHandler = mock(Consumer.class); - promise.onError(exceptionHandler); - - Exception exception = new Exception("barf!"); - promise.fulfillExceptionally(exception); - - verify(exceptionHandler).accept(eq(exception)); - } - - private static class NumberCrunchingTask implements Callable { - - private static final Integer CRUNCHED_NUMBER = Integer.MAX_VALUE; - - @Override - public Integer call() throws Exception { - // Do number crunching - Thread.sleep(100); - return CRUNCHED_NUMBER; - } - } -} diff --git a/property/README.md b/property/README.md deleted file mode 100644 index c1502f75cfd2..000000000000 --- a/property/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Property -folder: property -permalink: /patterns/property/ -pumlid: FSV13OCm30NGLTe1YEziumOBKYMEPN-3s9wUUdlltRJst2Izlmx0OYLolihUSEGdGxnEXIXAdODQpul1Jby-UTaasgwBCI2kGOFZ1pAV9ewR1FMVaZwAvUWF -categories: Creational -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Create hierarchy of objects and new objects using already existing -objects as parents. - -![alt text](./etc/property.png "Property") - -## Applicability -Use the Property pattern when - -* when you like to have objects with dynamic set of fields and prototype inheritance - -## Real world examples - -* [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototype inheritance diff --git a/property/etc/property.png b/property/etc/property.png deleted file mode 100644 index 98c0cbe3720cdfe50bff3f047096e0efe2d74e70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20016 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 F`ya22I%NO= diff --git a/property/etc/property.ucls b/property/etc/property.ucls deleted file mode 100644 index 8d50cb99d845..000000000000 --- a/property/etc/property.ucls +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/property/etc/property.urm.puml b/property/etc/property.urm.puml deleted file mode 100644 index f281cd87319f..000000000000 --- a/property/etc/property.urm.puml +++ /dev/null @@ -1,54 +0,0 @@ -@startuml -package com.iluwatar.property { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Character { - - name : String - - properties : Map - - prototype : Prototype - - type : Type - + Character() - + Character(name : String, prototype : Character) - + Character(type : Type, prototype : Prototype) - + get(stat : Stats) : Integer - + has(stat : Stats) : boolean - + name() : String - + remove(stat : Stats) - + set(stat : Stats, val : Integer) - + toString() : String - + type() : Type - } - enum Type { - + MAGE {static} - + ROGUE {static} - + WARRIOR {static} - + valueOf(name : String) : Type {static} - + values() : Type[] {static} - } - interface Prototype { - + get(Stats) : Integer {abstract} - + has(Stats) : boolean {abstract} - + remove(Stats) {abstract} - + set(Stats, Integer) {abstract} - } - enum Stats { - + AGILITY {static} - + ARMOR {static} - + ATTACK_POWER {static} - + ENERGY {static} - + INTELLECT {static} - + RAGE {static} - + SPIRIT {static} - + STRENGTH {static} - + valueOf(name : String) : Stats {static} - + values() : Stats[] {static} - } -} -Character --> "-prototype" Prototype -Type ..+ Character -Character --> "-type" Type -Character ..|> Prototype -@enduml \ No newline at end of file diff --git a/property/pom.xml b/property/pom.xml deleted file mode 100644 index db2ff8f60ed6..000000000000 --- a/property/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - property - - - junit - junit - test - - - diff --git a/property/src/main/java/com/iluwatar/property/App.java b/property/src/main/java/com/iluwatar/property/App.java deleted file mode 100644 index 2fd35689cf8f..000000000000 --- a/property/src/main/java/com/iluwatar/property/App.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -import com.iluwatar.property.Character.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The Property pattern is also known as Prototype inheritance. - *

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

    - * In this example we demonstrate {@link Character} instantiation using the Property pattern. - * - */ -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) { - /* set up */ - Prototype charProto = new Character(); - charProto.set(Stats.STRENGTH, 10); - charProto.set(Stats.AGILITY, 10); - charProto.set(Stats.ARMOR, 10); - charProto.set(Stats.ATTACK_POWER, 10); - - Character mageProto = new Character(Type.MAGE, charProto); - mageProto.set(Stats.INTELLECT, 15); - mageProto.set(Stats.SPIRIT, 10); - - Character warProto = new Character(Type.WARRIOR, charProto); - warProto.set(Stats.RAGE, 15); - warProto.set(Stats.ARMOR, 15); // boost default armor for warrior - - Character rogueProto = new Character(Type.ROGUE, charProto); - rogueProto.set(Stats.ENERGY, 15); - rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue - - /* usage */ - Character mag = new Character("Player_1", mageProto); - mag.set(Stats.ARMOR, 8); - LOGGER.info(mag.toString()); - - Character warrior = new Character("Player_2", warProto); - LOGGER.info(warrior.toString()); - - Character rogue = new Character("Player_3", rogueProto); - LOGGER.info(rogue.toString()); - - Character rogueDouble = new Character("Player_4", rogue); - rogueDouble.set(Stats.ATTACK_POWER, 12); - LOGGER.info(rogueDouble.toString()); - } -} diff --git a/property/src/main/java/com/iluwatar/property/Character.java b/property/src/main/java/com/iluwatar/property/Character.java deleted file mode 100644 index 37552fdc88b2..000000000000 --- a/property/src/main/java/com/iluwatar/property/Character.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -import java.util.HashMap; -import java.util.Map; - -/** - * Represents Character in game and his abilities (base stats). - */ -public class Character implements Prototype { - - /** - * Enumeration of Character types - */ - public enum Type { - WARRIOR, MAGE, ROGUE - } - - private final Prototype prototype; - private final Map properties = new HashMap<>(); - - private String name; - private Type type; - - /** - * Constructor - */ - public Character() { - this.prototype = new Prototype() { // Null-value object - @Override - public Integer get(Stats stat) { - return null; - } - - @Override - public boolean has(Stats stat) { - return false; - } - - @Override - public void set(Stats stat, Integer val) {} - - @Override - public void remove(Stats stat) {} - }; - } - - public Character(Type type, Prototype prototype) { - this.type = type; - this.prototype = prototype; - } - - /** - * Constructor - */ - public Character(String name, Character prototype) { - this.name = name; - this.type = prototype.type; - this.prototype = prototype; - } - - public String name() { - return name; - } - - public Type type() { - return type; - } - - @Override - public Integer get(Stats stat) { - boolean containsValue = properties.containsKey(stat); - if (containsValue) { - return properties.get(stat); - } else { - return prototype.get(stat); - } - } - - @Override - public boolean has(Stats stat) { - return get(stat) != null; - } - - @Override - public void set(Stats stat, Integer val) { - properties.put(stat, val); - } - - @Override - public void remove(Stats stat) { - properties.put(stat, null); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (name != null) { - builder.append("Player: ").append(name).append('\n'); - } - - if (type != null) { - builder.append("Character type: ").append(type.name()).append('\n'); - } - - builder.append("Stats:\n"); - for (Stats stat : Stats.values()) { - Integer value = this.get(stat); - if (value == null) { - continue; - } - builder.append(" - ").append(stat.name()).append(':').append(value).append('\n'); - } - return builder.toString(); - } - -} diff --git a/property/src/main/java/com/iluwatar/property/Prototype.java b/property/src/main/java/com/iluwatar/property/Prototype.java deleted file mode 100644 index 0c03e52cd7a5..000000000000 --- a/property/src/main/java/com/iluwatar/property/Prototype.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -/** - * Interface for prototype inheritance - */ -public interface Prototype { - - Integer get(Stats stat); - - boolean has(Stats stat); - - void set(Stats stat, Integer val); - - void remove(Stats stat); -} diff --git a/property/src/main/java/com/iluwatar/property/Stats.java b/property/src/main/java/com/iluwatar/property/Stats.java deleted file mode 100644 index 8f47924f11e9..000000000000 --- a/property/src/main/java/com/iluwatar/property/Stats.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -/** - * All possible attributes that Character can have - */ -public enum Stats { - - AGILITY, STRENGTH, ATTACK_POWER, ARMOR, INTELLECT, SPIRIT, ENERGY, RAGE -} diff --git a/property/src/test/java/com/iluwatar/property/AppTest.java b/property/src/test/java/com/iluwatar/property/AppTest.java deleted file mode 100644 index 08e0dbba13ae..000000000000 --- a/property/src/test/java/com/iluwatar/property/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/property/src/test/java/com/iluwatar/property/CharacterTest.java b/property/src/test/java/com/iluwatar/property/CharacterTest.java deleted file mode 100644 index 5dc996f4dec2..000000000000 --- a/property/src/test/java/com/iluwatar/property/CharacterTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.property; - -import org.junit.Test; - -import static com.iluwatar.property.Character.Type; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/28/15 - 7:46 PM - * - * @author Jeroen Meulemeester - */ -public class CharacterTest { - - @Test - public void testPrototypeStats() throws Exception { - final Character prototype = new Character(); - - for (final Stats stat : Stats.values()) { - assertFalse(prototype.has(stat)); - assertNull(prototype.get(stat)); - - final Integer expectedValue = stat.ordinal(); - prototype.set(stat, expectedValue); - assertTrue(prototype.has(stat)); - assertEquals(expectedValue, prototype.get(stat)); - - prototype.remove(stat); - assertFalse(prototype.has(stat)); - assertNull(prototype.get(stat)); - } - - } - - @Test - public void testCharacterStats() throws Exception { - final Character prototype = new Character(); - for (final Stats stat : Stats.values()) { - prototype.set(stat, stat.ordinal()); - } - - final Character mage = new Character(Type.MAGE, prototype); - for (final Stats stat : Stats.values()) { - final Integer expectedValue = stat.ordinal(); - assertTrue(mage.has(stat)); - assertEquals(expectedValue, mage.get(stat)); - } - } - - @Test - public void testToString() throws Exception { - final Character prototype = new Character(); - prototype.set(Stats.ARMOR, 1); - prototype.set(Stats.AGILITY, 2); - prototype.set(Stats.INTELLECT, 3); - assertEquals("Stats:\n - AGILITY:2\n - ARMOR:1\n - INTELLECT:3\n", prototype.toString()); - - final Character stupid = new Character(Type.ROGUE, prototype); - stupid.remove(Stats.INTELLECT); - assertEquals("Character type: ROGUE\nStats:\n - AGILITY:2\n - ARMOR:1\n", stupid.toString()); - - final Character weak = new Character("weak", prototype); - weak.remove(Stats.ARMOR); - assertEquals("Player: weak\nStats:\n - AGILITY:2\n - INTELLECT:3\n", weak.toString()); - - } - - @Test - public void testName() throws Exception { - final Character prototype = new Character(); - prototype.set(Stats.ARMOR, 1); - prototype.set(Stats.INTELLECT, 2); - assertNull(prototype.name()); - - final Character stupid = new Character(Type.ROGUE, prototype); - stupid.remove(Stats.INTELLECT); - assertNull(stupid.name()); - - final Character weak = new Character("weak", prototype); - weak.remove(Stats.ARMOR); - assertEquals("weak", weak.name()); - } - - @Test - public void testType() throws Exception { - final Character prototype = new Character(); - prototype.set(Stats.ARMOR, 1); - prototype.set(Stats.INTELLECT, 2); - assertNull(prototype.type()); - - final Character stupid = new Character(Type.ROGUE, prototype); - stupid.remove(Stats.INTELLECT); - assertEquals(Type.ROGUE, stupid.type()); - - final Character weak = new Character("weak", prototype); - weak.remove(Stats.ARMOR); - assertNull(weak.type()); - } - -} \ No newline at end of file diff --git a/prototype/README.md b/prototype/README.md deleted file mode 100644 index 477cd6e6fcc3..000000000000 --- a/prototype/README.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -layout: pattern -title: Prototype -folder: prototype -permalink: /patterns/prototype/ -pumlid: HSV13OCm30NGLM00udktCS62eCInxE-YRj_UUdjlRLfx7fBUbmkmU14vF-Lik7BF4AzJ8OfIvw3Mys6mqyrltWw9Tkfc38XhqE3uWSmd9Zuc9AZ_bVHHB4V_0W00 -categories: Creational -tags: - - Java - - Gang Of Four - - Difficulty-Beginner ---- - -## Intent -Specify the kinds of objects to create using a prototypical -instance, and create new objects by copying this prototype. - -## Explanation -Real world example - -> Remember Dolly? The sheep that was cloned! Lets not get into the details but the key point here is that it is all about cloning. - -In plain words - -> Create object based on an existing object through cloning. - -Wikipedia says - -> The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. - -In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up. - -**Programmatic Example** - -In Java, it can be easily done by implementing `Cloneable` and overriding `clone` from `Object` - -``` -class Sheep implements Cloneable { - private String name; - public Sheep(String name) { this.name = name; } - public void setName(String name) { this.name = name; } - public String getName() { return name; } - @Override - public Sheep clone() throws CloneNotSupportedException { - return new Sheep(name); - } -} -``` - -Then it can be cloned like below - -``` -Sheep original = new Sheep("Jolly"); -System.out.println(original.getName()); // Jolly - -// Clone and modify what is required -Sheep cloned = original.clone(); -cloned.setName("Dolly"); -System.out.println(cloned.getName()); // Dolly -``` - -## Applicability -Use the Prototype pattern when a system should be independent of how its products are created, composed and represented; and - -* when the classes to instantiate are specified at run-time, for example, by dynamic loading -* to avoid building a class hierarchy of factories that parallels the class hierarchy of products -* when instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state -* when object creation is expensive compared to cloning - -## Real world examples - -* [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/prototype/pom.xml b/prototype/pom.xml deleted file mode 100644 index 62d4f0eb1c72..000000000000 --- a/prototype/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - prototype - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/prototype/src/main/java/com/iluwatar/prototype/App.java b/prototype/src/main/java/com/iluwatar/prototype/App.java deleted file mode 100644 index dfebdab17605..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/App.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * type of objects to create is determined by a prototypical instance, which is cloned to produce - * new objects. This pattern is used to: - avoid subclasses of an object creator in the client - * application, like the abstract factory pattern does. - avoid the inherent cost of creating a new - * object in the standard way (e.g., using the 'new' keyword) - *

    - * In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by cloning - * the existing ones. The factory's prototype objects are given as constructor parameters. - * - */ -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) { - HeroFactory factory; - Mage mage; - Warlord warlord; - Beast beast; - - factory = new HeroFactoryImpl(new ElfMage(), new ElfWarlord(), new ElfBeast()); - mage = factory.createMage(); - warlord = factory.createWarlord(); - beast = factory.createBeast(); - 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(); - LOGGER.info(mage.toString()); - LOGGER.info(warlord.toString()); - LOGGER.info(beast.toString()); - } -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/Beast.java b/prototype/src/main/java/com/iluwatar/prototype/Beast.java deleted file mode 100644 index fc81ac4e6d35..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/Beast.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Beast - * - */ -public abstract class Beast extends Prototype { - - @Override - public abstract Beast clone() throws CloneNotSupportedException; - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java b/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java deleted file mode 100644 index 11783611ee38..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * ElfBeast - * - */ -public class ElfBeast extends Beast { - - public ElfBeast() {} - - @Override - public Beast clone() throws CloneNotSupportedException { - return new ElfBeast(); - } - - @Override - public String toString() { - return "Elven eagle"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java b/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java deleted file mode 100644 index 5ddefcdf5611..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * ElfMage - * - */ -public class ElfMage extends Mage { - - public ElfMage() {} - - @Override - public Mage clone() throws CloneNotSupportedException { - return new ElfMage(); - } - - @Override - public String toString() { - return "Elven mage"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java b/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java deleted file mode 100644 index d0dfde1db19c..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * ElfWarlord - * - */ -public class ElfWarlord extends Warlord { - - public ElfWarlord() {} - - @Override - public Warlord clone() throws CloneNotSupportedException { - return new ElfWarlord(); - } - - @Override - public String toString() { - return "Elven warlord"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java b/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java deleted file mode 100644 index cb11c9fe619a..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Interface for the factory class. - * - */ -public interface HeroFactory { - - Mage createMage(); - - Warlord createWarlord(); - - Beast createBeast(); - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java b/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java deleted file mode 100644 index 4f05bb843553..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Concrete factory class. - * - */ -public class HeroFactoryImpl implements HeroFactory { - - private Mage mage; - private Warlord warlord; - private Beast beast; - - /** - * Constructor - */ - public HeroFactoryImpl(Mage mage, Warlord warlord, Beast beast) { - this.mage = mage; - this.warlord = warlord; - this.beast = beast; - } - - /** - * Create mage - */ - public Mage createMage() { - try { - return mage.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** - * Create warlord - */ - public Warlord createWarlord() { - try { - return warlord.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** - * Create beast - */ - public Beast createBeast() { - try { - return beast.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/Mage.java b/prototype/src/main/java/com/iluwatar/prototype/Mage.java deleted file mode 100644 index 361b586b2e81..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/Mage.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Mage - * - */ -public abstract class Mage extends Prototype { - - @Override - public abstract Mage clone() throws CloneNotSupportedException; - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java b/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java deleted file mode 100644 index 212888fb4644..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * OrcBeast - * - */ -public class OrcBeast extends Beast { - - public OrcBeast() {} - - @Override - public Beast clone() throws CloneNotSupportedException { - return new OrcBeast(); - } - - @Override - public String toString() { - return "Orcish wolf"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java b/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java deleted file mode 100644 index c15143bbb6e4..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * OrcMage - * - */ -public class OrcMage extends Mage { - - public OrcMage() {} - - @Override - public Mage clone() throws CloneNotSupportedException { - return new OrcMage(); - } - - @Override - public String toString() { - return "Orcish mage"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java b/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java deleted file mode 100644 index e9f7c6cd4ad5..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * OrcWarlord - * - */ -public class OrcWarlord extends Warlord { - - public OrcWarlord() {} - - @Override - public Warlord clone() throws CloneNotSupportedException { - return new OrcWarlord(); - } - - @Override - public String toString() { - return "Orcish warlord"; - } - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/Prototype.java b/prototype/src/main/java/com/iluwatar/prototype/Prototype.java deleted file mode 100644 index 10d8b66eb351..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/Prototype.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Prototype - * - */ -public abstract class Prototype implements Cloneable { - - @Override - public abstract Object clone() throws CloneNotSupportedException; - -} diff --git a/prototype/src/main/java/com/iluwatar/prototype/Warlord.java b/prototype/src/main/java/com/iluwatar/prototype/Warlord.java deleted file mode 100644 index aef8676f4a53..000000000000 --- a/prototype/src/main/java/com/iluwatar/prototype/Warlord.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -/** - * - * Warlord - * - */ -public abstract class Warlord extends Prototype { - - @Override - public abstract Warlord clone() throws CloneNotSupportedException; - -} diff --git a/prototype/src/test/java/com/iluwatar/prototype/AppTest.java b/prototype/src/test/java/com/iluwatar/prototype/AppTest.java deleted file mode 100644 index 48c70429a924..000000000000 --- a/prototype/src/test/java/com/iluwatar/prototype/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java b/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java deleted file mode 100644 index bee05bc5e263..000000000000 --- a/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -import org.junit.Test; - -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -/** - * Date: 12/28/15 - 8:34 PM - * - * @author Jeroen Meulemeester - */ -public class HeroFactoryImplTest { - - @Test - public void testFactory() throws Exception { - final Mage mage = mock(Mage.class); - final Warlord warlord = mock(Warlord.class); - final Beast beast = mock(Beast.class); - - when(mage.clone()).thenThrow(CloneNotSupportedException.class); - when(warlord.clone()).thenThrow(CloneNotSupportedException.class); - when(beast.clone()).thenThrow(CloneNotSupportedException.class); - - final HeroFactoryImpl factory = new HeroFactoryImpl(mage, warlord, beast); - assertNull(factory.createMage()); - assertNull(factory.createWarlord()); - assertNull(factory.createBeast()); - - verify(mage).clone(); - verify(warlord).clone(); - verify(beast).clone(); - verifyNoMoreInteractions(mage, warlord, beast); - } - -} \ No newline at end of file diff --git a/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java b/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java deleted file mode 100644 index 839f27bc7147..000000000000 --- a/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.prototype; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; - -import java.util.Arrays; -import java.util.Collection; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -/** - * Date: 12/28/15 - 8:45 PM - * @param

    Prototype - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class PrototypeTest

    { - - @Parameterized.Parameters - public static Collection data() { - return Arrays.asList( - new Object[]{new OrcBeast(), "Orcish wolf"}, - new Object[]{new OrcMage(), "Orcish mage"}, - new Object[]{new OrcWarlord(), "Orcish warlord"}, - new Object[]{new ElfBeast(), "Elven eagle"}, - new Object[]{new ElfMage(), "Elven mage"}, - new Object[]{new ElfWarlord(), "Elven warlord"} - ); - } - - /** - * The tested prototype instance - */ - private final P testedPrototype; - - /** - * The expected {@link Prototype#toString()} value - */ - private final String expectedToString; - - /** - * Create a new test instance, using the given test object and expected value - * - * @param testedPrototype The tested prototype instance - * @param expectedToString The expected {@link Prototype#toString()} value - */ - public PrototypeTest(final P testedPrototype, final String expectedToString) { - this.expectedToString = expectedToString; - this.testedPrototype = testedPrototype; - } - - @Test - public void testPrototype() throws Exception { - assertEquals(this.expectedToString, this.testedPrototype.toString()); - - final Object clone = this.testedPrototype.clone(); - assertNotNull(clone); - assertNotSame(clone, this.testedPrototype); - assertSame(this.testedPrototype.getClass(), clone.getClass()); - } - -} diff --git a/proxy/README.md b/proxy/README.md deleted file mode 100644 index 615c02ced049..000000000000 --- a/proxy/README.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -layout: pattern -title: Proxy -folder: proxy -permalink: /patterns/proxy/ -pumlid: 9SR13OCm30NGLM00udktCS62eCI9x6yesrEfx_Jcehd69c5rEe3X7oBZE-q5HwpXOhahH95oRrHgt0msEldYPHClkow30J5rQko_qB3-VKYG_qjXBOrezGK0 -categories: Structural -tags: - - Java - - Gang Of Four - - Difficulty-Beginner ---- - -## Also known as -Surrogate - -## Intent -Provide a surrogate or placeholder for another object to control -access to it. - -## Explanation -Real world example - -> Imagine a tower where the local wizards go to study their spells. The ivory tower can only be accessed through a proxy which ensures that only the first three wizards can enter. Here the proxy represents the functionality of the tower and adds access control to it. - -In plain words - -> Using the proxy pattern, a class represents the functionality of another class. - -Wikipedia says - -> A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. - -**Programmatic Example** - -Taking our wizard tower example from above. Firstly we have the wizard tower interface and the ivory tower class - -``` -public interface WizardTower { - - void enter(Wizard wizard); -} - -public class IvoryTower implements WizardTower { - - private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class); - - public void enter(Wizard wizard) { - LOGGER.info("{} enters the tower.", wizard); - } - -} -``` - -Then a simple wizard class - -``` -public class Wizard { - - private final String name; - - public Wizard(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} -``` - -Then we have the proxy to add access control to wizard tower - -``` -public class WizardTowerProxy implements WizardTower { - - private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class); - - private static final int NUM_WIZARDS_ALLOWED = 3; - - private int numWizards; - - private final WizardTower tower; - - public WizardTowerProxy(WizardTower tower) { - this.tower = tower; - } - - @Override - public void enter(Wizard wizard) { - if (numWizards < NUM_WIZARDS_ALLOWED) { - tower.enter(wizard); - numWizards++; - } else { - LOGGER.info("{} is not allowed to enter!", wizard); - } - } -} -``` - -And here is tower entering scenario - -``` -WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower()); -proxy.enter(new Wizard("Red wizard")); // Red wizard enters the tower. -proxy.enter(new Wizard("White wizard")); // White wizard enters the tower. -proxy.enter(new Wizard("Black wizard")); // Black wizard enters the tower. -proxy.enter(new Wizard("Green wizard")); // Green wizard is not allowed to enter! -proxy.enter(new Wizard("Brown wizard")); // Brown wizard is not allowed to enter! -``` - -## Applicability -Proxy is applicable whenever there is a need for a more -versatile or sophisticated reference to an object than a simple pointer. Here -are several common situations in which the Proxy pattern is applicable - -* Remote proxy provides a local representative for an object in a different address space. -* Virtual proxy creates expensive objects on demand. -* Protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights. - -## Typical Use Case - -* Control access to another object -* Lazy initialization -* Implement logging -* Facilitate network connection -* Count references to an object - -## Tutorials -* [Controlling Access With Proxy Pattern](http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/) - -## Presentations -* [Proxy](https://github.com/iluwatar/java-design-patterns/tree/master/proxy/etc/presentation.html) - -## Real world examples - -* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html) -* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/) -* Mocking frameworks Mockito, Powermock, EasyMock - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/proxy/etc/presentation.html b/proxy/etc/presentation.html deleted file mode 100644 index f669bf4e9e49..000000000000 --- a/proxy/etc/presentation.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Title - - - - - - - - - diff --git a/proxy/etc/proxy-concept.png b/proxy/etc/proxy-concept.png deleted file mode 100644 index dac5d954bc58e9c59ded9f3963618d75a95d1b73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24957 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 diff --git a/proxy/etc/proxy-concept.xml b/proxy/etc/proxy-concept.xml deleted file mode 100644 index 83373a92959b..000000000000 --- a/proxy/etc/proxy-concept.xml +++ /dev/null @@ -1,25 +0,0 @@ - -7Vhtb5swEP41kbYPnQJuaPexeVv3YVK1aur60YEL8WowM05K+utnYxswkC6p2rSbmkoNfnx3vpfnLsAATZLiC8fZ6huLgA78YVQM0HTg+x4KPPmlkK1GziwQcxIZoRq4Jg9gwKFB1ySC3BEUjFFBMhcMWZpCKBwMc87uXbElo+6pGY6hA1yHmHbRGxKJlUbPR8MavwQSr+zJ3tDsLHB4F3O2Ts15Ax8ty4/eTrC1ZeTzFY7YfQNCswGacMaEvkqKCVCVW5s2rTffsVv5zSEV+yica4UNpmuwHgdUqo4z5Z3YmowEv9fKpXGCeUzSAbqQu8OskP8lWAam8BPBMr132tgTUIgTTEls9ELpG/DapryKzXd5MmkAOJEGx7S7+qpsLHEIFeyqOBZl/KR9yoJ3EAtcrxe/FKtq7UVbVmJZG1txlTLLZRudtzvQJ6WYwlI0crzLdje8PpdfxgMlW9b4ww15wDz6qKU3TLJuT/d8xzF/A1wQ2Z4XmkXTkmdjw6mpdmjMpNSSlt20JJLlaLxkqTDDxfPNeo4TQtVYugS6AWVVlU4kVAkpGak6YZTx8mTbvWicC87uoLEzLD+KahxHRMbb2Juezrz5qIpEuQ/Fzhb1qsaXAxVYAoJvpYhR8M/NrDCz1A6h+3owVeNk5Q4lMxDNMIwr0/VAkBdmJvTPB+vumxoQVTd+B0yP1awR2fQGbFOuHPcf68g8w+lBPSLddnUquPTl9VvlhYmPfJf4fcz3TnuYHzwH8f23TPwrzortO+X/O8oHnkv5s9ERGY/eIuN336VNqCrE/k3wj99SzAL19zw0G70iy7pPHLNCQBrlnQpJ8EI9y8nVgrLwTsYuIZv8QC/nZVmmQzfjMg98+1Phn0Z2eWv3CiIaW3J1awxoDyDqPBu28iq9ZGsegnuLJCTtQTQeq7rpbybYJpMDxYJs3CP7MmzMXTGiWL+jlAi1aqQ9NUrNB8GWHd/7iyEdXsdQWe8qxP0o8PmoFPCaBKiL/tOoVAQodw5v1SeSxn8nzUGkQd37sR85PEYYlkHq8kXN6wjnK4gMLZp0MZTwOpSoZ0mXSE8sPnov/mHF77s12V35lKVQ9izmomd8NOZFKWLWbULs8RPSJcvz/YToEI/CiKD1hqF643AsSsgi4W1DLFMC+eEO1wzTFvfkm1zWb1y1eP1aG83+AA== \ No newline at end of file diff --git a/proxy/pom.xml b/proxy/pom.xml deleted file mode 100644 index ea55330b73c6..000000000000 --- a/proxy/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - proxy - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/proxy/src/main/java/com/iluwatar/proxy/App.java b/proxy/src/main/java/com/iluwatar/proxy/App.java deleted file mode 100644 index 064d643beb4d..000000000000 --- a/proxy/src/main/java/com/iluwatar/proxy/App.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -/** - * - * A proxy, in its most general form, is a class functioning as an interface to something else. The - * proxy could interface to anything: a network connection, a large object in memory, a file, or - * some other resource that is expensive or impossible to duplicate. In short, a proxy is a wrapper - * or agent object that is being called by the client to access the real serving object behind the - * scenes. - *

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

    - * In this example the proxy ({@link WizardTowerProxy}) controls access to the actual object ( - * {@link IvoryTower}). - * - */ -public class App { - - /** - * Program entry point - */ - public static void main(String[] args) { - - WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower()); - proxy.enter(new Wizard("Red wizard")); - proxy.enter(new Wizard("White wizard")); - proxy.enter(new Wizard("Black wizard")); - proxy.enter(new Wizard("Green wizard")); - proxy.enter(new Wizard("Brown wizard")); - - } -} diff --git a/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java b/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java deleted file mode 100644 index 382f41c3d1de..000000000000 --- a/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The object to be proxyed. - * - */ -public class IvoryTower implements WizardTower { - - private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class); - - public void enter(Wizard wizard) { - LOGGER.info("{} enters the tower.", wizard); - } - -} diff --git a/proxy/src/main/java/com/iluwatar/proxy/Wizard.java b/proxy/src/main/java/com/iluwatar/proxy/Wizard.java deleted file mode 100644 index 817c46c0cfb0..000000000000 --- a/proxy/src/main/java/com/iluwatar/proxy/Wizard.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -/** - * - * Wizard - * - */ -public class Wizard { - - private final String name; - - public Wizard(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } - -} diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java deleted file mode 100644 index f89dbea9a56b..000000000000 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -/** - * WizardTower interface - */ -public interface WizardTower { - - void enter(Wizard wizard); -} diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java deleted file mode 100644 index 728b65bf757a..000000000000 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The proxy controlling access to the {@link IvoryTower}. - * - */ -public class WizardTowerProxy implements WizardTower { - - private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class); - - private static final int NUM_WIZARDS_ALLOWED = 3; - - private int numWizards; - - private final WizardTower tower; - - public WizardTowerProxy(WizardTower tower) { - this.tower = tower; - } - - @Override - public void enter(Wizard wizard) { - if (numWizards < NUM_WIZARDS_ALLOWED) { - tower.enter(wizard); - numWizards++; - } else { - LOGGER.info("{} is not allowed to enter!", wizard); - } - } -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/AppTest.java b/proxy/src/test/java/com/iluwatar/proxy/AppTest.java deleted file mode 100644 index d22d9c4bdd29..000000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/IvoryTowerTest.java b/proxy/src/test/java/com/iluwatar/proxy/IvoryTowerTest.java deleted file mode 100644 index 944193a0ab94..000000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/IvoryTowerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import com.iluwatar.proxy.utils.InMemoryAppender; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests for {@link IvoryTower} - */ -public class IvoryTowerTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(IvoryTower.class); - } - - @After - public void tearDown() { - appender.stop(); - } - - @Test - public void testEnter() throws Exception { - final Wizard[] wizards = new Wizard[]{ - new Wizard("Gandalf"), - new Wizard("Dumbledore"), - new Wizard("Oz"), - new Wizard("Merlin") - }; - - IvoryTower tower = new IvoryTower(); - for (Wizard wizard : wizards) { - tower.enter(wizard); - } - - 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()); - } -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java deleted file mode 100644 index ce5637214a6f..000000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for {@link Wizard} - */ -public class WizardTest { - - @Test - public void testToString() throws Exception { - final String[] wizardNames = {"Gandalf", "Dumbledore", "Oz", "Merlin"}; - for (String name : wizardNames) { - assertEquals(name, new Wizard(name).toString()); - } - } -} \ No newline at end of file diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java deleted file mode 100644 index 2958376d6755..000000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.proxy; - -import com.iluwatar.proxy.utils.InMemoryAppender; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests for {@link WizardTowerProxy} - */ -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 { - final Wizard[] wizards = new Wizard[]{ - new Wizard("Gandalf"), - new Wizard("Dumbledore"), - new Wizard("Oz"), - new Wizard("Merlin") - }; - - final WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower()); - for (Wizard wizard : wizards) { - proxy.enter(wizard); - } - - 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()); - } -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java b/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java deleted file mode 100644 index d78fdc93f440..000000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - - -/** - * InMemory Log Appender Util. - */ -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/publish-subscribe/.gitignore b/publish-subscribe/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/publish-subscribe/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/publish-subscribe/README.md b/publish-subscribe/README.md deleted file mode 100644 index 46220907472a..000000000000 --- a/publish-subscribe/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: pattern -title: Publish Subscribe -folder: publish-subscribe -permalink: /patterns/publish-subscribe/ -categories: Integration -tags: - - Java - - EIP - - Apache Camel™ ---- - -## Intent -Broadcast messages from sender to all the interested receivers. - -![alt text](./etc/publish-subscribe.png "Publish Subscribe Channel") - -## Applicability -Use the Publish Subscribe Channel pattern when - -* two or more applications need to communicate using a messaging system for broadcasts. - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) diff --git a/publish-subscribe/etc/publish-subscribe.png b/publish-subscribe/etc/publish-subscribe.png deleted file mode 100644 index 99867da66b548a6d484d67364d4eb3dbaed3e2f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27741 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

    s(c{+6#Xc&>ImMwHl&y7=u7` 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 xk&%Jtkpd1f - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/publish-subscribe/etc/publish-subscribe.urm.puml b/publish-subscribe/etc/publish-subscribe.urm.puml deleted file mode 100644 index 2e511c92dbb9..000000000000 --- a/publish-subscribe/etc/publish-subscribe.urm.puml +++ /dev/null @@ -1,9 +0,0 @@ -@startuml -package com.iluwatar.publish.subscribe { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml deleted file mode 100644 index ebd82f3a7bf1..000000000000 --- a/publish-subscribe/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - publish-subscribe - - - org.apache.camel - camel-core - - - org.apache.camel - camel-stream - - - junit - junit - - - \ No newline at end of file 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 deleted file mode 100644 index d642846fb24e..000000000000 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.publish.subscribe; - -import org.apache.camel.CamelContext; -import org.apache.camel.ProducerTemplate; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.impl.DefaultCamelContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * There are well-established patterns for implementing broadcasting. The Observer pattern describes - * the need to decouple observers from their subject (that is, the originator of the event) so that - * the subject can easily provide event notification to all interested observers no matter how many - * observers there are (even none). The Publish-Subscribe pattern expands upon Observer by adding - * the notion of an event channel for communicating event notifications. - *

    - * A Publish-Subscribe Channel works like this: It has one input channel that splits into multiple - * output channels, one for each subscriber. When an event is published into the channel, the - * Publish-Subscribe Channel delivers a copy of the message to each of the output channels. Each - * output end of the channel has only one subscriber, which is allowed to consume a message only - * once. In this way, each subscriber gets the message only once, and consumed copies disappear from - * their channels. - *

    - * In this example we use Apache Camel to establish a Publish-Subscribe Channel from "direct-origin" - * to "mock:foo", "mock:bar" and "stream:out". - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) throws Exception { - CamelContext context = new DefaultCamelContext(); - context.addRoutes(new RouteBuilder() { - @Override - public void configure() throws Exception { - from("direct:origin").multicast().to("mock:foo", "mock:bar", "stream:out"); - } - }); - ProducerTemplate template = context.createProducerTemplate(); - context.start(); - context.getRoutes().stream().forEach(r -> LOGGER.info(r.toString())); - template.sendBody("direct:origin", "Hello from origin"); - context.stop(); - } -} diff --git a/publish-subscribe/src/main/resources/logback.xml b/publish-subscribe/src/main/resources/logback.xml deleted file mode 100644 index 582af26bde36..000000000000 --- a/publish-subscribe/src/main/resources/logback.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - publish-subscribe.log - - publish-subscribe-%d.log - 5 - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - - - - - - - - diff --git a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java b/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java deleted file mode 100644 index 216ba49f08bd..000000000000 --- a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.publish.subscribe; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/queue-load-leveling/README.md b/queue-load-leveling/README.md deleted file mode 100644 index ca73ac34a93a..000000000000 --- a/queue-load-leveling/README.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -layout: pattern -title: Queue based load leveling -folder: queue-load-leveling -permalink: /patterns/queue-load-leveling/ -pumlid: ROux3W8n30LxJW47IDnJxLLCOcM376VnP_VwX9xgZKOQwMtcg1w3RuykXQDIADztzyEU08fNRjttU8MHbYbEuhdC0PtZmfN26qzCbQmtIGUwauh1G5i0dw2Wn1DhOZg9kpGWB_zy3Xtv-FtOIEhQBm00 -categories: Other -tags: - - Java - - Difficulty-Intermediate - - Performance ---- - -## Intent -Use a queue that acts as a buffer between a task and a service that it invokes in order to smooth -intermittent heavy loads that may otherwise cause the service to fail or the task to time out. -This pattern can help to minimize the impact of peaks in demand on availability and responsiveness -for both the task and the service. - -![alt text](./etc/queue-load-leveling.gif "queue-load-leveling") - - -## Applicability - -* This pattern is ideally suited to any type of application that uses services that may be subject to overloading. -* This pattern might not be suitable if the application expects a response from the service with minimal latency. - -## Tutorials -* [Queue-Based Load Leveling Pattern](http://java-design-patterns.com/blog/queue-load-leveling/) - -## Real world example - -* A Microsoft Azure web role stores data by using a separate storage service. If a large number of instances of the web role run concurrently, it is possible that the storage service could be overwhelmed and be unable to respond to requests quickly enough to prevent these requests from timing out or failing. - -## Credits - -* [Microsoft Cloud Design Patterns: Queue-Based Load Leveling Pattern](https://msdn.microsoft.com/en-us/library/dn589783.aspx) diff --git a/queue-load-leveling/etc/queue-load-leveling.gif b/queue-load-leveling/etc/queue-load-leveling.gif deleted file mode 100644 index 4f57c3e5070179760cb647c0d5047be19a1d92f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15062 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 NBP0zABshTQe*k~Fbn*ZI diff --git a/queue-load-leveling/etc/queue-load-leveling.ucls b/queue-load-leveling/etc/queue-load-leveling.ucls deleted file mode 100644 index 91440e27652f..000000000000 --- a/queue-load-leveling/etc/queue-load-leveling.ucls +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/queue-load-leveling/etc/queue-load-leveling.urm.puml b/queue-load-leveling/etc/queue-load-leveling.urm.puml deleted file mode 100644 index ca90842d92dd..000000000000 --- a/queue-load-leveling/etc/queue-load-leveling.urm.puml +++ /dev/null @@ -1,44 +0,0 @@ -@startuml -package com.iluwatar.queue.load.leveling { - class App { - - LOGGER : Logger {static} - - SHUTDOWN_TIME : int {static} - + App() - + main(args : String[]) {static} - } - class Message { - - msg : String - + Message(msg : String) - + getMsg() : String - + toString() : String - } - class MessageQueue { - - LOGGER : Logger {static} - - blkQueue : BlockingQueue - + MessageQueue() - + retrieveMsg() : Message - + submitMsg(msg : Message) - } - class ServiceExecutor { - - LOGGER : Logger {static} - - msgQueue : MessageQueue - + ServiceExecutor(msgQueue : MessageQueue) - + run() - } - interface Task { - + submit(Message) {abstract} - } - class TaskGenerator { - - LOGGER : Logger {static} - - msgCount : int - - msgQueue : MessageQueue - + TaskGenerator(msgQueue : MessageQueue, msgCount : int) - + run() - + submit(msg : Message) - } -} -MessageQueue --> "-blkQueue" Message -ServiceExecutor --> "-msgQueue" MessageQueue -TaskGenerator --> "-msgQueue" MessageQueue -TaskGenerator ..|> Task -@enduml \ No newline at end of file diff --git a/queue-load-leveling/pom.xml b/queue-load-leveling/pom.xml deleted file mode 100644 index 57741ed5266d..000000000000 --- a/queue-load-leveling/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - queue-load-leveling - - - junit - junit - test - - - diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/App.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/App.java deleted file mode 100644 index f71d30c16abf..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/App.java +++ /dev/null @@ -1,119 +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.queue.load.leveling; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Many solutions in the cloud involve running tasks that invoke services. In this environment, - * if a service is subjected to intermittent heavy loads, it can cause performance or reliability issues. - *

    - * A service could be a component that is part of the same solution as the tasks that utilize it, or it - * could be a third-party service providing access to frequently used resources such as a cache or a storage service. - * If the same service is utilized by a number of tasks running concurrently, it can be difficult to predict the - * volume of requests to which the service might be subjected at any given point in time. - *

    - * We will build a queue-based-load-leveling to solve above problem. - * Refactor the solution and introduce a queue between the task and the service. - * The task and the service run asynchronously. The task posts a message containing the data required - * by the service to a queue. The queue acts as a buffer, storing the message until it is retrieved - * by the service. The service retrieves the messages from the queue and processes them. - * Requests from a number of tasks, which can be generated at a highly variable rate, can be passed - * to the service through the same message queue. - *

    - * The queue effectively decouples the tasks from the service, and the service can handle the messages - * at its own pace irrespective of the volume of requests from concurrent tasks. Additionally, - * there is no delay to a task if the service is not available at the time it posts a message to the queue. - *

    - * In this example we have a class {@link MessageQueue} to hold the message {@link Message} objects. - * All the worker threads {@link TaskGenerator} will submit the messages to the MessageQueue. - * The service executor class {@link ServiceExecutor} will pick up one task at a time from the Queue and - * execute them. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - //Executor shut down time limit. - private static final int SHUTDOWN_TIME = 15; - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - // An Executor that provides methods to manage termination and methods that can - // produce a Future for tracking progress of one or more asynchronous tasks. - ExecutorService executor = null; - - try { - // Create a MessageQueue object. - MessageQueue msgQueue = new MessageQueue(); - - LOGGER.info("Submitting TaskGenerators and ServiceExecutor threads."); - - // Create three TaskGenerator threads. Each of them will submit different number of jobs. - Runnable taskRunnable1 = new TaskGenerator(msgQueue, 5); - Runnable taskRunnable2 = new TaskGenerator(msgQueue, 1); - Runnable taskRunnable3 = new TaskGenerator(msgQueue, 2); - - // Create e service which should process the submitted jobs. - Runnable srvRunnable = new ServiceExecutor(msgQueue); - - // Create a ThreadPool of 2 threads and - // submit all Runnable task for execution to executor.. - executor = Executors.newFixedThreadPool(2); - executor.submit(taskRunnable1); - executor.submit(taskRunnable2); - executor.submit(taskRunnable3); - - // submitting serviceExecutor thread to the Executor service. - executor.submit(srvRunnable); - - // Initiates an orderly shutdown. - LOGGER.info("Intiating shutdown. Executor will shutdown only after all the Threads are completed."); - executor.shutdown(); - - // Wait for SHUTDOWN_TIME seconds for all the threads to complete - // their tasks and then shut down the executor and then exit. - if ( !executor.awaitTermination(SHUTDOWN_TIME, TimeUnit.SECONDS) ) { - LOGGER.info("Executor was shut down and Exiting."); - executor.shutdownNow(); - } - } catch (InterruptedException ie) { - LOGGER.error(ie.getMessage()); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Message.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Message.java deleted file mode 100644 index fc218c875e15..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Message.java +++ /dev/null @@ -1,47 +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.queue.load.leveling; - -/** - * Message class with only one parameter. - * -*/ -public class Message { - private final String msg; - - // Parameter constructor. - public Message(String msg) { - super(); - this.msg = msg; - } - - // Get Method for attribute msg. - public String getMsg() { - return msg; - } - - @Override - public String toString() { - return msg; - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/MessageQueue.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/MessageQueue.java deleted file mode 100644 index c1e6d4c28b88..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/MessageQueue.java +++ /dev/null @@ -1,77 +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.queue.load.leveling; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * MessageQueue class. - * In this class we will create a Blocking Queue and - * submit/retrieve all the messages from it. - */ -public class MessageQueue { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - private final BlockingQueue blkQueue; - - // Default constructor when called creates Blocking Queue object. - public MessageQueue() { - this.blkQueue = new ArrayBlockingQueue(1024); - } - - /** - * All the TaskGenerator threads will call this method to insert the - * Messages in to the Blocking Queue. - */ - public void submitMsg(Message msg) { - try { - if (null != msg) { - blkQueue.add(msg); - } - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } - - /** - * All the messages will be retrieved by the ServiceExecutor by - * calling this method and process them. - * Retrieves and removes the head of this queue, or returns null if this queue is empty. - */ - public Message retrieveMsg() { - Message retrievedMsg = null; - try { - retrievedMsg = blkQueue.poll(); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - - return retrievedMsg; - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/ServiceExecutor.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/ServiceExecutor.java deleted file mode 100644 index 2b423ffafa4f..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/ServiceExecutor.java +++ /dev/null @@ -1,67 +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.queue.load.leveling; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * ServiceExecuotr class. - * This class will pick up Messages one by one from - * the Blocking Queue and process them. - */ -public class ServiceExecutor implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - private final MessageQueue msgQueue; - - public ServiceExecutor(MessageQueue msgQueue) { - this.msgQueue = msgQueue; - } - - /** - * The ServiceExecutor thread will retrieve each message and process it. - */ - public void run() { - try { - while (!Thread.currentThread().isInterrupted()) { - Message msg = msgQueue.retrieveMsg(); - - if (null != msg) { - LOGGER.info(msg.toString() + " is served."); - } else { - LOGGER.info("Service Executor: Waiting for Messages to serve .. "); - } - - Thread.sleep(1000); - } - } catch (InterruptedException ie) { - LOGGER.error(ie.getMessage()); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Task.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Task.java deleted file mode 100644 index f85f7d49c11c..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Task.java +++ /dev/null @@ -1,30 +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.queue.load.leveling; -/** - * Task Interface. - * -*/ -public interface Task { - void submit(Message msg); -} diff --git a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/TaskGenerator.java b/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/TaskGenerator.java deleted file mode 100644 index e99e918dbe4b..000000000000 --- a/queue-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/TaskGenerator.java +++ /dev/null @@ -1,89 +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.queue.load.leveling; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * TaskGenerator class. - * Each TaskGenerator thread will be a Worker which submit's messages to the queue. - * We need to mention the message count for each of the TaskGenerator threads. - * -*/ -public class TaskGenerator implements Task, Runnable { - - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - // MessageQueue reference using which we will submit our messages. - private final MessageQueue msgQueue; - - // Total message count that a TaskGenerator will submit. - private final int msgCount; - - // Parameterized constructor. - public TaskGenerator(MessageQueue msgQueue, int msgCount) { - this.msgQueue = msgQueue; - this.msgCount = msgCount; - } - - /** - * Submit messages to the Blocking Queue. - */ - public void submit(Message msg) { - try { - this.msgQueue.submitMsg(msg); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } - - /** - * Each TaskGenerator thread will submit all the messages to the Queue. - * After every message submission TaskGenerator thread will sleep for 1 second. - */ - public void run() { - - int count = this.msgCount; - - try { - while (count > 0) { - String statusMsg = "Message-" + count + " submitted by " + Thread.currentThread().getName(); - this.submit(new Message(statusMsg)); - - LOGGER.info(statusMsg); - - // reduce the message count. - count--; - - // Make the current thread to sleep after every Message submission. - Thread.sleep(1000); - } - } catch (InterruptedException ie) { - LOGGER.error(ie.getMessage()); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/AppTest.java b/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/AppTest.java deleted file mode 100644 index d1cf75ca8f2e..000000000000 --- a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/AppTest.java +++ /dev/null @@ -1,38 +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.queue.load.leveling; - -import java.io.IOException; - -import org.junit.Test; - -/** - * Application Test - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} \ No newline at end of file diff --git a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageQueueTest.java b/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageQueueTest.java deleted file mode 100644 index 30b5d7ce096b..000000000000 --- a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageQueueTest.java +++ /dev/null @@ -1,48 +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.queue.load.leveling; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -/** - * - * Test case for submitting and retrieving messages from Blocking Queue. - * - */ -public class MessageQueueTest { - - @Test - public void messageQueueTest() { - - MessageQueue msgQueue = new MessageQueue(); - - // submit message - msgQueue.submitMsg(new Message("MessageQueue Test")); - - // retrieve message - assertEquals(msgQueue.retrieveMsg().getMsg(), "MessageQueue Test"); - } - -} diff --git a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageTest.java b/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageTest.java deleted file mode 100644 index 93ef723ea7e5..000000000000 --- a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageTest.java +++ /dev/null @@ -1,43 +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.queue.load.leveling; - -import org.junit.Test; -import static org.junit.Assert.assertEquals; - -/** - * - * Test case for creating and checking the Message. - * - */ -public class MessageTest { - - @Test - public void messageTest() { - - // Parameterized constructor test. - String testMsg = "Message Test"; - Message msg = new Message(testMsg); - assertEquals(msg.getMsg(), testMsg); - } -} diff --git a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/TaskGenSrvExeTest.java b/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/TaskGenSrvExeTest.java deleted file mode 100644 index a773c377e9f0..000000000000 --- a/queue-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/TaskGenSrvExeTest.java +++ /dev/null @@ -1,50 +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.queue.load.leveling; - -import org.junit.Test; - -/** - * - * Test case for submitting Message to Blocking Queue by TaskGenerator - * and retrieve the message by ServiceExecutor. - * - */ -public class TaskGenSrvExeTest { - - @Test - public void taskGeneratorTest() { - MessageQueue msgQueue = new MessageQueue(); - - // Create a task generator thread with 1 job to submit. - Runnable taskRunnable = new TaskGenerator(msgQueue, 1); - Thread taskGenThr = new Thread(taskRunnable); - taskGenThr.start(); - - // Create a service executor thread. - Runnable srvRunnable = new ServiceExecutor(msgQueue); - Thread srvExeThr = new Thread(srvRunnable); - srvExeThr.start(); - } - -} diff --git a/reactor/README.md b/reactor/README.md deleted file mode 100644 index 68461cfdd9ab..000000000000 --- a/reactor/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: pattern -title: Reactor -folder: reactor -permalink: /patterns/reactor/ -pumlid: DSR14OGm20NGLjO23FVj1f7Hx2Ga0nzjVxtuJc-f9YrtJM-V4vZn9NA-or5nvfQXBiEWXYAZKsrvCzZfnnUlkqOzR9qCg5jGvtX2hYmOJWfvNz9xcTdR7m00 -pumlformat: svg -categories: Concurrency -tags: - - Java - - Difficulty-Expert - - I/O ---- - -## Intent -The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients. The application can register specific handlers for processing which are called by reactor on specific events. Dispatching of event handlers is performed by an initiation dispatcher, which manages the registered event handlers. Demultiplexing of service requests is performed by a synchronous event demultiplexer. - -![Reactor](./etc/reactor.png "Reactor") - -## Applicability -Use Reactor pattern when - -* a server application needs to handle concurrent service requests from multiple clients. -* a server application needs to be available for receiving requests from new clients even when handling older client requests. -* a server must maximize throughput, minimize latency and use CPU efficiently without blocking. - -## Real world examples - -* [Spring Reactor](http://projectreactor.io/) - -## Credits - -* [Douglas C. Schmidt - Reactor](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor.pdf) -* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697) -* [Doug Lea - Scalable IO in Java](http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf) -* [Netty](http://netty.io/) diff --git a/reactor/etc/reactor.png b/reactor/etc/reactor.png deleted file mode 100644 index abe705682f6c912858dcac8433e2495a1fec4fd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125804 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 diff --git a/reactor/etc/reactor.ucls b/reactor/etc/reactor.ucls deleted file mode 100644 index 90e28cdd7603..000000000000 --- a/reactor/etc/reactor.ucls +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/reactor/etc/reactor.urm.puml b/reactor/etc/reactor.urm.puml deleted file mode 100644 index 1ce92cab2ba6..000000000000 --- a/reactor/etc/reactor.urm.puml +++ /dev/null @@ -1,156 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.reactor.framework { - abstract class AbstractNioChannel { - - channel : SelectableChannel - - channelToPendingWrites : Map> - - handler : ChannelHandler - - reactor : NioReactor - + AbstractNioChannel(handler : ChannelHandler, channel : SelectableChannel) - + bind() {abstract} - # doWrite(Object, SelectionKey) {abstract} - ~ flush(key : SelectionKey) - + getHandler() : ChannelHandler - + getInterestedOps() : int {abstract} - + getJavaChannel() : SelectableChannel - + read(SelectionKey) : Object {abstract} - ~ setReactor(reactor : NioReactor) - + write(data : Object, key : SelectionKey) - } - interface ChannelHandler { - + handleChannelRead(AbstractNioChannel, Object, SelectionKey) {abstract} - } - interface Dispatcher { - + onChannelReadEvent(AbstractNioChannel, Object, SelectionKey) {abstract} - + stop() {abstract} - } - class NioDatagramChannel { - - LOGGER : Logger {static} - - port : int - + NioDatagramChannel(port : int, handler : ChannelHandler) - + bind() - # doWrite(pendingWrite : Object, key : SelectionKey) - + getInterestedOps() : int - + getJavaChannel() : DatagramChannel - + read(key : SelectionKey) : DatagramPacket - + write(data : Object, key : SelectionKey) - } - class DatagramPacket { - - data : ByteBuffer - - receiver : SocketAddress - - sender : SocketAddress - + DatagramPacket(data : ByteBuffer) - + getData() : ByteBuffer - + getReceiver() : SocketAddress - + getSender() : SocketAddress - + setReceiver(receiver : SocketAddress) - + setSender(sender : SocketAddress) - } - class NioReactor { - - LOGGER : Logger {static} - - dispatcher : Dispatcher - - pendingCommands : Queue - - reactorMain : ExecutorService - - selector : Selector - + NioReactor(dispatcher : Dispatcher) - + changeOps(key : SelectionKey, interestedOps : int) - - dispatchReadEvent(key : SelectionKey, readObject : Object) - - eventLoop() - - onChannelAcceptable(key : SelectionKey) - - onChannelReadable(key : SelectionKey) - - onChannelWritable(key : SelectionKey) {static} - - processKey(key : SelectionKey) - - processPendingCommands() - + registerChannel(channel : AbstractNioChannel) : NioReactor - + start() - + stop() - } - ~class ChangeKeyOpsCommand { - - interestedOps : int - - key : SelectionKey - + ChangeKeyOpsCommand(this$0 : SelectionKey, key : int) - + run() - + toString() : String - } - class NioServerSocketChannel { - - LOGGER : Logger {static} - - port : int - + NioServerSocketChannel(port : int, handler : ChannelHandler) - + bind() - # doWrite(pendingWrite : Object, key : SelectionKey) - + getInterestedOps() : int - + getJavaChannel() : ServerSocketChannel - + read(key : SelectionKey) : ByteBuffer - } - class SameThreadDispatcher { - + SameThreadDispatcher() - + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - + stop() - } - class ThreadPoolDispatcher { - - executorService : ExecutorService - + ThreadPoolDispatcher(poolSize : int) - + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - + stop() - } -} -package com.iluwatar.reactor.app { - class App { - - channels : List - - dispatcher : Dispatcher - - reactor : NioReactor - + App(dispatcher : Dispatcher) - + main(args : String[]) {static} - + start() - + stop() - - tcpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel - - udpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel - } - class AppClient { - - LOGGER : Logger {static} - - service : ExecutorService - + AppClient() - - artificialDelayOf(millis : long) {static} - + main(args : String[]) {static} - + start() - + stop() - } - ~class TcpLoggingClient { - - clientName : String - - serverPort : int - + TcpLoggingClient(clientName : String, serverPort : int) - + run() - - sendLogRequests(writer : PrintWriter, inputStream : InputStream) - } - ~class UdpLoggingClient { - - clientName : String - - remoteAddress : InetSocketAddress - + UdpLoggingClient(clientName : String, port : int) - + run() - } - class LoggingHandler { - - ACK : byte[] {static} - - LOGGER : Logger {static} - + LoggingHandler() - - doLogging(data : ByteBuffer) {static} - + handleChannelRead(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - - sendReply(channel : AbstractNioChannel, incomingPacket : DatagramPacket, key : SelectionKey) {static} - - sendReply(channel : AbstractNioChannel, key : SelectionKey) {static} - } -} -AbstractNioChannel --> "-handler" ChannelHandler -UdpLoggingClient ..+ AppClient -TcpLoggingClient ..+ AppClient -AbstractNioChannel --> "-reactor" NioReactor -NioReactor --> "-dispatcher" Dispatcher -App --> "-reactor" NioReactor -App --> "-channels" AbstractNioChannel -DatagramPacket ..+ NioDatagramChannel -App --> "-dispatcher" Dispatcher -ChangeKeyOpsCommand --+ NioReactor -LoggingHandler ..|> ChannelHandler -NioDatagramChannel --|> AbstractNioChannel -NioServerSocketChannel --|> AbstractNioChannel -SameThreadDispatcher ..|> Dispatcher -ThreadPoolDispatcher ..|> Dispatcher -@enduml diff --git a/reactor/pom.xml b/reactor/pom.xml deleted file mode 100644 index 9ab44d2c05a8..000000000000 --- a/reactor/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - reactor - - - junit - junit - test - - - diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/App.java b/reactor/src/main/java/com/iluwatar/reactor/app/App.java deleted file mode 100644 index 5208dea024a9..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/app/App.java +++ /dev/null @@ -1,163 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.app; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.iluwatar.reactor.framework.AbstractNioChannel; -import com.iluwatar.reactor.framework.ChannelHandler; -import com.iluwatar.reactor.framework.Dispatcher; -import com.iluwatar.reactor.framework.NioDatagramChannel; -import com.iluwatar.reactor.framework.NioReactor; -import com.iluwatar.reactor.framework.NioServerSocketChannel; -import com.iluwatar.reactor.framework.ThreadPoolDispatcher; - -/** - * This application demonstrates Reactor pattern. The example demonstrated is a Distributed Logging - * Service where it listens on multiple TCP or UDP sockets for incoming log requests. - * - *

    - * INTENT
    - * The Reactor design pattern handles service requests that are delivered concurrently to an - * application by one or more clients. The application can register specific handlers for processing - * which are called by reactor on specific events. - * - *

    - * PROBLEM
    - * Server applications in a distributed system must handle multiple clients that send them service - * requests. Following forces need to be resolved: - *

      - *
    • Availability
    • - *
    • Efficiency
    • - *
    • Programming Simplicity
    • - *
    • Adaptability
    • - *
    - * - *

    - * PARTICIPANTS
    - *

      - *
    • Synchronous Event De-multiplexer
    • {@link NioReactor} plays the role of synchronous event - * de-multiplexer. It waits for events on multiple channels registered to it in an event loop. - * - *

      - *

    • Initiation Dispatcher
    • {@link NioReactor} plays this role as the application specific - * {@link ChannelHandler}s are registered to the reactor. - * - *

      - *

    • Handle
    • {@link AbstractNioChannel} acts as a handle that is registered to the reactor. - * When any events occur on a handle, reactor calls the appropriate handler. - * - *

      - *

    • Event Handler
    • {@link ChannelHandler} acts as an event handler, which is bound to a - * channel and is called back when any event occurs on any of its associated handles. Application - * logic resides in event handlers. - *
    - * - *

    - * The application utilizes single thread to listen for requests on all ports. It does not create a - * separate thread for each client, which provides better scalability under load (number of clients - * increase). - * - *

    - * The example uses Java NIO framework to implement the Reactor. - * - */ -public class App { - - private NioReactor reactor; - private List channels = new ArrayList<>(); - private Dispatcher dispatcher; - - /** - * Creates an instance of App which will use provided dispatcher for dispatching events on - * reactor. - * - * @param dispatcher the dispatcher that will be used to dispatch events. - */ - public App(Dispatcher dispatcher) { - this.dispatcher = dispatcher; - } - - /** - * App entry. - */ - public static void main(String[] args) throws IOException { - new App(new ThreadPoolDispatcher(2)).start(); - } - - /** - * Starts the NIO reactor. - * - * @throws IOException if any channel fails to bind. - */ - public void start() throws IOException { - /* - * The application can customize its event dispatching mechanism. - */ - reactor = new NioReactor(dispatcher); - - /* - * This represents application specific business logic that dispatcher will call on appropriate - * events. These events are read events in our example. - */ - LoggingHandler loggingHandler = new LoggingHandler(); - - /* - * Our application binds to multiple channels and uses same logging handler to handle incoming - * log requests. - */ - reactor.registerChannel(tcpChannel(6666, loggingHandler)) - .registerChannel(tcpChannel(6667, loggingHandler)) - .registerChannel(udpChannel(6668, loggingHandler)).start(); - } - - /** - * Stops the NIO reactor. This is a blocking call. - * - * @throws InterruptedException if interrupted while stopping the reactor. - * @throws IOException if any I/O error occurs - */ - public void stop() throws InterruptedException, IOException { - reactor.stop(); - dispatcher.stop(); - for (AbstractNioChannel channel : channels) { - channel.getJavaChannel().close(); - } - } - - private AbstractNioChannel tcpChannel(int port, ChannelHandler handler) throws IOException { - NioServerSocketChannel channel = new NioServerSocketChannel(port, handler); - channel.bind(); - channels.add(channel); - return channel; - } - - private AbstractNioChannel udpChannel(int port, ChannelHandler handler) throws IOException { - NioDatagramChannel channel = new NioDatagramChannel(port, handler); - channel.bind(); - channels.add(channel); - return channel; - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java deleted file mode 100644 index 446628769c2a..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java +++ /dev/null @@ -1,194 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.io.PrintWriter; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * Represents the clients of Reactor pattern. Multiple clients are run concurrently and send logging - * requests to Reactor. - */ -public class AppClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(AppClient.class); - - private final ExecutorService service = Executors.newFixedThreadPool(4); - - /** - * App client entry. - * - * @throws IOException if any I/O error occurs. - */ - public static void main(String[] args) throws IOException { - AppClient appClient = new AppClient(); - appClient.start(); - } - - /** - * Starts the logging clients. - * - * @throws IOException if any I/O error occurs. - */ - public void start() throws IOException { - LOGGER.info("Starting logging clients"); - service.execute(new TcpLoggingClient("Client 1", 6666)); - service.execute(new TcpLoggingClient("Client 2", 6667)); - service.execute(new UdpLoggingClient("Client 3", 6668)); - service.execute(new UdpLoggingClient("Client 4", 6668)); - } - - /** - * Stops logging clients. This is a blocking call. - */ - public void stop() { - service.shutdown(); - if (!service.isTerminated()) { - service.shutdownNow(); - try { - service.awaitTermination(1000, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("exception awaiting termination", e); - } - } - LOGGER.info("Logging clients stopped"); - } - - private static void artificialDelayOf(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - LOGGER.error("sleep interrupted", e); - } - } - - /** - * A logging client that sends requests to Reactor on TCP socket. - */ - static class TcpLoggingClient implements Runnable { - - private final int serverPort; - private final String clientName; - - /** - * Creates a new TCP logging client. - * - * @param clientName the name of the client to be sent in logging requests. - * @param port the port on which client will send logging requests. - */ - public TcpLoggingClient(String clientName, int serverPort) { - this.clientName = clientName; - this.serverPort = serverPort; - } - - public void run() { - try (Socket socket = new Socket(InetAddress.getLocalHost(), serverPort)) { - OutputStream outputStream = socket.getOutputStream(); - PrintWriter writer = new PrintWriter(outputStream); - sendLogRequests(writer, socket.getInputStream()); - } catch (IOException e) { - LOGGER.error("error sending requests", e); - throw new RuntimeException(e); - } - } - - private void sendLogRequests(PrintWriter writer, InputStream inputStream) throws IOException { - for (int i = 0; i < 4; i++) { - writer.println(clientName + " - Log request: " + i); - writer.flush(); - - byte[] data = new byte[1024]; - int read = inputStream.read(data, 0, data.length); - if (read == 0) { - LOGGER.info("Read zero bytes"); - } else { - LOGGER.info(new String(data, 0, read)); - } - - artificialDelayOf(100); - } - } - - } - - /** - * A logging client that sends requests to Reactor on UDP socket. - */ - static class UdpLoggingClient implements Runnable { - private final String clientName; - private final InetSocketAddress remoteAddress; - - /** - * Creates a new UDP logging client. - * - * @param clientName the name of the client to be sent in logging requests. - * @param port the port on which client will send logging requests. - * @throws UnknownHostException if localhost is unknown - */ - public UdpLoggingClient(String clientName, int port) throws UnknownHostException { - this.clientName = clientName; - this.remoteAddress = new InetSocketAddress(InetAddress.getLocalHost(), port); - } - - @Override - public void run() { - try (DatagramSocket socket = new DatagramSocket()) { - for (int i = 0; i < 4; i++) { - - String message = clientName + " - Log request: " + i; - DatagramPacket request = - new DatagramPacket(message.getBytes(), message.getBytes().length, remoteAddress); - - socket.send(request); - - byte[] data = new byte[1024]; - DatagramPacket reply = new DatagramPacket(data, data.length); - socket.receive(reply); - if (reply.getLength() == 0) { - LOGGER.info("Read zero bytes"); - } else { - LOGGER.info(new String(reply.getData(), 0, reply.getLength())); - } - - artificialDelayOf(100); - } - } catch (IOException e1) { - LOGGER.error("error sending packets", e1); - } - } - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java b/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java deleted file mode 100644 index 8584702c75d0..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.app; - -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; - -import com.iluwatar.reactor.framework.AbstractNioChannel; -import com.iluwatar.reactor.framework.ChannelHandler; -import com.iluwatar.reactor.framework.NioDatagramChannel.DatagramPacket; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Logging server application logic. It logs the incoming requests on standard console and returns a - * canned acknowledgement back to the remote peer. - */ -public class LoggingHandler implements ChannelHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(LoggingHandler.class); - - private static final byte[] ACK = "Data logged successfully".getBytes(); - - /** - * Decodes the received data and logs it on standard console. - */ - @Override - public void handleChannelRead(AbstractNioChannel channel, Object readObject, SelectionKey key) { - /* - * As this handler is attached with both TCP and UDP channels we need to check whether the data - * received is a ByteBuffer (from TCP channel) or a DatagramPacket (from UDP channel). - */ - if (readObject instanceof ByteBuffer) { - doLogging((ByteBuffer) readObject); - sendReply(channel, key); - } else if (readObject instanceof DatagramPacket) { - DatagramPacket datagram = (DatagramPacket) readObject; - doLogging(datagram.getData()); - sendReply(channel, datagram, key); - } else { - throw new IllegalStateException("Unknown data received"); - } - } - - private static void sendReply(AbstractNioChannel channel, DatagramPacket incomingPacket, SelectionKey key) { - /* - * Create a reply acknowledgement datagram packet setting the receiver to the sender of incoming - * message. - */ - DatagramPacket replyPacket = new DatagramPacket(ByteBuffer.wrap(ACK)); - replyPacket.setReceiver(incomingPacket.getSender()); - - channel.write(replyPacket, key); - } - - private static void sendReply(AbstractNioChannel channel, SelectionKey key) { - ByteBuffer buffer = ByteBuffer.wrap(ACK); - channel.write(buffer, key); - } - - private static void doLogging(ByteBuffer data) { - // assuming UTF-8 :( - LOGGER.info(new String(data.array(), 0, data.limit())); - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java deleted file mode 100644 index aa7d703ce9af..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.framework; - -import java.io.IOException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * This represents the Handle of Reactor pattern. These are resources managed by OS which can - * be submitted to {@link NioReactor}. - * - *

    - * This class serves has the responsibility of reading the data when a read event occurs and writing - * the data back when the channel is writable. It leaves the reading and writing of data on the - * concrete implementation. It provides a block writing mechanism wherein when any - * {@link ChannelHandler} wants to write data back, it queues the data in pending write queue and - * clears it in block manner. This provides better throughput. - */ -public abstract class AbstractNioChannel { - - private final SelectableChannel channel; - private final ChannelHandler handler; - private final Map> channelToPendingWrites = - new ConcurrentHashMap<>(); - private NioReactor reactor; - - /** - * Creates a new channel. - * - * @param handler which will handle events occurring on this channel. - * @param channel a NIO channel to be wrapped. - */ - public AbstractNioChannel(ChannelHandler handler, SelectableChannel channel) { - this.handler = handler; - this.channel = channel; - } - - /** - * Injects the reactor in this channel. - */ - void setReactor(NioReactor reactor) { - this.reactor = reactor; - } - - /** - * @return the wrapped NIO channel. - */ - public SelectableChannel getJavaChannel() { - return channel; - } - - /** - * The operation in which the channel is interested, this operation is provided to - * {@link Selector}. - * - * @return interested operation. - * @see SelectionKey - */ - public abstract int getInterestedOps(); - - /** - * Binds the channel on provided port. - * - * @throws IOException if any I/O error occurs. - */ - public abstract void bind() throws IOException; - - /** - * Reads the data using the key and returns the read data. The underlying channel should be - * fetched using {@link SelectionKey#channel()}. - * - * @param key the key on which read event occurred. - * @return data read. - * @throws IOException if any I/O error occurs. - */ - public abstract Object read(SelectionKey key) throws IOException; - - /** - * @return the handler associated with this channel. - */ - public ChannelHandler getHandler() { - return handler; - } - - /* - * Called from the context of reactor thread when the key becomes writable. The channel writes the - * whole pending block of data at once. - */ - void flush(SelectionKey key) throws IOException { - Queue pendingWrites = channelToPendingWrites.get(key.channel()); - while (true) { - Object pendingWrite = pendingWrites.poll(); - if (pendingWrite == null) { - // We don't have anything more to write so channel is interested in reading more data - reactor.changeOps(key, SelectionKey.OP_READ); - break; - } - - // ask the concrete channel to make sense of data and write it to java channel - doWrite(pendingWrite, key); - } - } - - /** - * Writes the data to the channel. - * - * @param pendingWrite the data to be written on channel. - * @param key the key which is writable. - * @throws IOException if any I/O error occurs. - */ - protected abstract void doWrite(Object pendingWrite, SelectionKey key) throws IOException; - - /** - * Queues the data for writing. The data is not guaranteed to be written on underlying channel - * when this method returns. It will be written when the channel is flushed. - * - *

    - * This method is used by the {@link ChannelHandler} to send reply back to the client.
    - * Example: - * - *

    -   * 
    -   * {@literal @}Override
    -   * public void handleChannelRead(AbstractNioChannel channel, Object readObject, SelectionKey key) {
    -   *   byte[] data = ((ByteBuffer)readObject).array();
    -   *   ByteBuffer buffer = ByteBuffer.wrap("Server reply".getBytes());
    -   *   channel.write(buffer, key);
    -   * }
    -   * 
    -   * 
    - * - * @param data the data to be written on underlying channel. - * @param key the key which is writable. - */ - public void write(Object data, SelectionKey key) { - Queue pendingWrites = this.channelToPendingWrites.get(key.channel()); - if (pendingWrites == null) { - synchronized (this.channelToPendingWrites) { - pendingWrites = this.channelToPendingWrites.get(key.channel()); - if (pendingWrites == null) { - pendingWrites = new ConcurrentLinkedQueue<>(); - this.channelToPendingWrites.put(key.channel(), pendingWrites); - } - } - } - pendingWrites.add(data); - reactor.changeOps(key, SelectionKey.OP_WRITE); - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java b/reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java deleted file mode 100644 index 6391436ce70a..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.framework; - -import java.nio.channels.SelectionKey; - -/** - * Represents the EventHandler of Reactor pattern. It handles the incoming events dispatched - * to it by the {@link Dispatcher}. This is where the application logic resides. - * - *

    - * A {@link ChannelHandler} can be associated with one or many {@link AbstractNioChannel}s, and - * whenever an event occurs on any of the associated channels, the handler is notified of the event. - */ -public interface ChannelHandler { - - /** - * Called when the {@code channel} receives some data from remote peer. - * - * @param channel the channel from which the data was received. - * @param readObject the data read. - * @param key the key on which read event occurred. - */ - void handleChannelRead(AbstractNioChannel channel, Object readObject, SelectionKey key); -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java deleted file mode 100644 index a3fe187a36a7..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.framework; - -import java.nio.channels.SelectionKey; - -/** - * Represents the event dispatching strategy. When {@link NioReactor} senses any event on the - * registered {@link AbstractNioChannel}s then it de-multiplexes the event type, read or write or - * connect, and then calls the {@link Dispatcher} to dispatch the read events. This decouples the - * I/O processing from application specific processing.
    - * Dispatcher should call the {@link ChannelHandler} associated with the channel on which event - * occurred. - * - *

    - * The application can customize the way in which event is dispatched such as using the reactor - * thread to dispatch event to channels or use a worker pool to do the non I/O processing. - * - * @see SameThreadDispatcher - * @see ThreadPoolDispatcher - */ -public interface Dispatcher { - /** - * This hook method is called when read event occurs on particular channel. The data read is - * provided in readObject. The implementation should dispatch this read event to the - * associated {@link ChannelHandler} of channel. - * - *

    - * The type of readObject depends on the channel on which data was received. - * - * @param channel on which read event occurred - * @param readObject object read by channel - * @param key on which event occurred - */ - void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key); - - /** - * Stops dispatching events and cleans up any acquired resources such as threads. - * - * @throws InterruptedException if interrupted while stopping dispatcher. - */ - void stop() throws InterruptedException; -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java deleted file mode 100644 index 36171cf67bbc..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java +++ /dev/null @@ -1,186 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.DatagramChannel; -import java.nio.channels.SelectionKey; - -/** - * A wrapper over {@link DatagramChannel} which can read and write data on a DatagramChannel. - */ -public class NioDatagramChannel extends AbstractNioChannel { - - private static final Logger LOGGER = LoggerFactory.getLogger(NioDatagramChannel.class); - - private final int port; - - /** - * Creates a {@link DatagramChannel} which will bind at provided port and use handler - * to handle incoming events on this channel. - *

    - * Note the constructor does not bind the socket, {@link #bind()} method should be called for - * binding the socket. - * - * @param port the port to be bound to listen for incoming datagram requests. - * @param handler the handler to be used for handling incoming requests on this channel. - * @throws IOException if any I/O error occurs. - */ - public NioDatagramChannel(int port, ChannelHandler handler) throws IOException { - super(handler, DatagramChannel.open()); - this.port = port; - } - - @Override - public int getInterestedOps() { - /* - * there is no need to accept connections in UDP, so the channel shows interest in reading data. - */ - return SelectionKey.OP_READ; - } - - /** - * Reads and returns a {@link DatagramPacket} from the underlying channel. - * - * @return the datagram packet read having the sender address. - */ - @Override - public DatagramPacket read(SelectionKey key) throws IOException { - ByteBuffer buffer = ByteBuffer.allocate(1024); - SocketAddress sender = ((DatagramChannel) key.channel()).receive(buffer); - - /* - * It is required to create a DatagramPacket because we need to preserve which socket address - * acts as destination for sending reply packets. - */ - buffer.flip(); - DatagramPacket packet = new DatagramPacket(buffer); - packet.setSender(sender); - - return packet; - } - - /** - * @return the underlying datagram channel. - */ - @Override - public DatagramChannel getJavaChannel() { - return (DatagramChannel) super.getJavaChannel(); - } - - /** - * Binds UDP socket on the provided port. - * - * @throws IOException if any I/O error occurs. - */ - @Override - public void bind() throws IOException { - getJavaChannel().socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), port)); - getJavaChannel().configureBlocking(false); - LOGGER.info("Bound UDP socket at port: {}", port); - } - - /** - * Writes the pending {@link DatagramPacket} to the underlying channel sending data to the - * intended receiver of the packet. - */ - @Override - protected void doWrite(Object pendingWrite, SelectionKey key) throws IOException { - DatagramPacket pendingPacket = (DatagramPacket) pendingWrite; - getJavaChannel().send(pendingPacket.getData(), pendingPacket.getReceiver()); - } - - /** - * Writes the outgoing {@link DatagramPacket} to the channel. The intended receiver of the - * datagram packet must be set in the data using - * {@link DatagramPacket#setReceiver(SocketAddress)}. - */ - @Override - public void write(Object data, SelectionKey key) { - super.write(data, key); - } - - /** - * Container of data used for {@link NioDatagramChannel} to communicate with remote peer. - */ - public static class DatagramPacket { - private SocketAddress sender; - private ByteBuffer data; - private SocketAddress receiver; - - /** - * Creates a container with underlying data. - * - * @param data the underlying message to be written on channel. - */ - public DatagramPacket(ByteBuffer data) { - this.data = data; - } - - /** - * @return the sender address. - */ - public SocketAddress getSender() { - return sender; - } - - /** - * Sets the sender address of this packet. - * - * @param sender the sender address. - */ - public void setSender(SocketAddress sender) { - this.sender = sender; - } - - /** - * @return the receiver address. - */ - public SocketAddress getReceiver() { - return receiver; - } - - /** - * Sets the intended receiver address. This must be set when writing to the channel. - * - * @param receiver the receiver address. - */ - public void setReceiver(SocketAddress receiver) { - this.receiver = receiver; - } - - /** - * @return the underlying message that will be written on channel. - */ - public ByteBuffer getData() { - return data; - } - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java deleted file mode 100644 index a315389a3152..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java +++ /dev/null @@ -1,267 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.Iterator; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * This class acts as Synchronous Event De-multiplexer and Initiation Dispatcher of Reactor pattern. Multiple handles - * i.e. {@link AbstractNioChannel}s can be registered to the reactor and it blocks for events from all these handles. - * Whenever an event occurs on any of the registered handles, it synchronously de-multiplexes the event which can be any - * of read, write or accept, and dispatches the event to the appropriate {@link ChannelHandler} using the - * {@link Dispatcher}. - * - *

    - * Implementation: A NIO reactor runs in its own thread when it is started using {@link #start()} method. - * {@link NioReactor} uses {@link Selector} for realizing Synchronous Event De-multiplexing. - * - *

    - * NOTE: This is one of the ways to implement NIO reactor and it does not take care of all possible edge cases which are - * required in a real application. This implementation is meant to demonstrate the fundamental concepts that lie behind - * Reactor pattern. - */ -public class NioReactor { - - private static final Logger LOGGER = LoggerFactory.getLogger(NioReactor.class); - - private final Selector selector; - private final Dispatcher dispatcher; - /** - * All the work of altering the SelectionKey operations and Selector operations are performed in the context of main - * event loop of reactor. So when any channel needs to change its readability or writability, a new command is added - * in the command queue and then the event loop picks up the command and executes it in next iteration. - */ - private final Queue pendingCommands = new ConcurrentLinkedQueue<>(); - private final ExecutorService reactorMain = Executors.newSingleThreadExecutor(); - - /** - * Creates a reactor which will use provided {@code dispatcher} to dispatch events. The application can provide - * various implementations of dispatcher which suits its needs. - * - * @param dispatcher - * a non-null dispatcher used to dispatch events on registered channels. - * @throws IOException - * if any I/O error occurs. - */ - public NioReactor(Dispatcher dispatcher) throws IOException { - this.dispatcher = dispatcher; - this.selector = Selector.open(); - } - - /** - * Starts the reactor event loop in a new thread. - * - * @throws IOException - * if any I/O error occurs. - */ - public void start() throws IOException { - reactorMain.execute(() -> { - try { - LOGGER.info("Reactor started, waiting for events..."); - eventLoop(); - } catch (IOException e) { - LOGGER.error("exception in event loop", e); - } - }); - } - - /** - * Stops the reactor and related resources such as dispatcher. - * - * @throws InterruptedException - * if interrupted while stopping the reactor. - * @throws IOException - * if any I/O error occurs. - */ - public void stop() throws InterruptedException, IOException { - reactorMain.shutdownNow(); - selector.wakeup(); - reactorMain.awaitTermination(4, TimeUnit.SECONDS); - selector.close(); - LOGGER.info("Reactor stopped"); - } - - /** - * Registers a new channel (handle) with this reactor. Reactor will start waiting for events on this channel and - * notify of any events. While registering the channel the reactor uses {@link AbstractNioChannel#getInterestedOps()} - * to know about the interested operation of this channel. - * - * @param channel - * a new channel on which reactor will wait for events. The channel must be bound prior to being registered. - * @return this - * @throws IOException - * if any I/O error occurs. - */ - public NioReactor registerChannel(AbstractNioChannel channel) throws IOException { - SelectionKey key = channel.getJavaChannel().register(selector, channel.getInterestedOps()); - key.attach(channel); - channel.setReactor(this); - return this; - } - - private void eventLoop() throws IOException { - while (true) { - - // honor interrupt request - if (Thread.interrupted()) { - break; - } - - // honor any pending commands first - processPendingCommands(); - - /* - * Synchronous event de-multiplexing happens here, this is blocking call which returns when it is possible to - * initiate non-blocking operation on any of the registered channels. - */ - selector.select(); - - /* - * Represents the events that have occurred on registered handles. - */ - Set keys = selector.selectedKeys(); - - Iterator iterator = keys.iterator(); - - while (iterator.hasNext()) { - SelectionKey key = iterator.next(); - if (!key.isValid()) { - iterator.remove(); - continue; - } - processKey(key); - } - keys.clear(); - } - } - - private void processPendingCommands() { - Iterator iterator = pendingCommands.iterator(); - while (iterator.hasNext()) { - Runnable command = iterator.next(); - command.run(); - iterator.remove(); - } - } - - /* - * Initiation dispatcher logic, it checks the type of event and notifier application specific event handler to handle - * the event. - */ - private void processKey(SelectionKey key) throws IOException { - if (key.isAcceptable()) { - onChannelAcceptable(key); - } else if (key.isReadable()) { - onChannelReadable(key); - } else if (key.isWritable()) { - onChannelWritable(key); - } - } - - private static void onChannelWritable(SelectionKey key) throws IOException { - AbstractNioChannel channel = (AbstractNioChannel) key.attachment(); - channel.flush(key); - } - - private void onChannelReadable(SelectionKey key) { - try { - // reads the incoming data in context of reactor main loop. Can this be improved? - Object readObject = ((AbstractNioChannel) key.attachment()).read(key); - - dispatchReadEvent(key, readObject); - } catch (IOException e) { - try { - key.channel().close(); - } catch (IOException e1) { - LOGGER.error("error closing channel", e1); - } - } - } - - /* - * Uses the application provided dispatcher to dispatch events to application handler. - */ - private void dispatchReadEvent(SelectionKey key, Object readObject) { - dispatcher.onChannelReadEvent((AbstractNioChannel) key.attachment(), readObject, key); - } - - private void onChannelAcceptable(SelectionKey key) throws IOException { - ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); - SocketChannel socketChannel = serverSocketChannel.accept(); - socketChannel.configureBlocking(false); - SelectionKey readKey = socketChannel.register(selector, SelectionKey.OP_READ); - readKey.attach(key.attachment()); - } - - /** - * Queues the change of operations request of a channel, which will change the interested operations of the channel - * sometime in future. - *

    - * This is a non-blocking method and does not guarantee that the operations have changed when this method returns. - * - * @param key - * the key for which operations have to be changed. - * @param interestedOps - * the new interest operations. - */ - public void changeOps(SelectionKey key, int interestedOps) { - pendingCommands.add(new ChangeKeyOpsCommand(key, interestedOps)); - selector.wakeup(); - } - - /** - * A command that changes the interested operations of the key provided. - */ - class ChangeKeyOpsCommand implements Runnable { - private SelectionKey key; - private int interestedOps; - - public ChangeKeyOpsCommand(SelectionKey key, int interestedOps) { - this.key = key; - this.interestedOps = interestedOps; - } - - public void run() { - key.interestOps(interestedOps); - } - - @Override - public String toString() { - return "Change of ops to: " + interestedOps; - } - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java deleted file mode 100644 index 4721d292a673..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; - -/** - * A wrapper over {@link NioServerSocketChannel} which can read and write data on a - * {@link SocketChannel}. - */ -public class NioServerSocketChannel extends AbstractNioChannel { - - private static final Logger LOGGER = LoggerFactory.getLogger(NioServerSocketChannel.class); - - private final int port; - - /** - * Creates a {@link ServerSocketChannel} which will bind at provided port and use - * handler to handle incoming events on this channel. - *

    - * Note the constructor does not bind the socket, {@link #bind()} method should be called for - * binding the socket. - * - * @param port the port on which channel will be bound to accept incoming connection requests. - * @param handler the handler that will handle incoming requests on this channel. - * @throws IOException if any I/O error occurs. - */ - public NioServerSocketChannel(int port, ChannelHandler handler) throws IOException { - super(handler, ServerSocketChannel.open()); - this.port = port; - } - - - @Override - public int getInterestedOps() { - // being a server socket channel it is interested in accepting connection from remote peers. - return SelectionKey.OP_ACCEPT; - } - - /** - * @return the underlying {@link ServerSocketChannel}. - */ - @Override - public ServerSocketChannel getJavaChannel() { - return (ServerSocketChannel) super.getJavaChannel(); - } - - /** - * Reads and returns {@link ByteBuffer} from the underlying {@link SocketChannel} represented by - * the key. Due to the fact that there is a dedicated channel for each client - * connection we don't need to store the sender. - */ - @Override - public ByteBuffer read(SelectionKey key) throws IOException { - SocketChannel socketChannel = (SocketChannel) key.channel(); - ByteBuffer buffer = ByteBuffer.allocate(1024); - int read = socketChannel.read(buffer); - buffer.flip(); - if (read == -1) { - throw new IOException("Socket closed"); - } - return buffer; - } - - /** - * Binds TCP socket on the provided port. - * - * @throws IOException if any I/O error occurs. - */ - @Override - public void bind() throws IOException { - ((ServerSocketChannel) getJavaChannel()).socket().bind( - new InetSocketAddress(InetAddress.getLocalHost(), port)); - ((ServerSocketChannel) getJavaChannel()).configureBlocking(false); - LOGGER.info("Bound TCP socket at port: {}", port); - } - - /** - * Writes the pending {@link ByteBuffer} to the underlying channel sending data to the intended - * receiver of the packet. - */ - @Override - protected void doWrite(Object pendingWrite, SelectionKey key) throws IOException { - ByteBuffer pendingBuffer = (ByteBuffer) pendingWrite; - ((SocketChannel) key.channel()).write(pendingBuffer); - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java deleted file mode 100644 index 3db4f1e9a321..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.framework; - -import java.nio.channels.SelectionKey; - -/** - * Dispatches the events in the context of caller thread. This implementation is a good fit for - * small applications where there are limited clients. Using this implementation limits the - * scalability because the I/O thread performs the application specific processing. - * - *

    - * For better performance use {@link ThreadPoolDispatcher}. - * - * @see ThreadPoolDispatcher - */ -public class SameThreadDispatcher implements Dispatcher { - - /** - * Dispatches the read event in the context of caller thread.
    - * Note this is a blocking call. It returns only after the associated handler has handled the read - * event. - */ - @Override - public void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key) { - /* - * Calls the associated handler to notify the read event where application specific code - * resides. - */ - channel.getHandler().handleChannelRead(channel, readObject, key); - } - - /** - * No resources to free. - */ - @Override - public void stop() { - // no-op - } -} diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java deleted file mode 100644 index a43a974c9175..000000000000 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.framework; - -import java.nio.channels.SelectionKey; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * An implementation that uses a pool of worker threads to dispatch the events. This provides better - * scalability as the application specific processing is not performed in the context of I/O - * (reactor) thread. - */ -public class ThreadPoolDispatcher implements Dispatcher { - - private final ExecutorService executorService; - - /** - * Creates a pooled dispatcher with tunable pool size. - * - * @param poolSize number of pooled threads - */ - public ThreadPoolDispatcher(int poolSize) { - this.executorService = Executors.newFixedThreadPool(poolSize); - } - - /** - * Submits the work of dispatching the read event to worker pool, where it gets picked up by - * worker threads.
    - * Note that this is a non-blocking call and returns immediately. It is not guaranteed that the - * event has been handled by associated handler. - */ - @Override - public void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key) { - executorService.execute(() -> channel.getHandler().handleChannelRead(channel, readObject, key)); - } - - /** - * Stops the pool of workers. - * - * @throws InterruptedException if interrupted while stopping pool of workers. - */ - @Override - public void stop() throws InterruptedException { - executorService.shutdown(); - executorService.awaitTermination(4, TimeUnit.SECONDS); - } -} diff --git a/reactor/src/test/java/com/iluwatar/reactor/app/ReactorTest.java b/reactor/src/test/java/com/iluwatar/reactor/app/ReactorTest.java deleted file mode 100644 index 7aa80f8cca6c..000000000000 --- a/reactor/src/test/java/com/iluwatar/reactor/app/ReactorTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reactor.app; - -import java.io.IOException; - -import com.iluwatar.reactor.framework.NioReactor; -import org.junit.Test; - -import com.iluwatar.reactor.framework.SameThreadDispatcher; -import com.iluwatar.reactor.framework.ThreadPoolDispatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * This class tests the Distributed Logging service by starting a Reactor and then sending it - * concurrent logging requests using multiple clients. - */ -public class ReactorTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReactorTest.class); - - /** - * Test the application using pooled thread dispatcher. - * - * @throws IOException if any I/O error occurs. - * @throws InterruptedException if interrupted while stopping the application. - */ - @Test - public void testAppUsingThreadPoolDispatcher() throws IOException, InterruptedException { - LOGGER.info("testAppUsingThreadPoolDispatcher start"); - App app = new App(new ThreadPoolDispatcher(2)); - app.start(); - - AppClient client = new AppClient(); - client.start(); - - // allow clients to send requests. Artificial delay. - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - LOGGER.error("sleep interrupted", e); - } - - client.stop(); - - app.stop(); - LOGGER.info("testAppUsingThreadPoolDispatcher stop"); - } - - /** - * Test the application using same thread dispatcher. - * - * @throws IOException if any I/O error occurs. - * @throws InterruptedException if interrupted while stopping the application. - */ - @Test - public void testAppUsingSameThreadDispatcher() throws IOException, InterruptedException { - LOGGER.info("testAppUsingSameThreadDispatcher start"); - App app = new App(new SameThreadDispatcher()); - app.start(); - - AppClient client = new AppClient(); - client.start(); - - // allow clients to send requests. Artificial delay. - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - LOGGER.error("sleep interrupted", e); - } - - client.stop(); - - app.stop(); - LOGGER.info("testAppUsingSameThreadDispatcher stop"); - } -} diff --git a/reader-writer-lock/README.md b/reader-writer-lock/README.md deleted file mode 100644 index 556b9cd8541f..000000000000 --- a/reader-writer-lock/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -layout: pattern -title: Reader Writer Lock -folder: reader-writer-lock -permalink: /patterns/reader-writer-lock/ -pumlid: RSZB4S8m303HLg00MtUw4R8cCP5bZpwuVL80jttxx4gIZTFaSKOiVm4OxdhqEFETpaPJWpKgpG5TScEWmGU_M1fxFxGiZ61JXu5-1nXZOolR-gqYaoxWe3-xfeswSiWF -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate - - I/O - - Performance ---- - -**Intent:** - -Suppose we have a shared memory area with the basic constraints detailed above. It is possible to protect the shared data behind a mutual exclusion mutex, in which case no two threads can access the data at the same time. However, this solution is suboptimal, because it is possible that a reader R1 might have the lock, and then another reader R2 requests access. It would be foolish for R2 to wait until R1 was done before starting its own read operation; instead, R2 should start right away. This is the motivation for the Reader Writer Lock pattern. - -![alt text](./etc/reader-writer-lock.png "Reader writer lock") - -**Applicability:** - -Application need to increase the performance of resource synchronize for multiple thread, in particularly there are mixed read/write operations. - -**Real world examples:** - -* [Java Reader Writer Lock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html) - -**Credits** - -* [Readers–writer lock](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock) - -* [Readers–writers_problem](https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem) \ No newline at end of file diff --git a/reader-writer-lock/etc/reader-writer-lock.png b/reader-writer-lock/etc/reader-writer-lock.png deleted file mode 100644 index f7b6005309263d2dc8baf7505fd68091a580011b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39623 zcmbTeWkA$@*DXwUcZUi(bV-+>C?NFF(a0mu)aPSLg2;dXu0?kf1xXlQ~Hbt^tV5pj5h|I2*`;qwiG#Rcwf_1Mq+$4Q7N^H zj~q+8RB%g`i?UDDb?Sea$msw2eX6?2Di?k6bNY-@HjtAy#=B;Uid=j%yAe*vm!w94ZP!`bRp*TFsI!Nwl{~`J)dKI{U)`m<4hhv&#MN; zi}c=YPbhyNI(wcbRmj~$L{469G0CE0+n0PM8Hj`)(vjfk$mYB`;+brBbzZx)^lWf8 zEc|=mY9BW$7Mi^iyHcg?_}JKdBb7a6(#d|#d%`D@c}#kLE}(%0T)=&w+Y8u-L2Lpd zD27Yq;t4oN#4d}bUofKb37(>>%q3Xy-osw>)iA%LAmtO_D0<9HPB3WM^ZAh;XLxDp zvU08~#zkvbcu`=!hH;tcVp39)?T)5Iv3|j7-|nlGB3J9v{x8$kg8Y!g&mX&|lI15q zG^rseO-!jwRHJgfEoh{l%~*v%cg8qTo!VqSgv=KN({nUaGxR)SFocxd^}_K(5g97WGd~pV##)=S`+0h!1(iiA($ch|F1BcRE7o&Q z!8x~&Cjq9+QPiiVJIyxr@Jb07(B@8UBd)ws+T3TAKq(rM`J<63u zlNu?stN8^@mAr5x7It=?Nrhwi#3-($k_kpY>x1XS6N$_u;^I+%nQ9D#gNqoh7+evd zN`S0exLR(?&E&5MxH~In%CpMGI*QpEhH=;(ZDfT}X3`&Y#(W#qw)4CewrdK^cG!3w zFdS)b<+L%9-x==PvOZqoFN^wx0zm;)KNahoa9=#zD zaIqzNOj+9zHwl;`j^z;w5Wl%8lyKCF_Uw>^;A{tyKiJ| z`^$^DuOUtwudBb6pv9H_FcXVZ$Sex1sOZ?99d zMEG>#4K(ne6I9bjlo{hmzmS7WsOpVourjJtLJ#Og`JSfJK&ytbg=(>=tK#0LH zn@@bm<;hxbup-tAzTou_?k>f~eO&O@M=c>~r{|YvH@1;d;g?=wjfmSs%`kxxssco; zjh%<+9+F9oV&0U#O(x&9%YVS>%lM`j;b!m^l%Efkh-+%>s;RoI!cn0vSJ~iUR?RP=j<_O&*`8l_P`i_QnLUy5y zyYWaj-ePi;ym>-`VpcO~(&b(FY|chUO3+yPhs?}0rZv+HWF%}s>G?eC}O7CR*+zfO5 z8nEdbi8uxiJ=VII@y3=MrPXLUKR&x*V3)rz*wZgx%{Sc$7{0)h)6<+mYAEv?i&Sr6-Suk9jeFJ8VExBtDxbNH$=qhr^BPtV8StTRzTDn`%Z(>R zpWdbY`XG(uJGje}I!cfx%o=5e=`wFqovjzuLONFEZxbD0{71XNr1&f2o}# z+j||e;he<8YP6AWifN<2iB+9{yi0!3olFf`zb5{s>equRb1$P*!tPsL9KrQ$vBBox zFIBlDK|CGKi>RGvX|J&73Wl?x!!7BrPIjz(tRiXg`hAB{1RF*{fn3BhAvKoaevI+v z9rH`xM%bL`=dp5QxDTfTDNVRL<4Xdim zU7k_1z8PwYxmoJ?Qa)=LDtkUt^IEg`bbVvErdyC>)6c#8)8)2&r7go5cP{8obknsS zQ0Wunv9HfCW7)RD_d6-fMPCtcraOF2J4ufEC}Xtp?*2PCMztEj59&7><;Q7QFVIZ) zP!|P`-{4bq#1FcMeUD+J)R(FF*6!rsaCWvjeTq>?q%*+qtuOhdE>A}<=?;q}b-zd} zOgRT;Hd%&Gz~8*`MsKp~DduRvRc-a?`(6`(4Mt~OE&H3BE7!)-XA8=bMyH)D`E-B9 z1`EmWY}Z&Cwmqv^PJW`M26tZP{F`j*Ro&4@ZkO}_bej}QDaHuuNmN~S&jL+prIA!*Jm{M=f$m44G}D;ZcqO}YD96$Ck0b4i{TCL~ z8nBa-(<9Zt_@Z+0Sta|}@6LE`SrDrg8dn-idbB?QznLlgZP@ zZvokbQ~|TJv)CGZ)fXS$ds!qkbQuW7H#8dCAJQ#-%PbT>KN@A8x0|aMUuVB)w7en5 z8jl6&>cwcDdPiR&d0T|o&g*~fW&Z@W_1owcK=jjsbYwy{@aYhAG{-SRV9j}*9r_J3 z!FxZ;f4G|_ohwbZRtjVxHYbCo@lsGAN>QP;`23uH|6HKu1W{N@AQt+dkUuwr+ndeB zMGL$9qV2c(2b+xrIx~~j0`I9g7%Z);8BdSZ1m^sj$;GCs>xEplcfulS)h67IbT66e z(9d_O@-JzQ=NgvVeTwaDAkDVAjo<3FFj;WKWGr<$W7)%W;)4w%22Sl8)!eU+&PmzB znauhT-b3;Ss45jJ06s3Tb5G*QuET$38~!YLLXyJ0H2+M(Z`Z1F_9yyz&L!O;wOE3pnoyaRg*4+$3-^ocle!IDYw2Ugo@i z<-^C6_`(0&3djBRMHJ}e73uMZF%EN?!MyPcvBrmkH7dB4yxeGY8!>IuLD5@%#&B*g z5%e~9#*pSjV`=Y|v;TOf+*(*<86TgkC!@>%YSU~;XxVgFc@CrIvE+38>$XTOXhW-AbKwI}kvg!+gB@xTuqXZK! z0~xZ%72Z_ctj?SHt$7^sox{V(rX(gbG297gzEAD=bt)FyVTB%7`&|lg2?aZico#qA z%ssWnF1p-U*FqiRl?LO5ceAgjRk5}zjja2I{eB1Y*ur=qS4VsnWh%*f6Q!!<62#1| zMTM=~U3uz~GK%ID!4MgKzqzpJ;C_rRV@2u)Yp$(B9P?3?*zD=95+p~9ipO_ zZ5@EBa=P9ej6IwiYfM9ICsHY93<3%iAm~Pif>_PH6;xcDd?-;Tw#$ zAIi$sm6ljC&L};JJ$chlp3lwD@Zb*gwD-xG?y~Rx_#g0TpBpN3e6v5ZA}A?mdIC@p zp4`0@?sUUd_FapD|Dde*ko3!|eNj}p4EslTPy#f@Cvwt70NUUn-+{1OnBW^X_(fb! znl28Blc7Or2^nfRD|&Hta?#TEyrkb%pb3nH#fBYYn$#g}5!@R?**OakjUi+1wxD72 zHC26?AL24*IIk6NN0dMRF6!ZWI*?}19M-%3>&A06iMLXago%RMv6JK|K28Zrm;M;F z8Fse)v%Q?72j+EY^MH%1!s8;N!n5|wXfgU>5SR(prz({rXsj|p8S(k{4fo>ssIBm5 zQ&p$Z7Qu7>_is^mXW~M=-I)lZ9*R!39IdLA-UL30L9Kaj!-|p?R%# zI8yGl{;<4^?c|_JY$oO zKN(NN7(aa!q-u2;Kj5-Ar(14W+j-?143Re7mNz}1xkIX-A&U!)C8wgZUUeSBIl;6Z zJhsj6y%sim5;|Dy>p`;|_c9|O(BByGa2TKwu5hpS7T5N>d_q!(9x$MH6BW;sErug( zZ$ez4{W@F)48PX^xHxXb`RRbi_>ddvQbqOb*C$p^mU=~qcdyNT;^yI@V`6e&?G>OF;*AKS4#(U-Kk}HLPeMS{IN2QiXi?bBuDh)8sPM!* zXmzdxz=sNU6zeYwpH*qXxn<-+-)iYgL0#^ivKs^y>0p$7b<-fg*u}o=9hRR)JaZ z>)63+Jcl3)s#MT)3?-*v#pCc$tWWj{kN1*DtsTzJc`v~n2G9rM&a`X*u|~CX=(nn} z@#6~PUUQ#xafvfRHeJoj{gMR%Fhqw_3`f6Img|nZZ3VbGMY==H!Fo|_tuzVp%Zi^`O-?HEKv)l2WUqIycaC8G-d(sfR*B$mO5-rKj#6R1{Wx zxIXJE|5)!pMs&DwiA()vIA@r$Vw{#Ii&+j)YISG&^#hPBIhVmY_0`Xk54O}-0M!5@ z==_3Dques8$SBk;mMtGnbJF}o`_E;Ma0^!Vt-Nk;eJ)V#y4aU#H&cyY5zEJwR7O0> z#Q@2thFHu<-oL%*fR`o*7C$S^bZp*kco4TvaT4w&z5LW5k~d@YqP=05`LcsQRdBy2 z+COMBDRn<9(dT6RD@IIH?p88hGfWC43^pRSR189mrxA9@t2O4&JDc&V7x8a}y8CcC zd?thNp9!!Z?e-N5xhBZVt-rb}d=ht;!EoX7UmtadTm7;_p=5)l{`ai;dUw_@GmNZ;m8MlAaB%{~J#Wm5^3<^Txa194fFA^5qmxX9W^ zC45S4czwR&$8TTEJ7Vb)3$Le@~4gE>i&4aV) zwpM>PEdvV6{^lr33-yafY zmKXm%6blE<#AcxxMY`NZ+I-6zjFqZ|JH%1|>TH!={~r4&o?!HbZ`K@UFT~;E z=Eh0zSwx77&2m2*`upm_X=f<=Ehxiv=S&3#Z7ZkQ&m+nQs2;73XDzuKH!h0THhMxnGbJZEA%Nf1v&)9&&fG1w$^@P-K6C&A~PlOCSN|v z(ynvN031aaM#s?-pj~A0;dssCFhrS^mS}aKt`T%i{V=n*-VgxK@$d)IoqvC&7Od_-<6>s6wOdsQlz*NbzfUuv`S3B?Ej92e z1)^ua(sx5jK=?4Q0fln}>20!b|9t6oTmK7Xj?RB@gY-0e{i5I@pA{qX4}?RMaQ}DHm3DA>t&D4p0b1!YmD@8S zyNByuezIgx4BXgJTqX&Mt@cJrcs~?}m-5=paa`PXk0%S22G6oVujI)trpx*KnAu{A zANw3ysQvgD?X|+@@wUdR8dsN^l4N0ldn_z)a>1Q#VVjsYT*B3aYtSeW58~u-C2kko zb?hvV;YhL{2{SJ19G}>(U1305cDyu7vq%9i+7VS;QQZX)bqEOw21+>bqFhG`QU069 z_(4-O2^fiDb$%8>?1tY1FrP2td`?%4BL87AY1ELS8?Vcc$Nf1=rH3$i6BIG5Bw5Q* zt0ur(s-;QTir~LP9%O0W1fT_8U)L}&s>4?&pV=J+|ZYM9-X%}!}gU6=tiB}r? zs>Hp%o@=wDk+EdOu$KQRy`3Jaoy!5T>^EAJCt>AFgR{S$>A^X%K8~#?sRhSiT=_p!bx5ui&l8 z&D2!EY~XEklL}aJy*Gq0*s!jqM|d_(+{*ReK-wVOVR*M*~Q|!2O>Na@^Njn zaPeV^+)Ulg;`NnKnkNI)$S`lnKt^vl&pMj%2PpNrYljMnV{lBvU7;T^f<}CZ)S0oe zZZ3Aq?J|hUvWDdJWfnov$S5TeFqF|&GF^e2nrLgq!Nta|a4_>~`9M<6G`2pSlSJ1#B@)G4NqYAVG)y6kF%DwTTt!TeW7M)_GC`r2f3IDUClbZYDHG z?N5Fk@* zEYw({(jM)$&Ktq6=8FGT;~uWJ$u)m(ll5c`;Bq=yUF-35OM(h`)lW||1d8Q;yz;WF z*Nz)hLi>Rr&^g)!!~rIQj?aa!C3IV3ZWj7{S}|-c%H~)eOmnFw%PZ*kT$n9prVYu> zNcz&0cEel_{>D;iLeg}TVmz1F;!yT!WTd0Dg~beEkk6<1sMzk|latcxCW@p#NJNk( zoJzgK)q%*ZTJ9C{8>7x@7cYfPvAh9teVHmSMFC#>|M=nOw=%MN%NK6+CRahAuKoo` zRDlq57nJ{E#Qz(mPz6D}ZmvR}N9+RjYdbI-`hCLT?`U$jjOHUvfK!Hs-oB^<^50^_Y_3WVlnYND zKA=$RqI<=oR|K2~so+5<F4mb-zubBJ2^W)oFa{7Szp=Sj)^(S49c8ZN{*odG`Ec7*4QQJ zeqcOoq`qnlNE@eb?Abr!&2Kx}T2NZsn-{Z77VGm5309yvzM5+wc1QFq?JCRV80r93 zXMtJsgUf-`UVp74QjnfZ%^t!-d2?N_Y?Rt-R}m`F_1!PT;nW&t!ri{st(8%l)fKY6 zFmdy(Jup3TeGM`~u>gs@D?rvYUYT0GzBzjGyDkG_z>XHwcsl;YwkCI_JDydF4e88> zSJf1?N)CWfq780_JgEj>_vro?YFT~?LmvE!wIwAEW6(eoLL{NuQ}%$q`E_6JBonlRDsGj&Na$6=MwCE64`sJppFCJ=J!J-a+$(1koA zXh;7{w|=bigVDqfG#jg5gP$k|dGxlB=U(ruo1JFXL3+D1fy0+P2>VdGKdc%)~l*>u|RO5BD1c9NSSZCaT7Zp;Sp@_jJt ztz$_COVa#lPcfO`c29xxY+(t!$R&5S2Vf4zYm;A=`Nv@sP_}Nckf{ykaCw{O!@TB7SG}7bh$hGXO z#yZ*!*345Bb$SGdk7Ay@2Xet5z4vYBa%#QA!n|Gr_N^to|76xGmYd=4l~HkLoPa@( zh0qe7GyO3@qTm6xuhZW*U@(>uEn#e8K{M7oO}+()Ko6nuAMZ@XZfshvxdM}4g$~Tk z>V?y+A zx!r?X5;*-}uq>C2^#QVFC?SD0YcD1$`WY~H04c!ckvW2=Qg^2Wg18w{)T8xC{JAYn zp7nho-t}V{cYDI@$BTv=dvZKp(hU+~i5Ll6se0utlp&3A&8Z zVFx`ba4q)*4T=>YQ+wLZ+vt3ie7!J`It(otM@7_+P}q^siM*9r-;{DpszwHQ@TEYk zX62tKR|NfZ7g*0Pr}+1!!Ld0kaTv2b_(mO)W&R!#@cI62h`GuIt60|sV9vby^X3Z5 zhmZcqqir-64demC8db-L8R?y4n2ldJJRLi8TTcV%#QN#=GUcRY#d*GR=hS4r)^-D# z5eAqqy6P$}cj3}++BNUu6g6jx__u6)4pqmTrlu1*VB(rnhC|*7>}!c4qK@VFGkCsA zMBS@~vqix|^PkXl{Q9*K9O9K7Ru4ZkYO!r}9duC~Hs>(}y}wsBs-gQwJoSeDK5Iao z7cNTSIQF%D6q-U^p|YF9=|aDUXi+eT;~3vhfQPDv5Vd)eNn~kjMYVzoYwM}9RjhiZ zH_NUq*PKKuYc!7)!LySK0|WYcY_U~Qkp zh)A>$a;UOAOyX}7idXMM2saC@0(p-yQ-L;=^6cHP@X5|q`-;|gBA`zrNw7WXlIxHi zB*1&=6Sr?w;ps8k8usfG8?|v}U(y|w*v|z8zqR<6^z#P|>XWw#;lKTarwb;4!V2GE z@vr1+Eu1mLPi2md_ODQ@-&q}WpY=b3^&P3GpTY8~KDe0%nb0_-ONUP05IPKOvSzd*7s5dKk7;nrasKcjdVA*W&nvFE$EQ*=5=2Tv-H}xh=}sb(FVU+ zo56rB4*LqO55DOfL@D&BJt8i)CctdKAVZX^l&-nl`PS{&yze-NI6Ux7^4mhkJ8%O? zvVR&MPaO@%TTnllUhnB{-CK8T%GRp-fS*z7xoIu=o4nf!=efuEx_cSEqoJX-xOfQR zL*5rZYkc$#g8cjnwWpb>u={hYnMtDay+Ca!HCZ2&VZ9TO-$SS|aGGG9?TEG+atb>5 zU~q*I5)B2qDL#Jp`u+PgrE2E^9O{`RSSqNX#xlmMzH|x1%rnLTP$d#va)RbKg2Sfk ze%AGCl9Bubb^_rKjesJE86Z=+8#*B-e}>Me?(jak;6|bLglKyq_rE@uS91$3%_*KT zPn8o_$i)*wNF(sWrBqY^vzC7f$0R9jXqflZYJLlca)kP7DgOqrg0HZsLPrKr6PPQt zbQlfaY!i)er!Uo1+5M1ynXBM-a4`AY+*9<7D!c*K*p8SuFHT@-S+F^(Q0Xp^?PMiJ zA`Cy}O>#TaMKFPx4pW5zt0c7zru&=*(WF1Mpra!s5erprMUm*0IC&WS76Qd&g$>2I z%I$nOHQ0TM)wqXKEno{-3A5r-oST*@63UDuu0NF1usE>$E#I)4SYmZWQ zkI+;v4p}6_{g{Oi3*Ob+0JR()x@Z^&IYX3|93UGU{1nTsLt)=|sVe!Z)fi8uJz=ug z0O#jV!wxkXgQtU)T|Eh-zj9s9_J7lP&YM_+feDPHEF{C2^{nln5ySdCKl+KLKAbG? zD?58;m>C;0git~ykj@6I(A>v$Tn)ujZT_`jkZ3F z!%f7%#KZqPuZzZ~g;*WYmf-en*x9Qx%uT;Z$K!6+liNle1qo}G!;_+!8+r`f0yK)a z_0>&zekf$|ob@r6*B9H39GIZ0-a_$)wu=+5sX8xXs;`Efp`kIZa;6U`5Mhx)UsM`j zxufU>*cSMr219S>Xj0OUJ>)A?=FMSRV&d=y{BRU7D`;?XN}}Lk4Q(=6QL}#4Dh&sB zma}O=bC(N4#+?Fofk*3$ZJt_{wi4FX8e=%eM}S8^;6ZHP0^{EU%u$(oMKTV$S6tPi z5^9uI%&4zoAwH}c`g6-m8^F*a2RdA~p^V-Vyu22-acvjPLxi|~U~HS?@*icmMfFJtfL~hmP;U3}(K;AqYA!z>j=?yC~40^Rx6JC+DYf&%?Dh zrSBb=Eyf?;LShN(449ZlKybEFI@JX+PjD`#Q>{7YJb)_?<N{W6G^*2*U-?Lq*0vYj-4Md_k&uvLSmd`3I^2rG^ryN^}(LWNoM9v1-{pnAN-r} zpiHr!UVMnbPlQ-ajg5YPdxeNfBKtF+h?B+jH|cN^uzbafrgIqia_qwy^LO7TLvWI< z;QP#JfaYe@KGXdLEA$#LhvQyich3bq2t6F)*JbzSKW3r5xAa*V*$ddS>w5eiK5oCAFNycw@oN8k}$(v>}*kjTkx?OjgP;rpv{+s zg|;vz0$ogJTWd}}iw~^|J)ehPN~>cr1q3vvqxm(eH=n*iKcheWfN&|LQ6cI(8aS!< zR)gaQGA2o!s0YVqKsfFUE)V;P&odF=&_gj|KRr^FDslvDy`LC1&Pq_-m7~G1)!_Df zNLY0y?CD3;r3gvR(7&_j%Ve=S$-x0Q%~lfDjfND&)#A};kO(pvNY-h;a#c~K+p^`o zu4D~?oI>Sm`Se+UU4|j3U3FX(i1z5^Ce;$|F)YD-bXdFf3EVtUfP8476JPdD7MbLB zB?%9_EWF=XmYUms2t0vO<1^!o8s*S2Waz{@^!NBntHbmp+;2xuZLZ2AZnh2|=7xKQ zBGq;d&Gm8Z&EHBh%tewxs)W@>FNxgwPkk$J^m4@AUKB+o)`Z>$4+2ggD&20Bt%twx zNY-~&j<>%To~bh?N*tfdRDAH4Y=!V~lH6pG?ZQbW`5TV0i14JtAT6fc_CkVi(X1}?T>%OEbYMnWgHL$r7+t-&X$zssS zd86LXJzqopQ1vE2`SgQajsC&vjahfx4B6wUcG;gt%N0#6HQd}Ty6iNiaviY7Wt4r% zIl{g4z`&8`?eR+EBymx=_aagmHJ|Cb_xj7q!kF*(vxOsjG}e7g;HDBXRk}%hnILe> zjRZod>Gr)x;50}G2E%KnAC5hS?o+ZjztE~WUsIfQ#UQS zZf;P&yQI{6z?3uhjN~yY2JsY8&s^2#%jOf^@gN^#m`S%p!1Y)!wNpHz)ZmdV zx_?_Dh7DxscpaUARi?Pqnh$-smolo?e4({QCdSqpmmfN~fp_50$^%t7&sweD-VGb) zeiC%@JGiiYh&j*>@o^*dQh}w330$jh4L<(&SVQ}K|4TeLgJv3L@;9^%X51+daB*-; zsS>=#CPXb{*6;qrLABOY!xQ|oA>W}0TAfu6MsWp`Fxn?2{VY%l9fZa>TcEV1c-10( z`vI&aY7%539rcz3jY)iLnqy$PpWK-~5Z6kTYK1j6nL50uPvY!>`4JkIYYmI>zLna# zCO%#aJ^Gkzw02G4gDi3rGi{z94W?eo+9VKF1zB$oku zn)~7bHM1o9cwz@~IY*R?M?P|%jOTH>^bMMba!fVX$Ook)|(?E z51PsJDl3vZE1(dxzFoYXYM+03T4@k%gXASDhow3vg}r7$d2(T40*y!bB)=oSC_ex(xLLJZMj`O3qV#DcmjtdxS@T+wFVi1c$WP9+mjLhV*Jxhe zDd6-@XB`8&g#3l9LV=hGB6sT%zgH*(Jc?(620L|6rFP@{Xz=Ou2%iO^%$2PTri(C* zn3@oG{B(%6T_j4as5nuqd2@FkJngU*7We@-g-T$Nqmw=6eO^&5S#i)B#b9vei&a7O z&p{Qy^eY=MN#(HFU84M;|44H}Ao|Yeh|QHQAS-?tM_`EZ0RwmU0r}WViHZXhmWTYf zY;=!UA7x=1$h@J}|JXZ52qp0E$AKz!BN6m`5N3Ny6B11VX+3yOS&|{ z-+C2W`oyv5HKZJ9Ij%<=^`o`70r-*`AoeC{ZaHbDr~NGE&hccGYaL+lG`CLZg2;nc)B=$Uf{#1C&0VkzM3m}3wiGZE|X7?$KjXNg8slOpqnBm z%}I#n0+cb|^nMcP_wAYdsY4O5CYpF9KTg6eO#9(mhvuK()okRCA8J)_7Nl#eOtNpq zLf!^Va2ffg=x|@}=3qo-i@a?9K$Z6`5i5Tw=kt9@SD;bc`d9Y4o8Na*NFA9ApY~=fGk`@V7K7rTzcT<$-`Z;<52m$<1CO$aW zu5w@M)FCy`c!}{vt;f~)FOL7*m`MucF%7rR`ol!Uy?guW@?e5|s1Oe4AdT`h*EWMk zz3%5ces|?NG#Q`|fB`vdEz~rF$GFL@Qmf(*w%RHX1M~%>0#~&%+iY&KkJWkdr?N!y z9$*+!$(r*qH4-Ah;EP#pm92PN+a!4*mwgq7-VT3T>2b3qBoR}cJ1x?d`_j~ikiny) zp=sz>mgGR_xqWm4EGz~xcD&W2B|>}WAtbD!RS{WP){Alw5cRd|ReG342e1Q&?tv~#%$B%i>1y=K$*5OpHtqNLyF%D8_b(1-VKx+fO416b(YT`%fx? zv)C7G7S8Omxig<%&K_`Y`9c^h+T@DZ`<0^+O(JjcVC$DJBCg-+j&sUwf1O-nx#`LH zen`!2Rr=?*tiZC3{!ifqj1mx-{+f}#JjsBWpuaEsm#~&dkb?{m;9>jy<4N*2isw2J zXD`V|;!KwW`xoLI!S3xaBxXHYIcduI1a$pQVK~#Yn!BOIycI^$5|SCV*8~1|raOm5 zK%FZmta5d-<1I zfIn`@YXy>!jZL&29=rC}usu6LpsW7SXB2j}ew9T`$t#zyRV4#FV)a-Ou~5o)5UJiiiaCWELrB{C=+Vc^xUF1`{?V zCSh{@QHUX^zZV!L(8MwU3{qq^x&?JI`KR+i+jB3nMu4Zu+NwE2jlV=U2OR!bt-VXX!3@W(Ep9kAy^}MFfCTd8El?wGT)7nEt^F@S=OUpJ~q-SUTN2ZF#m>w_D@#&mFm9K?Rqzq6&Xi1nX4M) z?@#88s1&~Nzs^-vkPSuEm-s#0)|T*$l%O{+@~1xq0U@^`u#CEJu3?2Er#!aQ40#6O z%nsY&ecsLhmQjF+BB9m_TQPUWof{G5b>z1!x0;^N0UmW01h<$tzuUL#84k7=zN&O1 zeNizV_^73d;d#@f96@z2a_qn8082iOpmA z^z)FEL&E(ff-M+C+1-nM;2f9P9>BQICG$1kH0q#b=F&z_bX#OT*&FmV{IA$R`=S5O z-iO7n0NHY*mwwz`S(xW`7mgTBz;7ghE#Suc1(-g8k3W(|fa`&vE8ZwM8O~6*oS%)w z>ly(GOL4%L81L>fyt&Z}=#4YFEef&MuHnsja62zgYwU0qT4ccu%HQ6gem7FO%3N)Z z&ElI1x_R}5vOJT4MqJtqOyf_Av6@_5Dj1KS4%SRRl?3wKmq^fGZIjkV3k|>?4C9YK z@nOOBR{I|bP@UN|4_A%d|Kp$h099E=K#4wG1+HDOwvXG(D1gFO?ii~R&o(1Wz%o3N zvY!sR^83OKTxVEs+y(nbVH`CDkdC-jx-yVHW zx3nKT36^3k7Y9P*$KvnGxqQMRvcPRYJ=B%G*&61-sxcyFty^r!gyy%=ga7)@ScwOX zTKYg%j@D|x_*4p|FXd*V&k(pv1cXQp^UynmU2LO;6A@Np!1fnakB_J4)sa{y944p~ zC{p6s>9SRR5hW#1V7qHlH+(r&mooBAdK-vZMFwH0dar5(d^d{dZ@Zol@fiW0z6`-| zbH|4`^eU%5g9NT}6Giq1-=+b!wVII&+&tc2=5*mle)}G(=Z#G7fR1?Ie3Cb0dw^k` zx7CnR94w@u_c`3v2SYrR+f+hHm@QFhr2^bG*_HZHYjgi7{PKtU#vgqc{qRbGcO}2f$?z ztWfJ?a|yt|uppeZf21E6@N*^%!pTQ?@;!#X)sG`<=B@)psono3@*pP|Oj8eyd=E$M zUbNo(__1N?gsU00H>T~@L;m_3R#APHEE_pFGlQZok~C=nbj^3wp2zWa>lN1J2i zg?0ZUDuN$NOh|tHOr|~%?H7l>;yn;!NLTNR*I19%Zg_Lf;h%`C*KT8nGz@^fepuvj zWEP`ToKojx9D0tQFUOeBdx&%%{vZu_+x*Z8p+{(bTA+uf)+ zr|OF!@C)5~qK{1vdT$ZI--9cLKyD3-fNfAwSy&wnwMugZ&+^b>e+ljQv5-&;P)?`L zyZAcec`fFCWd`+_A`o#oY}6Ald{E9-DzIJt4txN8A4I6o~u?2I74~mdE-WH%^ zUV@gzL{eRr-5TNyB#prCCfJtT`vpn|!}PT^$7Z{a6>4jgeO1d>CKZ~N z`dT2*UmuO$%x(T*Dn%TaYQ1iHlLUVt(ffP?yAzbN`!T^O2qW=;WL(DFw83D;vWxpx( zI;yYq8wI;*Wt_+QSFe)`=`)CMbfsE5Rq|){4p|2) z_?Pvs=-N*E@j?B|xr^Zuj$11X;8`YX+-R`wZ7~{jhL93YPic-8rr4g@DuI=k>+8a= zX4BR2nt!}?)y!(|NDyr|N8&9eoQ;h$6NO^Eb^20f;n^TSx)c_EAdbG*I;VfTLDKjS zZ|UI3Mn)}S0!-%o%9qEJtNfU1cGfxHiO=XSj#=TN*OOWRy`-lHzxQ~x&+A9=Hqe3} z^{ElIUI7<0$N67cGv`?`o7Nk0J()wpk-RT!SQ}d-J*rUxUY!TTT+F;S+ISzCql*L{tO#Tu%B4S zF-5%sN-XZ#GLUnTZnf03j# ztGnhwdl^JY>Z1JR3%uE==UyH9)qb=@K;n~v7k>GQ+=GoP{_%;BfW=UrYU2lUEfVBv z(u|I|Z+&STMtPb@G*fqjI zce-_=jV!0bhIk^R_WabDTZu>19+Zztrn{!XnQ>@=?C8$_7Ndzd6`XI)VWda zfc*{cSXRnD1265LrKp8`1%8S~XU{XD1ZqI_Ff=_V5)T`)+)px71ceTI!O zow}_(i#*V7xh5(4~A%jwNdhV@avsV7koMS8Mr`b zy3~$o__n2qr->b278&`6o*eoj8n2+85hhgcd8O;X9yDO2SEbZ36b;v{~QN zmei9>!yYMO{rFw`*y7E_>2Fm&D&PrxaMn zmKr5S44_v|V%!0qP{=0FPZ7J7qxbJO@e$#^MU0wesiMrtWh+_ge%G!M-1|{@uo7nN z;E??~8;fP@>_AA3vHBjF4w=)bc<6CGMo~VXf)U5U{SrqQf)G^j;OB3=D4*>#QHpBl+UD4>}cg#GhQdN8^}}w z>6wSeJA|Yr2r8MxKfbj^bhZw5JBqDzydKPj9Q3AEg8KfwVw{GiB|4ha2f|4N_9}n@ zj8Lvso0;OBd^|+wB8SR&Dx1erGxrH1yYr`t)kkkiZz~OmZeF50d_o3Q$?@`753;3u zuD&&1A}4Q4#qq0X#Wj9U7#6?xTtHPFQ3^fqjUoaLm0L}08^?ir0OEVO<3e1?v1%6- zP3upAC*8kXBQKI#6S%pe8f~P)Kcvb03yNCf21^PETohQ54t|4z1tbJuwth0v)^@SK z{2;-pgW_LMAYD6sGOYM9hBzg@@*G6|tD@mMSb?Ptl{hIxv_tu#w_FvAtSxUa+k%h%SIil-}vTQm8Wlh*K5ua@AvlU5uY7brC zf6n+MW9g&M{JH)1MjEN){S#MWa&juLBy53x@!!yAGm!V^BG_r&`(c)X9-;g%@VQ_4 zR<`@=v)v9ahKvU`!gp;d&+yjTI|3Hv<;UVUYXlzp&;YE}D1eFau4$Ufkk@2xc}E*b zjFZh@1938pir+ewLAn73w?F@tJm<+^Kw{n>B1U{u_x@tdpwJ~SUjpZ|)5Z`1mE*Cw zZ-^|t$U}nWN+5{1f1j=gyGplP3deu96u^QS4(=|`yVrd{9@vAbs8nBCi)7?!*Id?J z4vPLrYHMm zZsz3^F$iCReFQ+dgEjN*>5Bo-0_qK2AM(4{J_XCk?mcG* zHvxrU!2BX?@RIB#`XOJ#8YzpKE?88~B5C<)f2Q%8OC+N?yXW&`q9I?wDhD@W!UX7N z+eiMOvuV6m`&lYvLK%dLQWjX!o>Su`h7A)2)RZGj4s!5*&WvXjXNYK-ZbKHW*HlMi zXei|st5-?S}9{^JmKW8}YEid0-JyBQtJ=fiDC>#vrz}oG9fTdtaWO z2X9J(hq!|;SReYMNVT!40ai3OwQf37ojilaq9a-hS_7RHzv1Zz3JHk`R&_2Cces?T zfJT%*sR#D~l5%|vQ z@%A$d)zyD9$o}*ZRugHYs8@z&;vkLBeHdkd&6x9wfr76d_2=@1De1nCBq?vheMK)Sm_5D)>8 zZctLXq`Rd{1nKVX=FU%coPEykp8x&daUFXM9b?1yz3*Cc&3NWBpOta(jkPeR}h>>8am+{=|vI#zr(RBG1aVXVqfs)1*7k6)3%)Lw`M21)u@+ zBs+ixOxe=-d;f$6ETa>*m}+V^(+;;cH0jdWWJ4)r-I81mDQ=5v(!6U&1nNj0@!5A- zq<_}BcQmDoaQ`DOsa|nE@z~nfHxrPO!fO=Has3?4pi@{K6@lP%JV7EiwXo1K*@ww} zb-9|005}g7nS8k7OHnM|9Q@q`NV-63=4GN*W<89t8O#Z+sWF0<&zrAcwL5N{pqC*F zb2x>&_qdSHQB0}JlYaJueH48(FpNfqay zpgg_l!UzatHfFv5m)AwOK&%V$N~*6W8C-^zGJE)67?>GVFl22NNw+854km!MuQe zS2YR^%J)COO}xdBO>oe`mZy&nmBGbyfes3xc?4JI8$*zLYI9C2m^P4z+ej1e}Q`s#Se-IyxljE;J$;#bHz^x0S{`8mvpOHQ#*jgv>LZ-^U*C zZMWtD1Ag9i3Wga2wf1Oo4UxcM%>OY7QM9fQ8_)jAn^hD!{d+FQv(&+kBFTa^W`iKe&M(xkq@im)v*~~QRrkZdN z9ZhE|{6Sy6Xr8}OD5&6}7y$CW*uJds6SBn@4X3ee`C8SkJnkljzcBJ)zHL*@o1)t7$HH}wY>2U;s|oWoEVwCoQ*jE@(B@gnjC>(y%jd>88Pc&6y2s@Ij) zbxw)d{ndq0{2rVl(Xh8RRwA1c3LGwHsA%<#!M>cHo;c1as%!rNQXrJbAg9tks{VqG zK=EXMew8ME5HAYU91crckeVVT;Zo3UfgI~6s z`fgJB%XY5gEitd#0P%P$D9wn)abuH_khqsw>S=Y1&t3n^4!v{tg8^l@ML(0JV(~YE z;QFRIMY-6N@t8UET2y>B2=eF*6)I7i2PL8;*ltdfzj&1y`LMhXc4JntCSOMG^$ zi>0UD>4884GD+HNEnOGPB&$W-C?=}%?8iOxo;F?a21t|r91x+?a)=WY#cX+tZ+EdH zm{t`Zq0<4~RhzvBB!Zr<)E;7Nz^PmvxcHiST>}QXVeonh>AU|>)n-Bj2Q0uW}4+}4Ga7WX7Ox%+_JYA`|uhRmAe5J1wplefIGX3`b z&Uq1EC-!F%Z%_cEb%d)M(8BWe&iz`b!SA0Ui4Gzik5$+u=-YxhOG$^7SR;=gvVI&V zRVR;@?kXvd<#sw&e6PJgn@la6d`0wZTlT@A2g#%55`=Hh*|~|A4AT@lLnbUFI-r@C zaW>1R-xl{5l>0x2H`8PQ3x^Td56<_`Fyjln#@|)2tKc(a)BKL;Uza4!8hweEzkvP% zGQf5@_nX%RA?4iA2gvuTe3`RToN)3Lxw4WHkQ5L|oB{Z8jicb$C?~va#-(w=b$f&TriU0Z=9P;tQf1I8UxS+5+K8x@7)2OxWFN6XlB%E( zCKA%(s?ZTPR~D$78gJ*W1T51nnwPD?*eK^JhSoZ$-ZUxt7P3RlW5{67daTBB2dHrlM>f0`RE zEjWXSXZJI@0%RWlXhLiTQp`lHiJiCP5Vh`QPHU3&jixoLl|@a7o6mFfE!OTTo|NO& z=5&&~vw=#|97wwaeysbC(Rk|bNjZb~@4~e!oc`(n$V=cfec??9&&{=WE#mJW4Bx6= zfCx^922B=)DgOLo%?7vJ6rw~==61G>r(OSq@pEM#khovI^zzA1NH!Umt&77H8W0*Z z=~pv1b9yj$RJi4O6>vcb`4=}kE!ARN_$K|4t7zidKivAbETW>@g_36~Q>-Vs^^ zP&?-x!VKTqSd|5sHYkEQE)Tqny_TD+(n>Z`m_AZ^kaq}zIJ`I@z_`Byl@m$!+4_WB z2HxjyAPvaJXGx)2uIq(nLQg&=#s-ZD!UG^U&j8RZWVt#_$z~Uji1K1`QszBdz$UQ@ z2xH{Dj3)W0)ex+69gv{EE92|WS_G%M6ShG+EdS(^^tBh)13^;=lf(2}jWbtYn%Hp| znj0CKj@4u;cY6+Z((6td>;UE0Rr_5j7=&Z|v_3s{A*M6a2+y~8))+aS303IHdY!c? zsW}w57pRuk&L~gsx&-eHnZzZi3}_4(^NJyxKUU1C-d=E@=>7Z!uy@$H)0XtBx%a4M zafyih)M{9$KTL!6Sy%J?{4<9=XHv;lm8VijC=%X>(g-CaXz7(78M6o^l{?>}bUFMG z4IHo9+gB{|?<<$XyoS!Es|NO!Xk3hW?5(Xo$KZ)$IN2_}qs$29h(t`?ccN8LstgkB zJpzXT`On0&&CxuT&rqUZ>v+|>T}^O?S$&asYy(Eq9rdaDalgf0U=7#VX}Gg zUw?NuR*9eXfawgLBLs?$EgvgIzN1td)6=FvvYJx}RArCbUTc?n9ruhWeQGb#yzA3$ zt7*?-lT@pbTmPC^rThqUTM;@cU?dP%`NE{wOd;36EX7$y+SK;?-s>5@S5x_e>$rU44K&DQMB zb|VPEZa~&|Prfxm#@5>OmeK(2g%@5?_bPO{!6^;bXl0<9G5nt7qKIo%?NT%sN8r`H3kn+rq@0)`(G($7oBAnYI2Ru9_2MgJ zk-jCcdrD>ZvLhI}t8B8hY_k=YCJ=Qhv25NZDv)fa@71!s%AGvv z_{$eS6Zck@s`O+TD?32`$e|6T8l6U}dSP#@YFq~~FLPRJ4sq#UZ1+c|r#O*BxO0)g zd_~rmeLh?^d#&+Hq0nKEcx@`#9B90p?SO*yQG0Fob-la$kQ-W3)!7V;-*@@pW&iYr zGg$-*AnwmsVIZKHMmipw#2^0&SvF?IwOGwHaYWki>hn!F{{Drg>R82E^ZG(U9J3;M zP{T^R=?JHL$7B0ur!@kj;i=yvW~0HUww*m=F+UzkqNzJpyBLb!a=kMhKwD(!oqCS+ z)1acDT*!2z_2@HCz8gCNsSB$Qg0;hD{zeG!{Db?K#iM?5J3A6!6w|8vml1KYDuUwP z@yp#$I4P*J+!orcK3IZgEz3$YJiXwhO*xfcNzq12Lpig8@?TK=(7Q}eE)zf@JA#Wn z|3`K(g~kl?l?XW8Jo(+xCd~HcwB{U*zZjT@hFH4X7Ggq{>JvlqbYE@L^O#4dvm79d zo48J5hYQ0ux41H3SPsw~9g!#aLP#I!S>3PZPw&*3%!+y2!_d4}?3A%nY1+Gq*0v&#%14IjJ`}&e(lIZ7q0FF$o8XJDC5B=K9CA*7#z~TG*u#4}M)}Jh%}90lFw=y!`51-u&RAupntS;Wz5qMA z-Ke8(r?}wVGRZz^%`ZeFK!mWzYT01#r$}9R$=yk!g>8~@I z{9S9SM5WG&FNd6;LpOLS-P4S=`EWw$@_e8<1q@g$L|6h zbNS`x+kX{4P=Hg`Lp$DPHCj`P>~kHkX^yvL<5ituEDw0bK56XcZ`v38q=Aw(x2#-f z5@)nU+6GA%7-R|&Lxp%HBE?Fn{l&2`G9j!Af+x8|tV5pp}e zuX#2Ysg8_}5WIR@8beClT?|VzAlB$lG?w{_MJ~-PXnJ}&I54o*B0fG|z!&>%H1vVy zUUkZFQv=6}%X}KCwMbi$o`C^Ulq79hVIf9Z@D_yuw3Yku&pmGFn<>H{_;w9V&4_f% zz10y6GLhrstxlmjj~h2{$|c<^yMx-gz0j+K%RSRXzKj&rtyZU!I={2`%%% zQXAgCFVsc)T_*DeG#-0q z{n=_fr$J10dA1vq00gIX@nB$Z+=hdTCnP1+b+lHMt>NK;g5`X;O@RSNg-Rg{zmky0 zIr`+CqoZ8zV-Aey{h)`EG%BT*+wKP$S^5UiM=dMM6S)|KY==q{dd%y1M%0)KpMpWJ?c&c3Y0N zA{r65a+$S}!I9u|jfaTmO9>1Oh2c5TzV!Bvj@|WjAz@(vfHljkR}{$=ExJBGlaP=& zuv?+R!`!uM3#ZG?%?&hON#Ch^zGN@7=?~^HoeDUD(`3DOiS!oOocf7q7)=G7xD?4a z=#uxFrc~ciQc^1Ej;=t$!$jq{_NF&kyx335K#}`&U-JNi7z5+_?-#qLxaf4WJ0mk= z`bac{vVkQ5(9hPQ(M08aLM|E_8jlAYqK?4H=u)A|IGb@7yFbAtiBe(j5Uau!{eqQ$;6^y!c zeBt$ak@4vrpZjyM1>McDv(r7uyLA@ydXpoziW(qJH#9dd`173ROo1Iq8i!^6e^HLZ`=0H0nV^Cd$52M#}-GY}EEW;CNO&O4*5V&;dQsu!c9;uA1EF7bVh$t=xYh~r(RN0h6 z0Mp>Fmj(JYWs3v3B+hOPZ<*dnUuH{6Nnz3Lx`6qZl@(iUBmMZ(TIG?1E{oaSmas?C z4<0?52QC{m0|`ljT)KR0Y;2w9&C53}$^feKgM@&P)wEjbOfs5Py2u#DPBruM@?yCh zn6=x&FJ8WeP3a%$$@mbIPa8lX|FliWN{KgQ+x>udE(8y;hE31K^jI)(aM)Z<9ZAV0 zqLDP46z>GvZB93XryzdF&ThXpS~2_yq#I0fJacTSP7e)oH5%ZsOc)68@%a*PU{cH z5deG}6K;?Y4W)kjj9RVo7;IYoiaM_nT}SZo!cv-Cy6Jb7m}nlCSRAGU;^)Z#-w|^n zhc-$-y3jaMXoNS66^iU|BT&Esq^#VrI4tL-rcS)_VFN<@(iOJ)U!oIn^A$+Oa?+Ux z3zr>ib@J4qG*`I9PDgy#;bYYjiet05<_%($1im|scqTb8?^U_{=nZ``Bli>?9o;%w zUyK>alKqP~GmOA;EDaIy*6|v5l!Yta@P;)Gt}DP570}So$X2buz`z)%6JjU%?!H7B zVcrr<@g!j8jrmLqFteT~<8#?FZt;hI)>9P5{`L0q^%kEmZ1^aegT-c3ushgnSU+5? zCypzQR?Dcb&ScS!w-zI0bxVABbg(a+Xe3iMUxywL*f~q zQ$Buqx4_^E8DA1#A8rqlw9(_FL)kulqXN+t#=W!e2kd7<5gb85ZQ`?|4x@8hj+<;2 zv!fQB)&w>6uao%EK;;OCPR%hQi)74}SO zm5zs%Q!K{Arj}~{m20eT$1y+2Mj}s4On^D6hcHo)VhcePys4>*`D8t^G7G4ehd5oiUe_A*5Om@nhWs!I zdCtpwFaaj=Ipmo679KT>cB`B^@AN6$#ASRP)AW%bT`@O)D{NVrWlYRNaorbfha>(V zv^|!q3__8}Vu;e~*Y{BfG~VaLv0L2`jdyjuFdM8_Ih7<5(sM!pn95m(QvR}9*x&E5 z>`qJms-~vKF?a1dg_-v!1|11qqAb+=Zu3o6)u$&%M%L;Qsn^nP(`h!MN=iz8rR3X! zq{VOwcHs3RH8nNVkLh=ICRFWaLb#m{bvw%8-EZH%tqXJeXC-s7z;I;2?UFyOSs1Nw z`1Lrlyk?w_aZa&vQ6 z*zZj4RkFJ@aab)T9&yBmhkxhclILx*iGFH|^_}AJNANlM*Rm+-*UJWqf8>mz#IOK< z+s{fS63l8bi)tV!D9AhWW%==|!ehvNlpbb<{Gv_Sy5@douR+hRESyS;8?RZU%S!+Rzn{M|A`G1qOZ_X`%a%d?2oY7doIPCLu9?qbMgZ0+o% z325AQo+5q>6_-(WqSk{QO$aMED?z_64RYE(C&jcn{v6Wp6vz=DZ``BIaf#?hv3$0` z4uPu5@E84vR}#DO6;Ze7z)vNt;OxIV_prqOMDxh126C+f^h@(7f_po+kY=y4kr7*f zOXw>wP$0OTh$5n53PDsXEiKc5faX%o%Ka45H#Dj)CsqVi#qlU26{ZK9TC}v#5U_O5NqR4op?U74nW%ffdGBRpv zu|3{fNJ_}&B5tQ&)vCDDsm;KfDHpSz%~+asT}@h@@A|?E-T2kIw6!HRNMii`{a3y2 z-^#<74!&|iXFe??FTy}he(hx&JFRkYH9G@p>E|B=;6Er|ewzm$Xo+*vgwAA(T^ak> z1533_%kff;3cSHQ44Hkcu6|0^H#9&SG*KJR=ZyhbQOkO`<+BK3;7wVSn9uC{x0PJV zc=rU?VC%>pNIGK`4mSPQVONn5PrHAzH|BGX%2ObQ-D-DjEG{})IYHni*4ok+l$N%- z^i)$Pd}UcoTGi-^?&Hc>$XC1Z1fOsqcIOi7%*Ip`_zVXKt$>|Ft~ngiJ?};@`xd2T zbEdV-yrI)N8|BkT4j4!!$KDJ=$GS zIrf$={oH1V;0Wn<$Cv)7hkUeg5Xt25BLN5K$oIgr%bP?$eL{Y5nKX;h}uyOSxE*g`8px{}2vV-e29n2osGoV76a@UJ5fIgre>Z!NlQQCy;cPGkaZM<=w zeAXN)+{soMdb>MPwgCV%E>l`qyjQ*B(aH@mLR#W>3E5B4GVg*LuRUZ-VkP|$OhG#P zGqae@ViZp8i`TEW)Li_`dQy*HX*?j|g}gP0#bkA`fQk<11{#`jl{4-TfI<!Ra%|+$UPe*%_d?ezymGiInHcmS^iB5Wq zKQ(;x`vH2`DE!2qnTwdgs=14zcFYBkIB@R`=YR5ybNOi9)7(sUO>!cd$I+H-@Dm30 z*9}9y`oxYHy!^)w+qPy4J;;$!W~;yQKO6pF(}{4h}yta}mKr#$?7qQds30vTMVoR`NmQr{Eak zcwE3~Zb-0)xQL30h{y}&xKEDpg71gq@5S-jLkgU)+^JO`xbF|qoT_g2j=y)FUR(wj4;~6}K(qs}8%YG^ za~XbB-l^@5=Z_gG+5^p2$joKt{rQRxe0;_RH<_=A(UF7j~xW1A2%`yzJDM7BTcTN$$u{)U!@G|{-a&4aAtB73)XYH z{}kLPKz?rbC8UkWxg8CcFj3|%UER!!Is}c=mnjljJUnU{!F6@+TQjY7JmWWR=)=SY z%1`S&oVopt6VRjD*xalivl(6JtW=x?%e#a*(nX*v+Z;F=jy>I0*|hSkH*7jME2w8+ z<@}81`PM%fEzWJ7RV&U?9UYyWMtt}?&Pl}B$0|m;Wr|5ejt2= zQM>*An;&^^9}pd=dofV<18=-gK>e+q2W({Bm(IWLfj99Yzqv^KRUruqH17xe7`#7x zri1xV;Lsy{jW5Pldv~Jq?F5c?yn*$TECQZYe`fn(ZmI`tTBSmIhGOR*8X=)kTiE8F zcg2NS-?8nAz_%sOig(UC+OXwr#}hnf_|rdMnTfb5VPQH@DrTt`oX{Ft!o^<=gIF|< zZ2B*<87244XFgy(`n1Vr8YAEx zl;av>xlo?G274ah710zpU-Ub|Z7hO8IjAlVwU1-tY<`u07)h}f8|1t#YJPgqx0G#D zCmKbk`7ZF~-gS)XcjPpycee343UQ61>`{F4b^KozuN(cOQR=~qO0x5Y-U}9UZ_+WL zuvp{kK1TUi_L+xqzAA;wF-f8i%QpnjIk$Id_Qz|uv2--1f`c1<&yNFnU^sW{DE?hG zL;fBa<}H=8BBRw<|H9)O3J!>lI9|}ld1edQX~%c#vE+XU+uZoajAbB6240t)`{wC z>$l-oV1o9F34gib&8197oJI+`;a*o)M3J319?E*o6EQ@K|Yn}30%JvYUx;{fJn;`Bu0HaB`O-PuLNJjTW zn-fTwAA!d9`Qj3n&kcb-ve9o$P{NxB3rb}ytW25oCEU+a(#Mgt3Y)g8Z$GKeXgi9+|!(%@s`&CiL z^D?-tP-L-_cdj)o1zi2IF_IvL`wsUZ7Z;cF*$E0~eIOA!-SuxS$8;YSP>x3L_GjN> zYV#5X0I4C8CEM?swVA^}gRlfe?RIi*`(AJx)}1?Htj)r2x&z7XgtMuXN1pO90TA8$Ya%gsggQCl=sEl_Or4$u5COx{L1?ktpWRM(B078H(Xe{^4L_{>* zNFXr*myn*`$PzVLaJD&7v`VHqTXsgP&iAAKmzm_xS(det#Ue-BB9F^wWyX|a&XARe zk*u>YZp&@gH_`Hy$t20_bJ&{d%%sZZ-D620Nr~omVja9k6{-)%b&j^mF^e@6n|iT( ztjNS+_f~&KalFU6dS8{k+@n}rcE)OLEE>9H%`9^9;}Jq@Gw{k!D)cf=V*{NGK)1c* zXz$M5CN^ZMhUd3X>aAB)_ost$g%)IzV(WGT0*D6)-E#sG;%oV$1AD^9k-+WqA>2Oc zm|1%%E$+5N+mATfxCz>c+DuWRl~|&0Z;)c;#u)c|C71Totk*`b&cCg+wVl@BlDY{G zU(0czs-HqF9gh^Nl~&JPGMRVjV1IY$-tyTHzAy;5;QjJaS>}CN$eb;g9>2Lwp1^KJ zng7@eb)hFm-H*t5-&Yuw+*JU0WnCZrPP$eCut?80ML(t7*-586UQ*uV&O1TQ96Xp6jvj%7z<1GtWFN~e#w|*vDwkLNJ{{@0n5n6MXmTHq;Pp$ zC(ak;y-=h$mq*HOVqmxraF8X@{h5V$ruw=F4H=_c-&1B!oC_r0_hGhQHj=SBbice@ z#f|+?(%F3JHKZ5IUo28U1{^zIZkH&ObuOaoX}PLn?&`tTtGglf1LH+wv8>R>cPO(l ziC{4?-hQ3W@6)((c_J`ufz zdie=@6&W4|1x-C|Us3;xQ(T+CNIvisT!*yA`$p3L(`@DgspnU$W(sf2`@a|St}v=J zZJ;d1WybziH z+Hv4}1nzZ66WYJa;&MDp%C&=t1-}iIS(yXND8Ki?gjZ*&rCwy})(>fo0a1zmXkm>< zepbXuxsm6AJ%X6dpJ)vo4b8AGjj$uM&P!pmDsH_Ij|--He^fZM?(cgH+-Kgc<8~UH z{DsTZLi>^tO_E7(vdUykgS$5LF%h)ed}E&Du{b}`Y(%o=W-(F4^J6wzRI94IBbcgO zvh97xpu4xw2%0g4kR~lAg+)RV9B?v-IV+WyxCf~{C>3gL{YVyPpo@S?V`Y%ZpCDjw zd6>Zs$OIbh=JC9n{l;R5q!R@#Faz6W z$BqY=^Y#b4`pHklG>peahYAexN6O}2$-o;^_&xsAnC#9M(1Pmi{XV>2|78sOy$ain zeSdCy&HDFY8|#}hMj6Z1P^;ytWy0MB>GCVh6s0z6ZqMA=w{HI+dbL6Jkks?!=~BJ- zB%O#mKqxxbFf!Hk9V;Fd?`39xoOb0?Rh%da!wa341tnv4#& z+b`R|B}puZD1ocy%;vK*u%_jL)ULPHJ|H@4fr;~pzmdC~d86q&uczg+>LQc=eLZCZ zA=D(gq};1L1C|hzVW)uktW-c5%){sGveAJ0)A{ru&E+^38KX|3ySP~L8k(cb=*jm0 zIYmnLuy78W$%y*bZ+{h;93kI1bU8gZS{bZ(;&f;l?TkfhyfRkBJJ;c-W|u^8q^Ip% zI>_U(V#M7%!L@%>i_({SffV&f1pXE z8nv%E{eb_*{=oroD^uh{uthXQG*J?B7w$_Z((`H*8b#IVPn|%6U9)k!1_#7e)Hng< zyP)eT<8oZ>!Ux$A0S!e-sBB3DcVEc#pQ@|#o*m4&o~-6;`{DCc#s$8N z^MBm9viI9S4z!oaw%B}7zfYb&^PBe_8&d}QKOV)6j#;z#)Jx&Y;=a1?Cw|@gK?n|p zJ2eqI|!5*qL7C7hkJC{ zI6fA$kgLYO&8N9P-n_^}tZtSdz?A#VWv4If{uRVow4y@u)9dy8#nT|E;LJC=wXQyy zqpouKa#WGgD^M@+jwBhYz=LKN$t@lFbRUDNuoGg&6eAM4e=+G}`S&;s0-7TqnRsZ{7XEC$Pin)WqIM2~LzgV^?wRV{iB%d&b)P{;;GH{E$R!U34%~CQsO;s^k%2S zQ<24Jmt;x)ZFoW&|M;DMD?mm3>mQw}SyHp)svb0Vu9X&!tssjt;)+i~p~I(h{^A&6 z;h1VW+LQEi{z8nyv0anpE<6*5J2A`ILk~68BWo$zqZ)mK+akn&JMz?R5nug&ccZ}{ z0GyyY?6yVtVe9uKzFnT^OXo13wiR%qciB^cdtZ|jfdEniw$RJjLgZpt%L+I3zRAtz zeisRMJ0Bgbk*tjz!5~DVKOtG^$%}84;?u#4jFn(FWzf@vL12@vrlvB3e(f+Cqjpn# z3=GWvEEVA|Z2Te6U6{@1=5dFhx z)nd2iiax((z*q1qu2(LgyekP;DjPL@EXnD?XNyI?>15R!>c1c1GSx_ffA`Ww$@aK0 zxD#AT*#HfH00ijmsnF_Y`qebc%Q+P?Z1*~OG~L|>zZtzEioyN@Ma}KoL4c}smsn_K zWd9;QJ#|2*(a~wcuGwuM{?VTeb<*2}vJ=B^q~a67yLxTWn_Hb@V+96;j=HPE-Rn8w z;S08l5R`T)4!1hH*S|w#o?Nt;@467`2lvELD-SIB&}tvA*XfwbKa>z|HZ(m)N7w?w zO$M3rzvx$;8M!Yt+{7Clt8&p>`Y9PYCmJR(KUP%-i5M}N&1!ueMfdAh<|)&0m7vj4 z`OJN>i(-9y;ih6Dyp`7Ovb3UcK67FHHPc@^ODXEeo$SQyAlO$++!8|dk*XiYU-F!b zS+_;GUW`?)ggtg>TG2@$(-TV(WAKZR1za1mErd$2!d~u^=rTq7UH&6*-@4=WXrc1? z+E)v;^0f;FROc<>+_n9Q^)h(t^-Zsq|I&|d(vFH?IODLl?3!+N2ed2X$BcD>zSh(v zHw;l01|Due7dq)z=&r=UYMJ|ZLc@o9lZdKIR$0Jru_1KJw+lr`SaCoqiZ;j;X&I#f zCguRtiNc?gZEh2on7lC)GgaP1G#-3H|!c3oxjKSh;;+Z{pnMU zkT$1bPkojBj`@H&h`X@f9#FlGMs4wLPy7=p&wOsg1}9EPEMI_m2%r7#+ayNE+sWVU zMZ##<^?II0ABd#M*0P4A=v4a2KKCE|mfGo68;FCONI|n!vG?+5_om_zfDZuVd(IpK z5Mwkv;BN)}LN*AyXwr}%xnDmzK5_abUZNNaNRk5Ai?vasQ0j>B-TdxA#;>x;A&tyq zvNX#3%x!^APG2M9;RqBT0wR0Up4lX}nci`T9_!aGrxN|D)X}lj{l+ou)IReyK2RE0TjtciSHb$#lQYWh^o&nYcZU>r$qphu5 z>k}dKN)_zi0LH=g^M+f8h5&l5c^@#*q&OJInv3bPlq&0$*O}^kOh+k6=ntS)m-Cb# z;g>Jjo4ll?)Sk&tavgSm9b@}R7OPfJ0*GUC^h;M5x0j+AixgUVn<@D@M}_Jff;kRvPkG zQD)1W9I}Tx1w?y3OGL=y4vih%II^3KSO#0+9pdKC{hltHk{1_8n?-#N+gi*?a2}e? zC=};lg?a-cPM!lcrQ{qBoq^l2`k*hz%ha8qz`n_V?_)Xd_MPU_wWG(~3&#Qn00d0Z zhar6Slu`UDY<_8UVbgSKE z?Qcpw8kr4%8U}x0!1ug`#guDrP$1E7wG0qhK)(!&Yf2=CRFLgL7lVF07FkP7gI}E&$aC%T5ZbpI2=p;CN2r=6)F@dm3X$ z%I)Ab%8QXrZW0?JXuC;s-b%bEtWf3tVLB!C^qlBR{;d`;VHN%@k9xsKeI=3kV{c0GL;@j}2#HOh#Z*y?}=!8cl*242S7T zTnVGYrf-^MX&QMg(~2fAf>O1HAw&xBdl(JxKZ9}|pTI}dS9`%u<7bzvgs`5N80~rZ z#}^j+NU>5kS)05PvCFd>Hy+{d%n6P$FIo|rgn2FSP5YDKaC9ugZCT4{NkDZ$A-jzPjdgg zqdFUiO-W_)CQ$YU^gyADis*s1;Cg?_+obQ>guSA^e7;qHC%=#%9Vbos21Pi|AMW@= z{cDxsBvIL)r+{9mlri&8c@c3hL9qTFz=d*e6F9P5)`kVowPt2M3&#M;@%4{J5lzEn z$d4Vv%$N5v)PUbVu8#QeM-u1jpz@)C>MS(e?dn#pM1}{b zZKX&l*|F)0r6e+vCqpX+(fBI8>!TpUV>5|SR~2;tPXpkT{MU?fe8$he?N#*rlN3HQ zJS2NOr@whHw`Sq3o)@nxj2aSB^aM60xUqga@Z2khXly{P(iYS-HC!?Pag~ru^&S2r zz5mURj(>g@1D!2d=$=8v>LcU}FOVtvPt&MSJcb02h;tw;OF1!bGc@sHjLa8!_@MKL zH>Sm;m4Iz9g?MsLL{r25d}Fn;h}z(%1(MZcdUO*Rnd#5BqK%A>k0j{-vR(Bb*5SL9 zh_MUpl4SBEI+Ak)jS3?{RDB3q&Cn38?xqQPh%T{q=APnX=*XRGQhD$V!1x8Hh!?f7 z-HBi!Z9?$hZzrbp#@p`LmM1xdW;TWPV87hW@fxY8$bdzltiG|No|vAY9Jq`MQt~>o z@rZie&~RWmkR^MmWGVmpxN&mqh;sM4PeKk+Ah*5cj_XAN4oh9d67z+`M6Gf^CB4ub z^c(u_M&%VKlfR(JBEofA>ExsI?3$36#|`ew*R3fPpQtVU?2O~UN_UP(5WK!2EWM<1i$50$Onfp(fA+ZNOhgoV!$Q9V9SUW<$y-eSk~)p}%1 zw?{>-#2a%2hC`gsQ4459>Pi4idVhbB))t6-7jN?&O*cQ{^kF7i?})KQy72~$<9BFN&Uv7WjY2Me=hDA_XbYT)tT0yvQC}yvr!*IHbBPM|WaEgi zM8|`JNxzFgo?BA?btsZ-IrmYctM1uG6FGHbF8j}5?2No$l~pI0?mD^03ZiWQmkkwW z@@Ukzf`FUc*LM}_q@F$DJp-4{*&c8_mt-!Dde^%`vj>{TH`w5A3hr_YE)dL}{48}{ z5M%1=J1$ji~Cwf8VPq|MI zcY2HKUq@fNnHEN+P!4T$)+`Mhhm-2JF)xdpV|n202z>fi2uYb1voj(WV_h#WCRb!J zMNy)qa;Pi$9amV6LBFBk_*8nTs@hPFTGejx{c-fvcU&pIJ%RNT`lMWv^JFFBt719T z3))?VHfZGgVQN{M1(3(5B^|5(1`d7 z(e3e^4!nayoGwPols-!-v6OERntM;je(4Z{t$hiBSN!4A6-Whg!pl}MrpmcFgni3& zWf0Ch?XS49uCWBice-Hk>}YJ2`CcD^FsQ7ya%6XADXoumPb_ovVQ8v-Aw-ZWWRk>2 z%i%JdEFj-PGueBzvZvx5V=B0PSzJ8Q-w4@^NUp7_A#9pfxqO)uzm>SRSyE;B*5PvG z)iEaYlwZwcvxt)Q-lEGX8}6j}{(8$&zs+P{t_ma7h^SB(NU_o<4uTl*P zh7?}(2Zy8fhe_shmuc77wAblbn|pU>Ncl6Tx4F*n-2J3rke6*qOYFA*?;YHzE&SX2 zl*mx4KBikFGA>O0nngi}lSLb+?PT5VwifBtyF3k9))#IvG78c+PqNV0bA<1>B$G#m ztdc>%fPmP;`e&|@q*(q^FbA!V9@2x4hcl;TwK$IE6X7&(A3BLCI@H{E0zFvBjm zLSAe)jX;hp*zcMpq@*I6canaiPRbOR*_@9HjY;TWg(K>fE6ahbPvDEda%9v-?f&^x z&QMzeZCg$z{VoEgQOvz7?0fs)PcN0EPiD3fgWO}fmMW?=25;%9rEDw;njc{{s=psE zq3)MWnhEZ=Y$bb4Z<=3sNC#NuHrY2yk8FCtL9Wn?A*crWM`@fDv21I$-N zsb5#$gkA%1K=wS^BZu~Q~b#`#N_MyQ*{zZS- zi@1?+$XO{7;r)-3ut(Hp`9fMnO~%Rka!-y##6=lg(LeHopwn-R-LBuD%6f6)N> z&to!8amOTHK}14tf<++~{{CIX#@81YDVDF!=$Ba;1n^Wn3WFwt(KubM>^7jtlCbf3oyl{}z>6e7;f zV?;D`d$x+va|!j0_pBKgqbP^-S|; zMu07HMpu0}ofD`SxG}`tQ|Uo<(|+h5H5>hpgHK?IAvX1ohms&|-2eNb4z`-s&7Ba% zc?HJQ!a@zZnf;bz+&Xov`3uB14@mkGwa${%R5}f9iQ<#(Xr@D>^Qm38r@V&fHzxPb zznZ6JbvrW5uZEsU*%c7rJ>>SR1z&6Lr1KKimtMf zOi2gGZAD|w9tCtIaQgyjRSz|IK969TAt~-h5bj;YuUyC7wLP~^j&ayKNZV< zFB9iVy96OiJDcW#zk-+ExH{10#KakO4DkOob!Z8w506*m~ccbuq&Pk0AR3F|Es9fIM@h%X?^SE~n$pVbp214(=?S!Sn9h6N(%(L`=J#UjP#;>%v`A+un^_AJKcJ&7l)C=N9Jq{% zsp=+cZg4Ze+xq+CH*sGyxqiB^>*Sm8Y0xHZN}ES#9-4O{kmu%-qNAgCgwb{aVewkn zza|gS!#C7FXl&?x)UE^0=r7>g7{KJ+P5p*J2A$Krl(?TsY!i&BO3JZ2Ls;38LDYrN zvD2$mCELm3srkh2?K>OYT~{f6=RBwAxCN}32T&Sym}Ij!=k9M~EQwHmgV}F4GD`Wp zSA~xChhemF;llY=G2)T?Kn2PeN(mr`V09xYmkxMqT#&3QoNB!aQc|Mk);v-LLh4LQ z^VXdIMBFZRghG~~|Hs0UZ(ZSx8M4~0!HtJdKL#QSF;P_MmoFjF=sB;Z{-fad|I<-M zC8O&&J8ScMb8o0OW5{^mK<8#N#XZfGi{Qr2iy`0pbQBcA0Mh{-sT2qz<4}6`Qa@dL zhm7n4IYFZCJyn|*_T1umgWHi-L*jI28DFL)^o|)nGhz~-S39>!wX0n}8V&udvR-Lk zGZ==BR<34(bb@_}^M^q!)lS7f2|IZ&agVDc*~ZSWk7TUHiwGEU9Ou#mrWEs+@ny8XLp5)x2i(k!TG4A!!g^ z^fkb?2lI8_CPY4)BpU}MZN=i8ek`@NYQ1Y#`3D1DSgJ5Ie=kGO@eRLRRBU&$aoNTk zt^2<=4*^o`q5kvZB?zhYx~mbu5v$4QE2#$=`hdax%ydA17&3dMUbK4ZbH;F1;LFCE z*}F4DN9%+e0euAvI7W+wc#fxm|8STeNd*!W%e60>wI5Caki;rY%nk&k`g*aozI3Y> zFR()w2Tu1ln1Bt5Vc+Wdak^^>m6l4Iyy^db;UOm#WXn`yAV|6X(Q5Ne zaG<>o-&CXX;+IDMHH9y3=--fC#_UpfWXZ_5$j0Y7iDZj&!uHv|Bj*YFOJAapd<*J~3 zf3l5C(MZl#Cp~T#zz$Q8fnx%b2*F@qZJ5jyv@){K|6yc<^4letQ6jpo=VksoA{IJs zB_sPgeei#w%-|Cc(Y$?Ly!>0|^1oAO|GR7W&vxu({tr*@-$J^g1A`jy*QFX9m|3`T f>FrZf&$H`q-_Qi+T~si<0Dpw}CHS(QzjpgyL@Z=j diff --git a/reader-writer-lock/etc/reader-writer-lock.ucls b/reader-writer-lock/etc/reader-writer-lock.ucls deleted file mode 100644 index 920904e76843..000000000000 --- a/reader-writer-lock/etc/reader-writer-lock.ucls +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/reader-writer-lock/etc/reader-writer-lock.urm.puml b/reader-writer-lock/etc/reader-writer-lock.urm.puml deleted file mode 100644 index b71cf73f6374..000000000000 --- a/reader-writer-lock/etc/reader-writer-lock.urm.puml +++ /dev/null @@ -1,61 +0,0 @@ -@startuml -package com.iluwatar.reader.writer.lock { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Reader { - - LOGGER : Logger {static} - - name : String - - readLock : Lock - + Reader(name : String, readLock : Lock) - + read() - + run() - } - class ReaderWriterLock { - - currentReaderCount : int - - globalMutex : Set - - readerLock : ReadLock - - readerMutex : Object - - writerLock : WriteLock - + ReaderWriterLock() - - doesReaderOwnThisLock() : boolean - - doesWriterOwnThisLock() : boolean - - isLockFree() : boolean - + readLock() : Lock - - waitUninterruptibly(o : Object) {static} - + writeLock() : Lock - } - -class ReadLock { - - ReadLock() - + lock() - + lockInterruptibly() - + newCondition() : Condition - + tryLock() : boolean - + tryLock(time : long, unit : TimeUnit) : boolean - + unlock() - } - -class WriteLock { - - WriteLock() - + lock() - + lockInterruptibly() - + newCondition() : Condition - + tryLock() : boolean - + tryLock(time : long, unit : TimeUnit) : boolean - + unlock() - } - class Writer { - - LOGGER : Logger {static} - - name : String - - writeLock : Lock - + Writer(name : String, writeLock : Lock) - + run() - + write() - } -} -ReaderWriterLock --> "-readerLock" ReadLock -ReadLock --+ ReaderWriterLock -WriteLock --+ ReaderWriterLock -ReaderWriterLock --> "-writerLock" WriteLock -@enduml \ No newline at end of file diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml deleted file mode 100644 index d5ea9114c9f6..000000000000 --- a/reader-writer-lock/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - reader-writer-lock - - - junit - junit - test - - - org.mockito - mockito-core - test - - - - 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 deleted file mode 100644 index 42335f313f1c..000000000000 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.reader.writer.lock; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * In a multiple thread applications, the threads may try to synchronize the shared resources - * regardless of read or write operation. It leads to a low performance especially in a "read more - * write less" system as indeed the read operations are thread-safe to another read operation. - *

    - * Reader writer lock is a synchronization primitive that try to resolve this problem. This pattern - * allows concurrent access for read-only operations, while write operations require exclusive - * access. This means that multiple threads can read the data in parallel but an exclusive lock is - * needed for writing or modifying data. When a writer is writing the data, all other writers or - * readers will be blocked until the writer is finished writing. - * - *

    - * This example use two mutex to demonstrate the concurrent access of multiple readers and writers. - * - * - * @author hongshuwei@gmail.com - */ -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) { - - ExecutorService executeService = Executors.newFixedThreadPool(10); - ReaderWriterLock lock = new ReaderWriterLock(); - - // Start writers - IntStream.range(0, 5) - .forEach(i -> executeService.submit(new Writer("Writer " + i, lock.writeLock(), - ThreadLocalRandom.current().nextLong(5000)))); - LOGGER.info("Writers added..."); - - // Start readers - IntStream.range(0, 5) - .forEach(i -> executeService.submit(new Reader("Reader " + i, lock.readLock(), - ThreadLocalRandom.current().nextLong(10)))); - LOGGER.info("Readers added..."); - - try { - Thread.sleep(5000L); - } catch (InterruptedException e) { - LOGGER.error("Error sleeping before adding more readers", e); - Thread.currentThread().interrupt(); - } - - // Start readers - IntStream.range(6, 10) - .forEach(i -> executeService.submit(new Reader("Reader " + i, lock.readLock(), - ThreadLocalRandom.current().nextLong(10)))); - LOGGER.info("More readers added..."); - - - - // In the system console, it can see that the read operations are executed concurrently while - // write operations are exclusive. - executeService.shutdown(); - try { - executeService.awaitTermination(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Error waiting for ExecutorService shutdown", e); - Thread.currentThread().interrupt(); - } - - } - -} 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 deleted file mode 100644 index b0ccecabadaf..000000000000 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -import java.util.concurrent.locks.Lock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Reader class, read when it acquired the read lock - */ -public class Reader implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(Reader.class); - - private Lock readLock; - - private String name; - - private long readingTime; - - /** - * Create new Reader - * - * @param name - Name of the thread owning the reader - * @param readLock - Lock for this reader - * @param readingTime - amount of time (in milliseconds) for this reader to engage reading - */ - public Reader(String name, Lock readLock, long readingTime) { - this.name = name; - this.readLock = readLock; - this.readingTime = readingTime; - } - - /** - * Create new Reader who reads for 250ms - * - * @param name - Name of the thread owning the reader - * @param readLock - Lock for this reader - */ - public Reader(String name, Lock readLock) { - this(name, readLock, 250L); - } - - @Override - public void run() { - readLock.lock(); - try { - read(); - } catch (InterruptedException e) { - LOGGER.info("InterruptedException when reading", e); - Thread.currentThread().interrupt(); - } finally { - readLock.unlock(); - } - } - - /** - * Simulate the read operation - * - */ - public void read() throws InterruptedException { - LOGGER.info("{} begin", name); - Thread.sleep(readingTime); - LOGGER.info("{} finish after reading {}ms", name, readingTime); - } -} diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java deleted file mode 100644 index b377b2273901..000000000000 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java +++ /dev/null @@ -1,221 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class responsible for control the access for reader or writer - * - * Allows multiple readers to hold the lock at same time, but if any writer holds the lock then readers wait. If reader - * holds the lock then writer waits. This lock is not fair. - */ -public class ReaderWriterLock implements ReadWriteLock { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReaderWriterLock.class); - - - private Object readerMutex = new Object(); - - private int currentReaderCount; - - /** - * Global mutex is used to indicate that whether reader or writer gets the lock in the moment. - *

    - * 1. When it contains the reference of {@link readerLock}, it means that the lock is acquired by the reader, another - * reader can also do the read operation concurrently.
    - * 2. When it contains the reference of reference of {@link writerLock}, it means that the lock is acquired by the - * writer exclusively, no more reader or writer can get the lock. - *

    - * This is the most important field in this class to control the access for reader/writer. - */ - private Set globalMutex = new HashSet<>(); - - private ReadLock readerLock = new ReadLock(); - private WriteLock writerLock = new WriteLock(); - - @Override - public Lock readLock() { - return readerLock; - } - - @Override - public Lock writeLock() { - return writerLock; - } - - /** - * return true when globalMutex hold the reference of writerLock - */ - private boolean doesWriterOwnThisLock() { - return globalMutex.contains(writerLock); - } - - /** - * Nobody get the lock when globalMutex contains nothing - * - */ - private boolean isLockFree() { - return globalMutex.isEmpty(); - } - - /** - * Reader Lock, can be access for more than one reader concurrently if no writer get the lock - */ - private class ReadLock implements Lock { - - @Override - public void lock() { - synchronized (readerMutex) { - currentReaderCount++; - if (currentReaderCount == 1) { - acquireForReaders(); - } - } - } - - /** - * Acquire the globalMutex lock on behalf of current and future concurrent readers. Make sure no writers currently - * owns the lock. - */ - private void acquireForReaders() { - // Try to get the globalMutex lock for the first reader - synchronized (globalMutex) { - // If the no one get the lock or the lock is locked by reader, just set the reference - // to the globalMutex to indicate that the lock is locked by Reader. - while (doesWriterOwnThisLock()) { - try { - globalMutex.wait(); - } catch (InterruptedException e) { - LOGGER.info("InterruptedException while waiting for globalMutex in acquireForReaders", e); - Thread.currentThread().interrupt(); - } - } - globalMutex.add(this); - } - } - - @Override - public void unlock() { - - synchronized (readerMutex) { - currentReaderCount--; - // Release the lock only when it is the last reader, it is ensure that the lock is released - // when all reader is completely. - if (currentReaderCount == 0) { - synchronized (globalMutex) { - // Notify the waiter, mostly the writer - globalMutex.remove(this); - globalMutex.notifyAll(); - } - } - } - - } - - @Override - public void lockInterruptibly() throws InterruptedException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean tryLock() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - throw new UnsupportedOperationException(); - } - - @Override - public Condition newCondition() { - throw new UnsupportedOperationException(); - } - - } - - /** - * Writer Lock, can only be accessed by one writer concurrently - */ - private class WriteLock implements Lock { - - @Override - public void lock() { - - synchronized (globalMutex) { - - // Wait until the lock is free. - while (!isLockFree()) { - try { - globalMutex.wait(); - } catch (InterruptedException e) { - LOGGER.info("InterruptedException while waiting for globalMutex to begin writing", e); - Thread.currentThread().interrupt(); - } - } - // When the lock is free, acquire it by placing an entry in globalMutex - globalMutex.add(this); - } - } - - @Override - public void unlock() { - - synchronized (globalMutex) { - globalMutex.remove(this); - // Notify the waiter, other writer or reader - globalMutex.notifyAll(); - } - } - - @Override - public void lockInterruptibly() throws InterruptedException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean tryLock() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - throw new UnsupportedOperationException(); - } - - @Override - public Condition newCondition() { - throw new UnsupportedOperationException(); - } - } - -} 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 deleted file mode 100644 index dc379eef97ba..000000000000 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -import java.util.concurrent.locks.Lock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Writer class, write when it acquired the write lock - */ -public class Writer implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(Writer.class); - - private Lock writeLock; - - private String name; - - private long writingTime; - - /** - * Create new Writer who writes for 250ms - * - * @param name - Name of the thread owning the writer - * @param writeLock - Lock for this writer - */ - public Writer(String name, Lock writeLock) { - this(name, writeLock, 250L); - } - - /** - * Create new Writer - * - * @param name - Name of the thread owning the writer - * @param writeLock - Lock for this writer - * @param writingTime - amount of time (in milliseconds) for this reader to engage writing - */ - public Writer(String name, Lock writeLock, long writingTime) { - this.name = name; - this.writeLock = writeLock; - this.writingTime = writingTime; - } - - - @Override - public void run() { - writeLock.lock(); - try { - write(); - } catch (InterruptedException e) { - LOGGER.info("InterruptedException when writing", e); - Thread.currentThread().interrupt(); - } finally { - writeLock.unlock(); - } - } - - /** - * Simulate the write operation - */ - public void write() throws InterruptedException { - LOGGER.info("{} begin", name); - Thread.sleep(writingTime); - LOGGER.info("{} finished after writing {}ms", name, writingTime); - } -} diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java deleted file mode 100644 index fd0cd4b270a7..000000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - - } -} 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 deleted file mode 100644 index adc2adae2001..000000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.reader.writer.lock; - -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 static org.junit.Assert.assertTrue; - -/** - * @author hongshuwei@gmail.com - */ -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); - - /** - * Verify reader and writer can only get the lock to read and write orderly - */ - @Test - public void testReadAndWrite() throws Exception { - - ReaderWriterLock lock = new ReaderWriterLock(); - - Reader reader1 = new Reader("Reader 1", lock.readLock()); - Writer writer1 = new Writer("Writer 1", lock.writeLock()); - - ExecutorService executeService = Executors.newFixedThreadPool(2); - executeService.submit(reader1); - // Let reader1 execute first - Thread.sleep(150); - executeService.submit(writer1); - - executeService.shutdown(); - try { - executeService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Error waiting for ExecutorService shutdown", e); - } - - assertTrue(appender.logContains("Reader 1 begin")); - assertTrue(appender.logContains("Reader 1 finish")); - assertTrue(appender.logContains("Writer 1 begin")); - assertTrue(appender.logContains("Writer 1 finish")); - } - - /** - * Verify reader and writer can only get the lock to read and write orderly - */ - @Test - public void testWriteAndRead() throws Exception { - - ExecutorService executeService = Executors.newFixedThreadPool(2); - ReaderWriterLock lock = new ReaderWriterLock(); - - Reader reader1 = new Reader("Reader 1", lock.readLock()); - Writer writer1 = new Writer("Writer 1", lock.writeLock()); - - executeService.submit(writer1); - // Let writer1 execute first - Thread.sleep(150); - executeService.submit(reader1); - - executeService.shutdown(); - try { - executeService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Error waiting for ExecutorService shutdown", e); - } - - 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 deleted file mode 100644 index c9b3eb72cd17..000000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -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 static junit.framework.TestCase.assertTrue; -import static org.mockito.Mockito.spy; - -/** - * @author hongshuwei@gmail.com - */ -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); - - /** - * Verify that multiple readers can get the read lock concurrently - */ - @Test - public void testRead() throws Exception { - - ExecutorService executeService = Executors.newFixedThreadPool(2); - ReaderWriterLock lock = new ReaderWriterLock(); - - Reader reader1 = spy(new Reader("Reader 1", lock.readLock())); - Reader reader2 = spy(new Reader("Reader 2", lock.readLock())); - - executeService.submit(reader1); - Thread.sleep(150); - executeService.submit(reader2); - - executeService.shutdown(); - try { - executeService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Error waiting for ExecutorService shutdown", e); - } - - // Read operation will hold the read lock 250 milliseconds, so here we prove that multiple reads - // can be performed in the same time. - 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/WriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java deleted file mode 100644 index 7c4b4148dc78..000000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.reader.writer.lock; - -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 static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.spy; - -/** - * @author hongshuwei@gmail.com - */ -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); - - /** - * Verify that multiple writers will get the lock in order. - */ - @Test - public void testWrite() throws Exception { - - ExecutorService executeService = Executors.newFixedThreadPool(2); - ReaderWriterLock lock = new ReaderWriterLock(); - - Writer writer1 = spy(new Writer("Writer 1", lock.writeLock())); - Writer writer2 = spy(new Writer("Writer 2", lock.writeLock())); - - executeService.submit(writer1); - // Let write1 execute first - Thread.sleep(150); - executeService.submit(writer2); - - executeService.shutdown(); - try { - executeService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - 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 - // finished. - 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 deleted file mode 100644 index b8ad531ce856..000000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; - -/** - * InMemory Log Appender Util. - */ -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().contains(message)); - } -} diff --git a/repository/README.md b/repository/README.md deleted file mode 100644 index 501f39f9c60a..000000000000 --- a/repository/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: pattern -title: Repository -folder: repository -permalink: /patterns/repository/ -pumlid: JSV13OCm30NGLM00udktCS42eyI9xE-YRjyUUtjlLQij3qblomNCU14vF-LKNBbdYDTX44EfevEsV1ZiTFERjqD2Jzic0-8Mr3b-89SvGZ7yGuBwrvBUoypUlW00 -categories: Persistence Tier -tags: - - Java - - Difficulty-Intermediate - - Spring ---- - -## Intent -Repository layer is added between the domain and data mapping -layers to isolate domain objects from details of the database access code and -to minimize scattering and duplication of query code. The Repository pattern is -especially useful in systems where number of domain classes is large or heavy -querying is utilized. - -![alt text](./etc/repository.png "Repository") - -## Applicability -Use the Repository pattern when - -* the number of domain objects is large -* you want to avoid duplication of query code -* you want to keep the database querying code in single place -* you have multiple data sources - -## Real world examples - -* [Spring Data](http://projects.spring.io/spring-data/) - -## Credits - -* [Don’t use DAO, use Repository](http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/) -* [Advanced Spring Data JPA - Specifications and Querydsl](https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/) diff --git a/repository/etc/repository.png b/repository/etc/repository.png deleted file mode 100644 index 08d5d571d0a82607a3c714686c6f58e0999f81b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55254 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%0Db#Ymqoa9Uf5(TB(u>Gdf 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 diff --git a/repository/etc/repository.ucls b/repository/etc/repository.ucls deleted file mode 100644 index 894e9434cccc..000000000000 --- a/repository/etc/repository.ucls +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/repository/etc/repository.urm.puml b/repository/etc/repository.urm.puml deleted file mode 100644 index 10768260cefc..000000000000 --- a/repository/etc/repository.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.repository { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class AppConfig { - - LOGGER : Logger {static} - + AppConfig() - + dataSource() : DataSource - + entityManagerFactory() : LocalContainerEntityManagerFactoryBean - - jpaProperties() : Properties {static} - + main(args : String[]) {static} - + transactionManager() : JpaTransactionManager - } - class Person { - - age : int - - id : Long - - name : String - - surname : String - + Person() - + Person(name : String, surname : String, age : int) - + equals(obj : Object) : boolean - + getAge() : int - + getId() : Long - + getName() : String - + getSurname() : String - + hashCode() : int - + setAge(age : int) - + setId(id : Long) - + setName(name : String) - + setSurname(surname : String) - + toString() : String - } - interface PersonRepository { - + findByName(String) : Person {abstract} - } - class PersonSpecifications { - + PersonSpecifications() - } - class AgeBetweenSpec { - - from : int - - to : int - + AgeBetweenSpec(from : int, to : int) - + toPredicate(root : Root, query : CriteriaQuery, cb : CriteriaBuilder) : Predicate - } - class NameEqualSpec { - + name : String - + NameEqualSpec(name : String) - + toPredicate(root : Root, query : CriteriaQuery, cb : CriteriaBuilder) : Predicate - } -} -NameEqualSpec ..+ PersonSpecifications -AgeBetweenSpec ..+ PersonSpecifications -@enduml \ No newline at end of file diff --git a/repository/pom.xml b/repository/pom.xml deleted file mode 100644 index f12c4011376c..000000000000 --- a/repository/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - repository - - - org.springframework - spring-test - - - org.springframework.data - spring-data-jpa - - - org.hibernate - hibernate-entitymanager - - - commons-dbcp - commons-dbcp - - - com.h2database - h2 - - - junit - junit - test - - - com.google.guava - guava - - - diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java deleted file mode 100644 index d96b4351ea38..000000000000 --- a/repository/src/main/java/com/iluwatar/repository/App.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * Repository pattern mediates between the domain and data mapping layers using a collection-like - * interface for accessing domain objects. A system with complex domain model often benefits from a - * layer that isolates domain objects from the details of the database access code and in such - * systems it can be worthwhile to build another layer of abstraction over the mapping layer where - * query construction code is concentrated. This becomes more important when there are a large - * number of domain classes or heavy querying. In these cases particularly, adding this layer helps - * minimize duplicate query logic. - *

    - * In this example we utilize Spring Data to automatically generate a repository for us from the - * {@link Person} domain object. Using the {@link PersonRepository} we perform CRUD operations on - * the entity, moreover, the query by {@link org.springframework.data.jpa.domain.Specification} are - * also performed. Underneath we have configured in-memory H2 database for which schema is created - * and dropped on each run. - */ -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) { - - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "applicationContext.xml"); - PersonRepository repository = context.getBean(PersonRepository.class); - - Person peter = new Person("Peter", "Sagan", 17); - Person nasta = new Person("Nasta", "Kuzminova", 25); - Person john = new Person("John", "lawrence", 35); - Person terry = new Person("Terry", "Law", 36); - - // Add new Person records - repository.save(peter); - repository.save(nasta); - repository.save(john); - repository.save(terry); - - // Count Person records - LOGGER.info("Count Person records: {}", repository.count()); - - // Print all records - List persons = (List) repository.findAll(); - for (Person person : persons) { - LOGGER.info(person.toString()); - } - - // Update Person - nasta.setName("Barbora"); - nasta.setSurname("Spotakova"); - repository.save(nasta); - - LOGGER.info("Find by id 2: {}", repository.findOne(2L)); - - // Remove record from Person - repository.delete(2L); - - // count records - LOGGER.info("Count Person records: {}", repository.count()); - - // find by name - Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); - LOGGER.info("Find by John is {}", p); - - // find by age - persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - - LOGGER.info("Find Person with age between 20,40: "); - for (Person person : persons) { - LOGGER.info(person.toString()); - } - - repository.deleteAll(); - - context.close(); - - } -} diff --git a/repository/src/main/java/com/iluwatar/repository/AppConfig.java b/repository/src/main/java/com/iluwatar/repository/AppConfig.java deleted file mode 100644 index c5ccb7d00002..000000000000 --- a/repository/src/main/java/com/iluwatar/repository/AppConfig.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import java.sql.SQLException; -import java.util.List; -import java.util.Properties; - -import javax.sql.DataSource; - -import org.apache.commons.dbcp.BasicDataSource; -import org.hibernate.jpa.HibernatePersistenceProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; - -/** - * This is the same example as in {@link App} but with annotations based - * configuration for Spring. - * - */ -@EnableJpaRepositories -public class AppConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(AppConfig.class); - - /** - * Creation of H2 db - * - * @return A new Instance of DataSource - */ - @Bean(destroyMethod = "close") - public DataSource dataSource() { - BasicDataSource basicDataSource = new BasicDataSource(); - basicDataSource.setDriverClassName("org.h2.Driver"); - basicDataSource.setUrl("jdbc:h2:~/databases/person"); - basicDataSource.setUsername("sa"); - basicDataSource.setPassword("sa"); - return (DataSource) basicDataSource; - } - - /** - * Factory to create a especific instance of Entity Manager - */ - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); - entityManager.setDataSource(dataSource()); - entityManager.setPackagesToScan("com.iluwatar"); - entityManager.setPersistenceProvider(new HibernatePersistenceProvider()); - entityManager.setJpaProperties(jpaProperties()); - - return entityManager; - } - - /** - * Properties for Jpa - */ - private static Properties jpaProperties() { - Properties properties = new Properties(); - properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); - properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); - return properties; - } - - /** - * Get transaction manager - */ - @Bean - public JpaTransactionManager transactionManager() throws SQLException { - JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return transactionManager; - } - - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - AppConfig.class); - PersonRepository repository = context.getBean(PersonRepository.class); - - Person peter = new Person("Peter", "Sagan", 17); - Person nasta = new Person("Nasta", "Kuzminova", 25); - Person john = new Person("John", "lawrence", 35); - Person terry = new Person("Terry", "Law", 36); - - // Add new Person records - repository.save(peter); - repository.save(nasta); - repository.save(john); - repository.save(terry); - - // Count Person records - LOGGER.info("Count Person records: {}", repository.count()); - - // Print all records - List persons = (List) repository.findAll(); - for (Person person : persons) { - LOGGER.info(person.toString()); - } - - // Update Person - nasta.setName("Barbora"); - nasta.setSurname("Spotakova"); - repository.save(nasta); - - LOGGER.info("Find by id 2: {}", repository.findOne(2L)); - - // Remove record from Person - repository.delete(2L); - - // count records - LOGGER.info("Count Person records: {}", repository.count()); - - // find by name - Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); - LOGGER.info("Find by John is {}", p); - - // find by age - persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - - LOGGER.info("Find Person with age between 20,40: "); - for (Person person : persons) { - LOGGER.info(person.toString()); - } - - context.close(); - - } - -} diff --git a/repository/src/main/java/com/iluwatar/repository/Person.java b/repository/src/main/java/com/iluwatar/repository/Person.java deleted file mode 100644 index d37234e43b3a..000000000000 --- a/repository/src/main/java/com/iluwatar/repository/Person.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - -/** - * - * Person entity - * - */ -@Entity -public class Person { - - @Id - @GeneratedValue - private Long id; - private String name; - private String surname; - - private int age; - - public Person() { - } - - /** - * Constructor - */ - public Person(String name, String surname, int age) { - this.name = name; - this.surname = surname; - this.age = age; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getSurname() { - return surname; - } - - public void setSurname(String surname) { - this.surname = surname; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - @Override - public String toString() { - return "Person [id=" + id + ", name=" + name + ", surname=" + surname + ", age=" + age + "]"; - } - - @Override - public int hashCode() { - - final int prime = 31; - int result = 1; - result = prime * result + age; - result = prime * result + (id == null ? 0 : id.hashCode()); - result = prime * result + (name == null ? 0 : name.hashCode()); - result = prime * result + (surname == null ? 0 : surname.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Person other = (Person) obj; - if (age != other.age) { - return false; - } - if (id == null) { - if (other.id != null) { - return false; - } - } else if (!id.equals(other.id)) { - return false; - } - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (surname == null) { - if (other.surname != null) { - return false; - } - } else if (!surname.equals(other.surname)) { - return false; - } - return true; - } - -} diff --git a/repository/src/main/java/com/iluwatar/repository/PersonRepository.java b/repository/src/main/java/com/iluwatar/repository/PersonRepository.java deleted file mode 100644 index e999116cad02..000000000000 --- a/repository/src/main/java/com/iluwatar/repository/PersonRepository.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; - -/** - * - * Person repository - * - */ -@Repository -public interface PersonRepository - extends CrudRepository, JpaSpecificationExecutor { - - Person findByName(String name); -} diff --git a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java deleted file mode 100644 index 3da46e2eec0a..000000000000 --- a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; - -import org.springframework.data.jpa.domain.Specification; - -/** - * Helper class, includes vary Specification as the abstraction of sql query criteria - */ -public class PersonSpecifications { - - /** - * Specifications stating the Between (From - To) Age Specification - */ - public static class AgeBetweenSpec implements Specification { - - private int from; - - private int to; - - public AgeBetweenSpec(int from, int to) { - this.from = from; - this.to = to; - } - - @Override - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - - return cb.between(root.get("age"), from, to); - - } - - } - - /** - * Name specification - * - */ - public static class NameEqualSpec implements Specification { - - public String name; - - public NameEqualSpec(String name) { - this.name = name; - } - - /** - * Get predicate - */ - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - - return cb.equal(root.get("name"), this.name); - - } - } - -} diff --git a/repository/src/main/resources/META-INF/persistence.xml b/repository/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index 257495cb72c5..000000000000 --- a/repository/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - diff --git a/repository/src/main/resources/applicationContext.xml b/repository/src/main/resources/applicationContext.xml deleted file mode 100644 index 26d6cb3f4dc3..000000000000 --- a/repository/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repository/src/main/resources/logback.xml b/repository/src/main/resources/logback.xml deleted file mode 100644 index 56b6a59bb6cf..000000000000 --- a/repository/src/main/resources/logback.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - repository.log - - repository-%d.log - 5 - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - - - - - - - - diff --git a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java deleted file mode 100644 index cb84b1ae8311..000000000000 --- a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.List; - -import javax.annotation.Resource; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -import com.google.common.collect.Lists; - -/** - * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query - * by {@link org.springframework.data.jpa.domain.Specification} are also test. - * - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { AppConfig.class }, loader = AnnotationConfigContextLoader.class) -public class AnnotationBasedRepositoryTest { - - @Resource - private PersonRepository repository; - - Person peter = new Person("Peter", "Sagan", 17); - Person nasta = new Person("Nasta", "Kuzminova", 25); - Person john = new Person("John", "lawrence", 35); - Person terry = new Person("Terry", "Law", 36); - - List persons = Arrays.asList(peter, nasta, john, terry); - - /** - * Prepare data for test - */ - @Before - public void setup() { - - repository.save(persons); - } - - @Test - public void testFindAll() { - - List actuals = Lists.newArrayList(repository.findAll()); - assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals)); - } - - @Test - public void testSave() { - - Person terry = repository.findByName("Terry"); - terry.setSurname("Lee"); - terry.setAge(47); - repository.save(terry); - - terry = repository.findByName("Terry"); - assertEquals(terry.getSurname(), "Lee"); - assertEquals(47, terry.getAge()); - } - - @Test - public void testDelete() { - - Person terry = repository.findByName("Terry"); - repository.delete(terry); - - assertEquals(3, repository.count()); - assertNull(repository.findByName("Terry")); - } - - @Test - public void testCount() { - - assertEquals(4, repository.count()); - } - - @Test - public void testFindAllByAgeBetweenSpec() { - - List persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - - assertEquals(3, persons.size()); - assertTrue(persons.stream().allMatch((item) -> { - return item.getAge() > 20 && item.getAge() < 40; - })); - } - - @Test - public void testFindOneByNameEqualSpec() { - - Person actual = repository.findOne(new PersonSpecifications.NameEqualSpec("Terry")); - assertEquals(terry, actual); - } - - @After - public void cleanup() { - - repository.deleteAll(); - } - -} diff --git a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java deleted file mode 100644 index 6d6a58e8dd86..000000000000 --- a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.springframework.transaction.annotation.Transactional; - -/** - * This case is Just for test the Annotation Based configuration - * - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { AppConfig.class }, loader = AnnotationConfigContextLoader.class) -public class AppConfigTest { - - @Autowired - DataSource dataSource; - - /** - * Test for bean instance - */ - @Test - public void testDataSource() { - assertNotNull(dataSource); - } - - /** - * Test for correct query execution - */ - @Test - @Transactional - public void testQuery() throws SQLException { - ResultSet resultSet = dataSource.getConnection().createStatement().executeQuery("SELECT 1"); - String result = null; - String expected = "1"; - while (resultSet.next()) { - result = resultSet.getString(1); - - } - assertTrue(result.equals(expected)); - } - -} diff --git a/repository/src/test/java/com/iluwatar/repository/AppTest.java b/repository/src/test/java/com/iluwatar/repository/AppTest.java deleted file mode 100644 index d3f05caaa5e4..000000000000 --- a/repository/src/test/java/com/iluwatar/repository/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import org.junit.Test; - -import java.io.IOException; - -/** - * Tests that Repository example runs without errors. - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java deleted file mode 100644 index 3201c024cac7..000000000000 --- a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.repository; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.List; - -import javax.annotation.Resource; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.google.common.collect.Lists; - -/** - * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query - * by {@link org.springframework.data.jpa.domain.Specification} are also test. - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) -public class RepositoryTest { - - @Resource - private PersonRepository repository; - - Person peter = new Person("Peter", "Sagan", 17); - Person nasta = new Person("Nasta", "Kuzminova", 25); - Person john = new Person("John", "lawrence", 35); - Person terry = new Person("Terry", "Law", 36); - - List persons = Arrays.asList(peter, nasta, john, terry); - - /** - * Prepare data for test - */ - @Before - public void setup() { - - repository.save(persons); - } - - @Test - public void testFindAll() { - - List actuals = Lists.newArrayList(repository.findAll()); - assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals)); - } - - @Test - public void testSave() { - - Person terry = repository.findByName("Terry"); - terry.setSurname("Lee"); - terry.setAge(47); - repository.save(terry); - - terry = repository.findByName("Terry"); - assertEquals(terry.getSurname(), "Lee"); - assertEquals(47, terry.getAge()); - } - - @Test - public void testDelete() { - - Person terry = repository.findByName("Terry"); - repository.delete(terry); - - assertEquals(3, repository.count()); - assertNull(repository.findByName("Terry")); - } - - @Test - public void testCount() { - - assertEquals(4, repository.count()); - } - - @Test - public void testFindAllByAgeBetweenSpec() { - - List persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - - assertEquals(3, persons.size()); - assertTrue(persons.stream().allMatch((item) -> { - return item.getAge() > 20 && item.getAge() < 40; - })); - } - - @Test - public void testFindOneByNameEqualSpec() { - - Person actual = repository.findOne(new PersonSpecifications.NameEqualSpec("Terry")); - assertEquals(terry, actual); - } - - @After - public void cleanup() { - - repository.deleteAll(); - } - -} diff --git a/resource-acquisition-is-initialization/README.md b/resource-acquisition-is-initialization/README.md deleted file mode 100644 index df7ee294b211..000000000000 --- a/resource-acquisition-is-initialization/README.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: pattern -title: Resource Acquisition Is Initialization -folder: resource-acquisition-is-initialization -permalink: /patterns/resource-acquisition-is-initialization/ -pumlid: ZShR3S8m343HLUW0YV_PnhXMQvGumOzMOdhA1lqxkhgBABLSEQqzzeZfJm33isuIUxxIsMXei4QbqK5QdXXeyCO3oyekcvQ94MpgqD4lWB6FDEA2z4bn2HbQn8leHMponNy13hgvrhHUP_Rs0m00 -categories: Other -tags: - - Java - - Difficulty-Beginner - - Idiom ---- - -## Intent -Resource Acquisition Is Initialization pattern can be used to implement exception safe resource management. - -![alt text](./etc/resource-acquisition-is-initialization.png "Resource Acquisition Is Initialization") - -## Applicability -Use the Resource Acquisition Is Initialization pattern when - -* you have resources that must be closed in every condition diff --git a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.png b/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.png deleted file mode 100644 index 487b975690047c120c6938c974ebf5dd85f2cfba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3760 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 BJsSW3 diff --git a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.ucls b/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.ucls deleted file mode 100644 index 32fdb381cd91..000000000000 --- a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.ucls +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml b/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml deleted file mode 100644 index 11309f0a6230..000000000000 --- a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml +++ /dev/null @@ -1,19 +0,0 @@ -@startuml -package com.iluwatar.resource.acquisition.is.initialization { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class SlidingDoor { - - LOGGER : Logger {static} - + SlidingDoor() - + close() - } - class TreasureChest { - - LOGGER : Logger {static} - + TreasureChest() - + close() - } -} -@enduml \ No newline at end of file diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml deleted file mode 100644 index 7a6716d7b25f..000000000000 --- a/resource-acquisition-is-initialization/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - resource-acquisition-is-initialization - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 75d5dff27d41..000000000000 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * management by C++ creator Bjarne Stroustrup. - *

    - * In RAII resource is tied to object lifetime: resource allocation is done during object creation - * while resource deallocation is done during object destruction. - *

    - * In Java RAII is achieved with try-with-resources statement and interfaces {@link Closeable} and - * {@link AutoCloseable}. The try-with-resources statement ensures that each resource is closed at - * the end of the statement. Any object that implements {@link java.lang.AutoCloseable}, which - * includes all objects which implement {@link java.io.Closeable}, can be used as a resource. - * - * In this example, {@link SlidingDoor} implements {@link AutoCloseable} and {@link TreasureChest} - * implements {@link Closeable}. Running the example, we can observe that both resources are - * automatically closed. - *

    - * http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html - * - */ -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()) { - LOGGER.info("Walking in."); - } - - try (TreasureChest treasureChest = new TreasureChest()) { - 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 deleted file mode 100644 index b23c2df6d3df..000000000000 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.resource.acquisition.is.initialization; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * SlidingDoor resource - * - */ -public class SlidingDoor implements AutoCloseable { - - private static final Logger LOGGER = LoggerFactory.getLogger(SlidingDoor.class); - - public SlidingDoor() { - LOGGER.info("Sliding door opens."); - } - - @Override - public void close() throws Exception { - 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 deleted file mode 100644 index a2b7009a65ec..000000000000 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.resource.acquisition.is.initialization; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.IOException; - -/** - * - * TreasureChest resource - * - */ -public class TreasureChest implements Closeable { - - private static final Logger LOGGER = LoggerFactory.getLogger(TreasureChest.class); - - public TreasureChest() { - LOGGER.info("Treasure chest opens."); - } - - @Override - public void close() throws IOException { - LOGGER.info("Treasure chest closes."); - } -} diff --git a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/AppTest.java b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/AppTest.java deleted file mode 100644 index 1d7b4137ad44..000000000000 --- a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.resource.acquisition.is.initialization; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} 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 deleted file mode 100644 index 6786416fa84b..000000000000 --- a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.resource.acquisition.is.initialization; - -import static org.junit.Assert.assertTrue; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import java.util.LinkedList; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -/** - * Date: 12/28/15 - 9:31 PM - * - * @author Jeroen Meulemeester - */ -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 { - try (final SlidingDoor door = new SlidingDoor(); final TreasureChest chest = new TreasureChest()) { - assertTrue(appender.logContains("Sliding door opens.")); - assertTrue(appender.logContains("Treasure chest opens.")); - } - assertTrue(appender.logContains("Treasure chest closes.")); - assertTrue(appender.logContains("Sliding door closes.")); - } - - /** - * Logging Appender Implementation - */ - public class InMemoryAppender extends AppenderBase { - private List log = new LinkedList<>(); - - public InMemoryAppender() { - ((Logger) LoggerFactory.getLogger("root")).addAppender(this); - start(); - } - - @Override - protected void append(ILoggingEvent eventObject) { - log.add(eventObject); - } - - public boolean logContains(String message) { - return log.stream().anyMatch(event -> event.getMessage().equals(message)); - } - } - -} diff --git a/semaphore/README.md b/semaphore/README.md deleted file mode 100644 index 071e061a7c00..000000000000 --- a/semaphore/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: pattern -title: Semaphore -folder: semaphore -permalink: /patterns/semaphore/ -pumlid: HSV14SCm20J0Lk82BFxf1ikCfOn06ZZizfDVVhjRjphobFJnQi2ADv7pKwwEbaU6U9q6CPGwbVh8Xy5E7xvvFoNwPVjYGDo2bEC72b5URRgGeFvNqhMirF45 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate ---- - -## Also known as -Counting Semaphore - -## Intent -Create a lock which mediates access to a pool of resources. -Only a limited number of threads, specified at the creation -of the semaphore, can access the resources at any given time. -A semaphore which only allows one concurrent access to a resource -is called a binary semaphore. - -![alt text](./etc/semaphore.png "Semaphore") - -## Applicability -Use a Semaphore when - -* you have a pool of resources to allocate to different threads -* concurrent access to a resource could lead to a race condition - -## Credits - -* [Semaphore(programming)] (http://en.wikipedia.org/wiki/Semaphore_(programming)) -* [Semaphores] (http://tutorials.jenkov.com/java-concurrency/semaphores.html) diff --git a/semaphore/etc/semaphore.png b/semaphore/etc/semaphore.png deleted file mode 100644 index a2ff6d0c4f5bb931d724a4dd3872e7dde4730102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30089 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 diff --git a/semaphore/etc/semaphore.urm.puml b/semaphore/etc/semaphore.urm.puml deleted file mode 100644 index 168fd17e711a..000000000000 --- a/semaphore/etc/semaphore.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.semaphore { - class App { - + App() - + main(args : String[]) {static} - } - class Fruit { - - type : FruitType - + Fruit(type : FruitType) - + getType() : FruitType - + toString() : String - } - enum FruitType { - + APPLE {static} - + LEMON {static} - + ORANGE {static} - + valueOf(name : String) : FruitType {static} - + values() : FruitType[] {static} - } - class FruitBowl { - - fruit : List - + FruitBowl() - + countFruit() : int - + put(f : Fruit) - + take() : Fruit - + toString() : String - } - class FruitShop { - - available : boolean[] - - bowls : FruitBowl[] - - semaphore : Semaphore - + FruitShop() - + countFruit() : int - + returnBowl(bowl : FruitBowl) - + takeBowl() : FruitBowl - } - interface Lock { - + acquire() {abstract} - + release() {abstract} - } - class Semaphore { - - counter : int - - licenses : int - + Semaphore(licenses : int) - + acquire() - + getAvailableLicenses() : int - + getNumLicenses() : int - + release() - } -} -FruitType ..+ Fruit -Fruit --> "-type" FruitType -FruitShop --> "-semaphore" Semaphore -FruitBowl --> "-fruit" Fruit -Semaphore ..|> Lock -@enduml \ No newline at end of file diff --git a/semaphore/pom.xml b/semaphore/pom.xml deleted file mode 100644 index 4fa1733f4a47..000000000000 --- a/semaphore/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - semaphore - - - junit - junit - test - - - diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/App.java b/semaphore/src/main/java/com/iluwatar/semaphore/App.java deleted file mode 100644 index 90b96cc6f2da..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/App.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -/** - * A Semaphore mediates access by a group of threads to a pool of resources. - *

    - * In this example a group of customers are taking fruit from a fruit shop. - * There is a bowl each of apples, oranges and lemons. Only one customer can - * access a bowl simultaneously. A Semaphore is used to indicate how many - * resources are currently available and must be acquired in order for a bowl - * to be given to a customer. Customers continually try to take fruit until - * there is no fruit left in the shop. - */ -public class App { - - /** - * main method - */ - public static void main(String[] args) { - FruitShop shop = new FruitShop(); - new Customer("Peter", shop).start(); - new Customer("Paul", shop).start(); - new Customer("Mary", shop).start(); - new Customer("John", shop).start(); - new Customer("Ringo", shop).start(); - new Customer("George", shop).start(); - } - -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java deleted file mode 100644 index 9c480cb84521..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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. - */ - private final String name; - - /** - * The FruitShop he is using. - */ - private final FruitShop fruitShop; - - /** - * Their bowl of Fruit. - */ - private final FruitBowl fruitBowl; - - /** - * Customer constructor - */ - public Customer(String name, FruitShop fruitShop) { - this.name = name; - this.fruitShop = fruitShop; - this.fruitBowl = new FruitBowl(); - } - - /** - * The Customer repeatedly takes Fruit from the FruitShop until no Fruit - * remains. - */ - public void run() { - - while (fruitShop.countFruit() > 0) { - FruitBowl bowl = fruitShop.takeBowl(); - Fruit fruit; - - if (bowl != null && (fruit = bowl.take()) != null) { - LOGGER.info("{} took an {}", name, fruit); - fruitBowl.put(fruit); - fruitShop.returnBowl(bowl); - } - } - - LOGGER.info("{} took {}", name, fruitBowl); - - } - -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java b/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java deleted file mode 100644 index 88255997fa7e..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -/** - * Fruit is a resource stored in a FruitBowl. - */ -public class Fruit { - - /** - * Enumeration of Fruit Types - */ - public static enum FruitType { - ORANGE, APPLE, LEMON - } - - private FruitType type; - - public Fruit(FruitType type) { - this.type = type; - } - - public FruitType getType() { - return type; - } - - /** - * toString method - */ - public String toString() { - switch (type) { - case ORANGE: - return "Orange"; - case APPLE: - return "Apple"; - case LEMON: - return "Lemon"; - default: - return ""; - } - } - -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java deleted file mode 100644 index a53672109612..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -import java.util.List; -import java.util.ArrayList; - -/** - * A FruitBowl contains Fruit. - */ -public class FruitBowl { - - private List fruit = new ArrayList<>(); - - /** - * - * @return The amount of Fruit left in the bowl. - */ - public int countFruit() { - return fruit.size(); - } - - /** - * Put an item of Fruit into the bowl. - * - * @param f fruit - */ - public void put(Fruit f) { - fruit.add(f); - } - - /** - * Take an item of Fruit out of the bowl. - * @return The Fruit taken out of the bowl, or null if empty. - */ - public Fruit take() { - if (fruit.isEmpty()) { - return null; - } else { - return fruit.remove(0); - } - } - - /** - * toString method - */ - public String toString() { - int apples = 0; - int oranges = 0; - int lemons = 0; - - for (Fruit f : fruit) { - switch (f.getType()) { - case APPLE: - apples++; - break; - case ORANGE: - oranges++; - break; - case LEMON: - lemons++; - break; - default: - } - } - - return apples + " Apples, " + oranges + " Oranges, and " + lemons + " Lemons"; - } -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java deleted file mode 100644 index 63c1dfa54a42..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -/** - * A FruitShop contains three FruitBowl instances and controls access to them. - */ -public class FruitShop { - - /** - * The FruitBowl instances stored in the class. - */ - private FruitBowl[] bowls = { - new FruitBowl(), - new FruitBowl(), - new FruitBowl() - }; - - /** - * Access flags for each of the FruitBowl instances. - */ - private boolean[] available = { - true, - true, - true - }; - - /** - * The Semaphore that controls access to the class resources. - */ - private Semaphore semaphore; - - /** - * FruitShop constructor - */ - public FruitShop() { - for (int i = 0; i < 100; i++) { - bowls[0].put(new Fruit(Fruit.FruitType.APPLE)); - bowls[1].put(new Fruit(Fruit.FruitType.ORANGE)); - bowls[2].put(new Fruit(Fruit.FruitType.LEMON)); - } - - semaphore = new Semaphore(3); - } - - /** - * - * @return The amount of Fruit left in the shop. - */ - public synchronized int countFruit() { - return bowls[0].countFruit() + bowls[1].countFruit() + bowls[2].countFruit(); - } - - /** - * Method called by Customer to get a FruitBowl from the shop. This method - * will try to acquire the Semaphore before returning the first available - * FruitBowl. - */ - public synchronized FruitBowl takeBowl() { - - FruitBowl bowl = null; - - try { - semaphore.acquire(); - - if (available[0]) { - bowl = bowls[0]; - available[0] = false; - } else if (available[1]) { - bowl = bowls[1]; - available[1] = false; - } else if (available[2]) { - bowl = bowls[2]; - available[2] = false; - } - - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - semaphore.release(); - } - return bowl; - } - - /** - * Method called by a Customer instance to return a FruitBowl to the shop. - * This method releases the Semaphore, making the FruitBowl available to - * another Customer. - */ - public synchronized void returnBowl(FruitBowl bowl) { - if (bowl == bowls[0]) { - available[0] = true; - } else if (bowl == bowls[1]) { - available[1] = true; - } else if (bowl == bowls[2]) { - available [2] = true; - } - } - -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java b/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java deleted file mode 100644 index d4f5917542b5..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -/** - * Lock is an interface for a lock which can be acquired and released. - */ -public interface Lock { - - void acquire() throws InterruptedException; - - void release(); - -} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java deleted file mode 100644 index 01351ad9a4dc..000000000000 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -/** - * Semaphore is an implementation of a semaphore lock. - */ -public class Semaphore implements Lock { - - private final int licenses; - /** - * The number of concurrent resource accesses which are allowed. - */ - private int counter; - - public Semaphore(int licenses) { - this.licenses = licenses; - this.counter = licenses; - } - - /** - * Returns the number of licenses managed by the Semaphore - */ - public int getNumLicenses() { - return licenses; - } - - /** - * Returns the number of available licenses - */ - public int getAvailableLicenses() { - return counter; - } - - /** - * Method called by a thread to acquire the lock. If there are no resources - * available this will wait until the lock has been released to re-attempt - * the acquire. - */ - public synchronized void acquire() throws InterruptedException { - while (counter == 0) { - wait(); - } - counter = counter - 1; - } - - /** - * Method called by a thread to release the lock. - */ - public synchronized void release() { - if (counter < licenses) { - counter = counter + 1; - notify(); - } - } - -} diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java deleted file mode 100644 index 5eaed3b2eda6..000000000000 --- a/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -import org.junit.Test; -import java.io.IOException; - -/** - * Application Test Entrypoint - */ -public class AppTest { - @Test - public void test() throws IOException { - String[] args = {}; - App.main(args); - } -} diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java deleted file mode 100644 index 30a7dce44f53..000000000000 --- a/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * Test taking from and putting Fruit into a FruitBowl - */ -public class FruitBowlTest { - - @Test - public void fruitBowlTest() { - FruitBowl fbowl = new FruitBowl(); - - assertEquals(fbowl.countFruit(), 0); - - for (int i = 1; i <= 10; i++) { - fbowl.put(new Fruit(Fruit.FruitType.LEMON)); - assertEquals(fbowl.countFruit(), i); - } - - for (int i = 9; i >= 0; i--) { - assertNotNull(fbowl.take()); - assertEquals(fbowl.countFruit(), i); - } - - assertNull(fbowl.take()); - } -} diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java deleted file mode 100644 index b787a33014cd..000000000000 --- a/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.semaphore; - -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * Test case for acquiring and releasing a Semaphore - */ -public class SemaphoreTest { - - @Test - public void acquireReleaseTest() { - Semaphore sphore = new Semaphore(3); - - assertEquals(sphore.getAvailableLicenses(), 3); - - for (int i = 2; i >= 0; i--) { - try { - sphore.acquire(); - assertEquals(sphore.getAvailableLicenses(), i); - } catch (InterruptedException e) { - fail(e.toString()); - } - } - - for (int i = 1; i <= 3; i++) { - sphore.release(); - assertEquals(sphore.getAvailableLicenses(), i); - } - - sphore.release(); - assertEquals(sphore.getAvailableLicenses(), 3); - } -} diff --git a/servant/README.md b/servant/README.md deleted file mode 100644 index d14d35edfcd7..000000000000 --- a/servant/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Servant -folder: servant -permalink: /patterns/servant/ -pumlid: DSkn4O0m20NGLNG0G-ys63cDbv0SV7HzRUnUy-QYkSOkONKwWU4haV6JZe8pjd2nt1MYIBatAZKU1XjTVFEoYvT3by60c3erzW_qdPiL9CY_KrXB8rfz0G00 -categories: Structural -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Servant is used for providing some behavior to a group of classes. -Instead of defining that behavior in each class - or when we cannot factor out -this behavior in the common parent class - it is defined once in the Servant. - -![alt text](./etc/servant-pattern.png "Servant") - -## Applicability -Use the Servant pattern when - -* when we want some objects to perform a common action and don't want to define this action as a method in every class. - -## Credits -* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf) diff --git a/servant/etc/servant-pattern.png b/servant/etc/servant-pattern.png deleted file mode 100644 index a8237775e332609268debd3c61870d25d0de3424..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30103 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 Ze`JaFroT8T3jFGvyo`$U$Hy<<{y#X`r}O{- diff --git a/servant/etc/servant-pattern.ucls b/servant/etc/servant-pattern.ucls deleted file mode 100644 index 54e5ffc005d9..000000000000 --- a/servant/etc/servant-pattern.ucls +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/servant/etc/servant.urm.puml b/servant/etc/servant.urm.puml deleted file mode 100644 index 96dee04bce15..000000000000 --- a/servant/etc/servant.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.servant { - class App { - - LOGGER : Logger {static} - ~ jenkins : Servant {static} - ~ travis : Servant {static} - + App() - + main(args : String[]) {static} - + scenario(servant : Servant, compliment : int) {static} - } - class King { - - complimentReceived : boolean - - isDrunk : boolean - - isHappy : boolean - - isHungry : boolean - + King() - + changeMood() - + getDrink() - + getFed() - + getMood() : boolean - + receiveCompliments() - } - class Queen { - - complimentReceived : boolean - - isDrunk : boolean - - isFlirty : boolean - - isHappy : boolean - - isHungry : boolean - + Queen() - + changeMood() - + getDrink() - + getFed() - + getMood() : boolean - + receiveCompliments() - + setFlirtiness(f : boolean) - } - ~interface Royalty { - + changeMood() {abstract} - + getDrink() {abstract} - + getFed() {abstract} - + getMood() : boolean {abstract} - + receiveCompliments() {abstract} - } - class Servant { - + name : String - + Servant(name : String) - + checkIfYouWillBeHanged(tableGuests : List) : boolean - + feed(r : Royalty) - + giveCompliments(r : Royalty) - + giveWine(r : Royalty) - } -} -App --> "-jenkins" Servant -King ..|> Royalty -Queen ..|> Royalty -@enduml \ No newline at end of file diff --git a/servant/pom.xml b/servant/pom.xml deleted file mode 100644 index daa44d223d24..000000000000 --- a/servant/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - servant - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/servant/src/etc/servant.jpg b/servant/src/etc/servant.jpg deleted file mode 100644 index d7ea6626759f7967f99e73627baded2091f9559c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134957 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 T|DM_6|Fq8gcfKC|YxjQuV>iy( diff --git a/servant/src/etc/servant.svg b/servant/src/etc/servant.svg deleted file mode 100644 index c4891c79f35d..000000000000 --- a/servant/src/etc/servant.svg +++ /dev/null @@ -1,259 +0,0 @@ - - - - UML diagram java-design-patterns - - - - - - - - - - - - - - - - - App - (from iluwatar) - - - - - main(String[*]): void - - - - - scenario(Servant[0..1], Integer): void - - - - - - - King - (from iluwatar) - - - - isHappy: Boolean - - - - - complimentReceived: Boolean - - - - - - getFed(): void - - - - - getDrink(): void - - - - - receiveCompliments(): void - - - - - changeMood(): void - - - - - getMood(): Boolean - - - - - - - Queen - (from iluwatar) - - - - isHappy: Boolean - - - - - complimentReceived: Boolean - - - - - - getFed(): void - - - - - getDrink(): void - - - - - receiveCompliments(): void - - - - - changeMood(): void - - - - - getMood(): Boolean - - - - - setFlirtiness(Boolean): void - - - - - - - « Interface » - Royalty - (from iluwatar) - - - - getFed(): void - - - - - getDrink(): void - - - - - changeMood(): void - - - - - receiveCompliments(): void - - - - - getMood(): Boolean - - - - - - - Servant - (from iluwatar) - - - - name: String[0..1] - - - - - - Servant(String[0..1]): void - - - - - feed(Royalty[0..1]): void - - - - - giveWine(Royalty[0..1]): void - - - - - GiveCompliments(Royalty[0..1]): void - - - - - checkIfYouWillBeHanged(Royalty[*]): Boolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1..* - « use » - - - - diff --git a/servant/src/etc/servant.xml b/servant/src/etc/servant.xml deleted file mode 100644 index 06227a6b0a75..000000000000 --- a/servant/src/etc/servant.xml +++ /dev/null @@ -1,662 +0,0 @@ - - - - -

    - - - -
    - - - - - -
    - - - - - -
    - - - -
    - - - -
    - - - -
    - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - -
    - - - - -
    - - - - - -
    - - - - -
    - - - - -
    - - - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - -
    - - - - - - - -
    - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - - -
    - - - - - -
    - - - -
    - - - - -
    - - - - - - - - - -
    - - - - -
    - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - -
    - - - - -
    - - - - - - -
    - - - diff --git a/servant/src/main/java/com/iluwatar/servant/App.java b/servant/src/main/java/com/iluwatar/servant/App.java deleted file mode 100644 index 0e65e1de205f..000000000000 --- a/servant/src/main/java/com/iluwatar/servant/App.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Servant offers some functionality to a group of classes without defining that functionality in - * each of them. A Servant is a class whose instance provides methods that take care of a desired - * service, while objects for which the servant does something, are taken as parameters. - *

    - * In this example {@link Servant} is serving {@link King} and {@link Queen}. - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - static Servant jenkins = new Servant("Jenkins"); - static Servant travis = new Servant("Travis"); - - /** - * Program entry point - */ - public static void main(String[] args) { - scenario(jenkins, 1); - scenario(travis, 0); - } - - /** - * Can add a List with enum Actions for variable scenarios - */ - public static void scenario(Servant servant, int compliment) { - King k = new King(); - Queen q = new Queen(); - - List guests = new ArrayList<>(); - guests.add(k); - guests.add(q); - - // feed - servant.feed(k); - servant.feed(q); - // serve drinks - servant.giveWine(k); - servant.giveWine(q); - // compliment - servant.giveCompliments(guests.get(compliment)); - - // outcome of the night - for (Royalty r : guests) { - r.changeMood(); - } - - // check your luck - if (servant.checkIfYouWillBeHanged(guests)) { - LOGGER.info("{} will live another day", servant.name); - } else { - LOGGER.info("Poor {}. His days are numbered", servant.name); - } - } -} diff --git a/servant/src/main/java/com/iluwatar/servant/King.java b/servant/src/main/java/com/iluwatar/servant/King.java deleted file mode 100644 index 31b97184bb5e..000000000000 --- a/servant/src/main/java/com/iluwatar/servant/King.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -/** - * - * King - * - */ -public class King implements Royalty { - - private boolean isDrunk; - private boolean isHungry = true; - private boolean isHappy; - private boolean complimentReceived; - - @Override - public void getFed() { - isHungry = false; - } - - @Override - public void getDrink() { - isDrunk = true; - } - - public void receiveCompliments() { - complimentReceived = true; - } - - @Override - public void changeMood() { - if (!isHungry && isDrunk) { - isHappy = true; - } - if (complimentReceived) { - isHappy = false; - } - } - - @Override - public boolean getMood() { - return isHappy; - } -} diff --git a/servant/src/main/java/com/iluwatar/servant/Queen.java b/servant/src/main/java/com/iluwatar/servant/Queen.java deleted file mode 100644 index ad8ed1253d25..000000000000 --- a/servant/src/main/java/com/iluwatar/servant/Queen.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -/** - * - * Queen - * - */ -public class Queen implements Royalty { - - private boolean isDrunk = true; - private boolean isHungry; - private boolean isHappy; - private boolean isFlirty = true; - private boolean complimentReceived; - - @Override - public void getFed() { - isHungry = false; - } - - @Override - public void getDrink() { - isDrunk = true; - } - - public void receiveCompliments() { - complimentReceived = true; - } - - @Override - public void changeMood() { - if (complimentReceived && isFlirty && isDrunk && !isHungry) { - isHappy = true; - } - } - - @Override - public boolean getMood() { - return isHappy; - } - - public void setFlirtiness(boolean f) { - this.isFlirty = f; - } - -} diff --git a/servant/src/main/java/com/iluwatar/servant/Royalty.java b/servant/src/main/java/com/iluwatar/servant/Royalty.java deleted file mode 100644 index f60ccfed16e6..000000000000 --- a/servant/src/main/java/com/iluwatar/servant/Royalty.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -/** - * - * Royalty - * - */ -interface Royalty { - - void getFed(); - - void getDrink(); - - void changeMood(); - - void receiveCompliments(); - - boolean getMood(); -} diff --git a/servant/src/main/java/com/iluwatar/servant/Servant.java b/servant/src/main/java/com/iluwatar/servant/Servant.java deleted file mode 100644 index 2774f468e3c3..000000000000 --- a/servant/src/main/java/com/iluwatar/servant/Servant.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import java.util.List; - -/** - * - * Servant - * - */ -public class Servant { - - public String name; - - /** - * Constructor - */ - public Servant(String name) { - this.name = name; - } - - public void feed(Royalty r) { - r.getFed(); - } - - public void giveWine(Royalty r) { - r.getDrink(); - } - - public void giveCompliments(Royalty r) { - r.receiveCompliments(); - } - - /** - * Check if we will be hanged - */ - public boolean checkIfYouWillBeHanged(List tableGuests) { - boolean anotherDay = true; - for (Royalty r : tableGuests) { - if (!r.getMood()) { - anotherDay = false; - } - } - - return anotherDay; - } -} diff --git a/servant/src/test/java/com/iluwatar/servant/AppTest.java b/servant/src/test/java/com/iluwatar/servant/AppTest.java deleted file mode 100644 index 5b8908d80cbf..000000000000 --- a/servant/src/test/java/com/iluwatar/servant/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/servant/src/test/java/com/iluwatar/servant/KingTest.java b/servant/src/test/java/com/iluwatar/servant/KingTest.java deleted file mode 100644 index 3ebbaf28bb41..000000000000 --- a/servant/src/test/java/com/iluwatar/servant/KingTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Date: 12/28/15 - 9:40 PM - * - * @author Jeroen Meulemeester - */ -public class KingTest { - - @Test - public void testHungrySoberUncomplimentedKing() { - final King king = new King(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testFedSoberUncomplimentedKing() { - final King king = new King(); - king.getFed(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testHungryDrunkUncomplimentedKing() { - final King king = new King(); - king.getDrink(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testHungrySoberComplimentedKing() { - final King king = new King(); - king.receiveCompliments(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testFedDrunkUncomplimentedKing() { - final King king = new King(); - king.getFed(); - king.getDrink(); - king.changeMood(); - assertTrue(king.getMood()); - } - - @Test - public void testFedSoberComplimentedKing() { - final King king = new King(); - king.getFed(); - king.receiveCompliments(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testFedDrunkComplimentedKing() { - final King king = new King(); - king.getFed(); - king.getDrink(); - king.receiveCompliments(); - king.changeMood(); - assertFalse(king.getMood()); - } - - @Test - public void testHungryDrunkComplimentedKing() { - final King king = new King(); - king.getDrink(); - king.receiveCompliments(); - king.changeMood(); - assertFalse(king.getMood()); - } - -} \ No newline at end of file diff --git a/servant/src/test/java/com/iluwatar/servant/QueenTest.java b/servant/src/test/java/com/iluwatar/servant/QueenTest.java deleted file mode 100644 index d425886ba198..000000000000 --- a/servant/src/test/java/com/iluwatar/servant/QueenTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Date: 12/28/15 - 9:52 PM - * - * @author Jeroen Meulemeester - */ -public class QueenTest { - - @Test - public void testNotFlirtyUncomplemented() throws Exception { - final Queen queen = new Queen(); - queen.setFlirtiness(false); - queen.changeMood(); - assertFalse(queen.getMood()); - } - - @Test - public void testNotFlirtyComplemented() throws Exception { - final Queen queen = new Queen(); - queen.setFlirtiness(false); - queen.receiveCompliments(); - queen.changeMood(); - assertFalse(queen.getMood()); - } - - @Test - public void testFlirtyUncomplemented() throws Exception { - final Queen queen = new Queen(); - queen.changeMood(); - assertFalse(queen.getMood()); - } - - @Test - public void testFlirtyComplemented() throws Exception { - final Queen queen = new Queen(); - queen.receiveCompliments(); - queen.changeMood(); - assertTrue(queen.getMood()); - } - -} \ No newline at end of file diff --git a/servant/src/test/java/com/iluwatar/servant/ServantTest.java b/servant/src/test/java/com/iluwatar/servant/ServantTest.java deleted file mode 100644 index 900ccc4189be..000000000000 --- a/servant/src/test/java/com/iluwatar/servant/ServantTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servant; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -/** - * Date: 12/28/15 - 10:02 PM - * - * @author Jeroen Meulemeester - */ -public class ServantTest { - - @Test - public void testFeed() throws Exception { - final Royalty royalty = mock(Royalty.class); - final Servant servant = new Servant("test"); - servant.feed(royalty); - verify(royalty).getFed(); - verifyNoMoreInteractions(royalty); - } - - @Test - public void testGiveWine() throws Exception { - final Royalty royalty = mock(Royalty.class); - final Servant servant = new Servant("test"); - servant.giveWine(royalty); - verify(royalty).getDrink(); - verifyNoMoreInteractions(royalty); - } - - @Test - public void testGiveCompliments() throws Exception { - final Royalty royalty = mock(Royalty.class); - final Servant servant = new Servant("test"); - servant.giveCompliments(royalty); - verify(royalty).receiveCompliments(); - verifyNoMoreInteractions(royalty); - } - - @Test - public void testCheckIfYouWillBeHanged() throws Exception { - final Royalty goodMoodRoyalty = mock(Royalty.class); - when(goodMoodRoyalty.getMood()).thenReturn(true); - - final Royalty badMoodRoyalty = mock(Royalty.class); - when(badMoodRoyalty.getMood()).thenReturn(true); - - final List goodCompany = new ArrayList<>(); - goodCompany.add(goodMoodRoyalty); - goodCompany.add(goodMoodRoyalty); - goodCompany.add(goodMoodRoyalty); - - final List badCompany = new ArrayList<>(); - goodCompany.add(goodMoodRoyalty); - goodCompany.add(goodMoodRoyalty); - goodCompany.add(badMoodRoyalty); - - assertTrue(new Servant("test").checkIfYouWillBeHanged(goodCompany)); - assertTrue(new Servant("test").checkIfYouWillBeHanged(badCompany)); - - } - -} \ No newline at end of file diff --git a/service-layer/README.md b/service-layer/README.md deleted file mode 100644 index af393947f343..000000000000 --- a/service-layer/README.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: pattern -title: Service Layer -folder: service-layer -permalink: /patterns/service-layer/ -pumlid: LOl93SCm3C1MQGUmzUysgY8aAcJ5q96WszVV_aW2V8gHriRb-ZWoPxm07E--Inxrhc2dqv8jEvq3HEl6H8SFNjWs3jcjJSnaju21iG3MSmbnK_mkuwJ_qij7dpNq1m00 -categories: Architectural -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Service Layer is an abstraction over domain logic. Typically -applications require multiple kinds of interfaces to the data they store and -logic they implement: data loaders, user interfaces, integration gateways, and -others. Despite their different purposes, these interfaces often need common -interactions with the application to access and manipulate its data and invoke -its business logic. The Service Layer fulfills this role. - -![alt text](./etc/service-layer.png "Service Layer") - -## Applicability -Use the Service Layer pattern when - -* you want to encapsulate domain logic under API -* you need to implement multiple interfaces with common logic and data - -## Credits - -* [Martin Fowler - Service Layer](http://martinfowler.com/eaaCatalog/serviceLayer.html) -* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420) diff --git a/service-layer/bin/pom.xml b/service-layer/bin/pom.xml deleted file mode 100644 index 6eadbfa0c471..000000000000 --- a/service-layer/bin/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.0-SNAPSHOT - - dao - - - org.hibernate - hibernate-core - - - com.h2database - h2 - - - junit - junit - test - - - diff --git a/service-layer/etc/service-layer.png b/service-layer/etc/service-layer.png deleted file mode 100644 index 31d38361225f0c1a25949d8d4638bd18cf1c3972..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89966 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 diff --git a/service-layer/etc/service-layer.ucls b/service-layer/etc/service-layer.ucls deleted file mode 100644 index 979ae1204471..000000000000 --- a/service-layer/etc/service-layer.ucls +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/service-layer/etc/service-layer.urm.puml b/service-layer/etc/service-layer.urm.puml deleted file mode 100644 index 6cf9b938d2bb..000000000000 --- a/service-layer/etc/service-layer.urm.puml +++ /dev/null @@ -1,161 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.servicelayer.hibernate { - class HibernateUtil { - - LOGGER : Logger {static} - - sessionFactory : SessionFactory {static} - - HibernateUtil() - + dropSession() {static} - + getSessionFactory() : SessionFactory {static} - } -} -package com.iluwatar.servicelayer.common { - abstract class BaseEntity { - - version : Long - + BaseEntity() - + getId() : Long {abstract} - + getName() : String {abstract} - + setId(Long) {abstract} - + setName(String) {abstract} - } - interface Dao { - + delete(E extends BaseEntity) {abstract} - + find(Long) : E extends BaseEntity {abstract} - + findAll() : List {abstract} - + merge(E extends BaseEntity) : E extends BaseEntity {abstract} - + persist(E extends BaseEntity) {abstract} - } - abstract class DaoBaseImpl { - # persistentClass : Class - + DaoBaseImpl() - + delete(entity : E extends BaseEntity) - + find(id : Long) : E extends BaseEntity - + findAll() : List - # getSession() : Session - + merge(entity : E extends BaseEntity) : E extends BaseEntity - + persist(entity : E extends BaseEntity) - } -} -package com.iluwatar.servicelayer.magic { - interface MagicService { - + findAllSpellbooks() : List {abstract} - + findAllSpells() : List {abstract} - + findAllWizards() : List {abstract} - + findWizardsWithSpell(String) : List {abstract} - + findWizardsWithSpellbook(String) : List {abstract} - } - class MagicServiceImpl { - - spellDao : SpellDao - - spellbookDao : SpellbookDao - - wizardDao : WizardDao - + MagicServiceImpl(wizardDao : WizardDao, spellbookDao : SpellbookDao, spellDao : SpellDao) - + findAllSpellbooks() : List - + findAllSpells() : List - + findAllWizards() : List - + findWizardsWithSpell(name : String) : List - + findWizardsWithSpellbook(name : String) : List - } -} -package com.iluwatar.servicelayer.wizard { - class Wizard { - - id : Long - - name : String - - spellbooks : Set - + Wizard() - + Wizard(name : String) - + addSpellbook(spellbook : Spellbook) - + getId() : Long - + getName() : String - + getSpellbooks() : Set - + setId(id : Long) - + setName(name : String) - + setSpellbooks(spellbooks : Set) - + toString() : String - } - interface WizardDao { - + findByName(String) : Wizard {abstract} - } - class WizardDaoImpl { - + WizardDaoImpl() - + findByName(name : String) : Wizard - } -} -package com.iluwatar.servicelayer.spellbook { - class Spellbook { - - id : Long - - name : String - - spells : Set - - wizards : Set - + Spellbook() - + Spellbook(name : String) - + addSpell(spell : Spell) - + getId() : Long - + getName() : String - + getSpells() : Set - + getWizards() : Set - + setId(id : Long) - + setName(name : String) - + setSpells(spells : Set) - + setWizards(wizards : Set) - + toString() : String - } - interface SpellbookDao { - + findByName(String) : Spellbook {abstract} - } - class SpellbookDaoImpl { - + SpellbookDaoImpl() - + findByName(name : String) : Spellbook - } -} -package com.iluwatar.servicelayer.spell { - class Spell { - - id : Long - - name : String - - spellbook : Spellbook - + Spell() - + Spell(name : String) - + getId() : Long - + getName() : String - + getSpellbook() : Spellbook - + setId(id : Long) - + setName(name : String) - + setSpellbook(spellbook : Spellbook) - + toString() : String - } - interface SpellDao { - + findByName(String) : Spell {abstract} - } - class SpellDaoImpl { - + SpellDaoImpl() - + findByName(name : String) : Spell - } -} -package com.iluwatar.servicelayer.app { - class App { - - LOGGER : Logger {static} - + App() - + initData() {static} - + main(args : String[]) {static} - + queryData() {static} - } -} -MagicServiceImpl --> "-wizardDao" WizardDao -MagicServiceImpl --> "-spellbookDao" SpellbookDao -MagicServiceImpl --> "-spellDao" SpellDao -Spellbook --> "-spells" Spell -Spellbook --> "-wizards" Wizard -DaoBaseImpl ..|> Dao -MagicServiceImpl ..|> MagicService -Spell --|> BaseEntity -SpellDao --|> Dao -SpellDaoImpl ..|> SpellDao -SpellDaoImpl --|> DaoBaseImpl -Spellbook --|> BaseEntity -SpellbookDao --|> Dao -SpellbookDaoImpl ..|> SpellbookDao -SpellbookDaoImpl --|> DaoBaseImpl -Wizard --|> BaseEntity -WizardDao --|> Dao -WizardDaoImpl ..|> WizardDao -WizardDaoImpl --|> DaoBaseImpl -@enduml diff --git a/service-layer/pom.xml b/service-layer/pom.xml deleted file mode 100644 index 6edbeba442c8..000000000000 --- a/service-layer/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - service-layer - - - org.hibernate - hibernate-core - - - com.h2database - h2 - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 73dc1fe5c91f..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java +++ /dev/null @@ -1,210 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.app; - -import java.util.List; - -import com.iluwatar.servicelayer.magic.MagicService; -import com.iluwatar.servicelayer.magic.MagicServiceImpl; -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.spell.SpellDao; -import com.iluwatar.servicelayer.spell.SpellDaoImpl; -import com.iluwatar.servicelayer.spellbook.Spellbook; -import com.iluwatar.servicelayer.spellbook.SpellbookDao; -import com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl; -import com.iluwatar.servicelayer.wizard.Wizard; -import com.iluwatar.servicelayer.wizard.WizardDao; -import com.iluwatar.servicelayer.wizard.WizardDaoImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Service layer defines an application's boundary with a layer of services that establishes a set - * of available operations and coordinates the application's response in each operation. - *

    - * Enterprise applications typically require different kinds of interfaces to the data they store - * and the logic they implement: data loaders, user interfaces, integration gateways, and others. - * Despite their different purposes, these interfaces often need common interactions with the - * application to access and manipulate its data and invoke its business logic. The interactions may - * be complex, involving transactions across multiple resources and the coordination of several - * responses to an action. Encoding the logic of the interactions separately in each interface - * causes a lot of duplication. - *

    - * The example application demonstrates interactions between a client ({@link App}) and a service ( - * {@link MagicService}). The service is implemented with 3-layer architecture (entity, dao, - * service). For persistence the example uses in-memory H2 database which is populated on each - * application startup. - * - */ -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) { - // populate the in-memory database - initData(); - // query the data using the service - queryData(); - } - - /** - * Initialize data - */ - public static void initData() { - // spells - Spell spell1 = new Spell("Ice dart"); - Spell spell2 = new Spell("Invisibility"); - Spell spell3 = new Spell("Stun bolt"); - Spell spell4 = new Spell("Confusion"); - Spell spell5 = new Spell("Darkness"); - Spell spell6 = new Spell("Fireball"); - Spell spell7 = new Spell("Enchant weapon"); - Spell spell8 = new Spell("Rock armour"); - Spell spell9 = new Spell("Light"); - Spell spell10 = new Spell("Bee swarm"); - Spell spell11 = new Spell("Haste"); - Spell spell12 = new Spell("Levitation"); - Spell spell13 = new Spell("Magic lock"); - Spell spell14 = new Spell("Summon hell bat"); - Spell spell15 = new Spell("Water walking"); - Spell spell16 = new Spell("Magic storm"); - Spell spell17 = new Spell("Entangle"); - SpellDao spellDao = new SpellDaoImpl(); - spellDao.persist(spell1); - spellDao.persist(spell2); - spellDao.persist(spell3); - spellDao.persist(spell4); - spellDao.persist(spell5); - spellDao.persist(spell6); - spellDao.persist(spell7); - spellDao.persist(spell8); - spellDao.persist(spell9); - spellDao.persist(spell10); - spellDao.persist(spell11); - spellDao.persist(spell12); - spellDao.persist(spell13); - spellDao.persist(spell14); - spellDao.persist(spell15); - spellDao.persist(spell16); - spellDao.persist(spell17); - - // spellbooks - SpellbookDao spellbookDao = new SpellbookDaoImpl(); - Spellbook spellbook1 = new Spellbook("Book of Orgymon"); - spellbookDao.persist(spellbook1); - spellbook1.addSpell(spell1); - spellbook1.addSpell(spell2); - spellbook1.addSpell(spell3); - spellbook1.addSpell(spell4); - spellbookDao.merge(spellbook1); - Spellbook spellbook2 = new Spellbook("Book of Aras"); - spellbookDao.persist(spellbook2); - spellbook2.addSpell(spell5); - spellbook2.addSpell(spell6); - spellbookDao.merge(spellbook2); - Spellbook spellbook3 = new Spellbook("Book of Kritior"); - spellbookDao.persist(spellbook3); - spellbook3.addSpell(spell7); - spellbook3.addSpell(spell8); - spellbook3.addSpell(spell9); - spellbookDao.merge(spellbook3); - Spellbook spellbook4 = new Spellbook("Book of Tamaex"); - spellbookDao.persist(spellbook4); - spellbook4.addSpell(spell10); - spellbook4.addSpell(spell11); - spellbook4.addSpell(spell12); - spellbookDao.merge(spellbook4); - Spellbook spellbook5 = new Spellbook("Book of Idores"); - spellbookDao.persist(spellbook5); - spellbook5.addSpell(spell13); - spellbookDao.merge(spellbook5); - Spellbook spellbook6 = new Spellbook("Book of Opaen"); - spellbookDao.persist(spellbook6); - spellbook6.addSpell(spell14); - spellbook6.addSpell(spell15); - spellbookDao.merge(spellbook6); - Spellbook spellbook7 = new Spellbook("Book of Kihione"); - spellbookDao.persist(spellbook7); - spellbook7.addSpell(spell16); - spellbook7.addSpell(spell17); - spellbookDao.merge(spellbook7); - - // wizards - WizardDao wizardDao = new WizardDaoImpl(); - Wizard wizard1 = new Wizard("Aderlard Boud"); - wizardDao.persist(wizard1); - wizard1.addSpellbook(spellbookDao.findByName("Book of Orgymon")); - wizard1.addSpellbook(spellbookDao.findByName("Book of Aras")); - wizardDao.merge(wizard1); - Wizard wizard2 = new Wizard("Anaxis Bajraktari"); - wizardDao.persist(wizard2); - wizard2.addSpellbook(spellbookDao.findByName("Book of Kritior")); - wizard2.addSpellbook(spellbookDao.findByName("Book of Tamaex")); - wizardDao.merge(wizard2); - Wizard wizard3 = new Wizard("Xuban Munoa"); - wizardDao.persist(wizard3); - wizard3.addSpellbook(spellbookDao.findByName("Book of Idores")); - wizard3.addSpellbook(spellbookDao.findByName("Book of Opaen")); - wizardDao.merge(wizard3); - Wizard wizard4 = new Wizard("Blasius Dehooge"); - wizardDao.persist(wizard4); - wizard4.addSpellbook(spellbookDao.findByName("Book of Kihione")); - wizardDao.merge(wizard4); - } - - /** - * Query the data - */ - public static void queryData() { - MagicService service = - new MagicServiceImpl(new WizardDaoImpl(), new SpellbookDaoImpl(), new SpellDaoImpl()); - LOGGER.info("Enumerating all wizards"); - for (Wizard w : service.findAllWizards()) { - LOGGER.info(w.getName()); - } - LOGGER.info("Enumerating all spellbooks"); - for (Spellbook s : service.findAllSpellbooks()) { - LOGGER.info(s.getName()); - } - LOGGER.info("Enumerating all spells"); - for (Spell s : service.findAllSpells()) { - LOGGER.info(s.getName()); - } - LOGGER.info("Find wizards with spellbook 'Book of Idores'"); - List wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores"); - for (Wizard w : wizardsWithSpellbook) { - LOGGER.info("{} has 'Book of Idores'", w.getName()); - } - LOGGER.info("Find wizards with spell 'Fireball'"); - List wizardsWithSpell = service.findWizardsWithSpell("Fireball"); - for (Wizard w : wizardsWithSpell) { - LOGGER.info("{} has 'Fireball'", w.getName()); - } - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java b/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java deleted file mode 100644 index 52c24292e2ec..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.common; - -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.MappedSuperclass; -import javax.persistence.Version; - -/** - * - * Base class for entities. - * - */ -@MappedSuperclass -@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public abstract class BaseEntity { - - @Version - private Long version; - - /** - * Indicates the unique id of this entity - * - * @return The id of the entity, or 'null' when not persisted - */ - public abstract Long getId(); - - /** - * Set the id of this entity - * - * @param id The new id - */ - public abstract void setId(Long id); - - /** - * Get the name of this entity - * - * @return The name of the entity - */ - public abstract String getName(); - - /** - * Set the name of this entity - * - * @param name The new name - */ - public abstract void setName(final String name); - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/common/Dao.java b/service-layer/src/main/java/com/iluwatar/servicelayer/common/Dao.java deleted file mode 100644 index eee73b14bdd0..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/common/Dao.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.common; - -import java.util.List; - -/** - * - * Dao interface. - * - * @param - * - */ -public interface Dao { - - E find(Long id); - - void persist(E entity); - - E merge(E entity); - - void delete(E entity); - - List findAll(); -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java deleted file mode 100644 index 401c4170cc0c..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.common; - -import java.lang.reflect.ParameterizedType; -import java.util.List; - -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.Transaction; -import org.hibernate.criterion.Restrictions; - -import com.iluwatar.servicelayer.hibernate.HibernateUtil; - -/** - * - * Base class for Dao implementations. - * - * @param - * - */ -public abstract class DaoBaseImpl implements Dao { - - @SuppressWarnings("unchecked") - protected Class persistentClass = (Class) ((ParameterizedType) getClass() - .getGenericSuperclass()).getActualTypeArguments()[0]; - - /* - * Making this getSessionFactory() instead of getSession() so that it is the responsibility - * of the caller to open as well as close the session (prevents potential resource leak). - */ - protected SessionFactory getSessionFactory() { - return HibernateUtil.getSessionFactory(); - } - - @Override - public E find(Long id) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - E result = null; - try { - tx = session.beginTransaction(); - Criteria criteria = session.createCriteria(persistentClass); - criteria.add(Restrictions.idEq(id)); - result = (E) criteria.uniqueResult(); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } - - @Override - public void persist(E entity) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - try { - tx = session.beginTransaction(); - session.persist(entity); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - } - - @Override - public E merge(E entity) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - E result = null; - try { - tx = session.beginTransaction(); - result = (E) session.merge(entity); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } - - @Override - public void delete(E entity) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - try { - tx = session.beginTransaction(); - session.delete(entity); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - } - - @Override - public List findAll() { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - List result = null; - try { - tx = session.beginTransaction(); - Criteria criteria = session.createCriteria(persistentClass); - result = criteria.list(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } -} 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 deleted file mode 100644 index f83abf17c8ee..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.hibernate; - -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.spellbook.Spellbook; -import com.iluwatar.servicelayer.wizard.Wizard; - -import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Produces the Hibernate {@link SessionFactory}. - */ -public final class HibernateUtil { - - private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); - - /** - * The cached session factory - */ - private static volatile SessionFactory sessionFactory; - - private HibernateUtil() { - } - - /** - * Create the current session factory instance, create a new one when there is none yet. - * - * @return The session factory - */ - public static synchronized SessionFactory getSessionFactory() { - if (sessionFactory == null) { - try { - sessionFactory = - new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class) - .addAnnotatedClass(Spell.class) - .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect") - .setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1") - .setProperty("hibernate.current_session_context_class", "thread") - .setProperty("hibernate.show_sql", "false") - .setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory(); - } catch (Throwable ex) { - LOGGER.error("Initial SessionFactory creation failed.", ex); - throw new ExceptionInInitializerError(ex); - } - } - return sessionFactory; - } - - /** - * Drop the current connection, resulting in a create-drop clean database next time. This is - * mainly used for JUnit testing since one test should not influence the other - */ - public static void dropSession() { - getSessionFactory().close(); - sessionFactory = null; - } - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicService.java b/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicService.java deleted file mode 100644 index dcbab06966fe..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicService.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.magic; - -import java.util.List; - -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.spellbook.Spellbook; -import com.iluwatar.servicelayer.wizard.Wizard; - - -/** - * - * Service interface. - * - */ -public interface MagicService { - - List findAllWizards(); - - List findAllSpellbooks(); - - List findAllSpells(); - - List findWizardsWithSpellbook(String name); - - List findWizardsWithSpell(String name); -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java deleted file mode 100644 index 1e7ba9d56895..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.magic; - -import java.util.ArrayList; -import java.util.List; - -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.spell.SpellDao; -import com.iluwatar.servicelayer.spellbook.Spellbook; -import com.iluwatar.servicelayer.spellbook.SpellbookDao; -import com.iluwatar.servicelayer.wizard.Wizard; -import com.iluwatar.servicelayer.wizard.WizardDao; - -/** - * - * Service implementation. - * - */ -public class MagicServiceImpl implements MagicService { - - private WizardDao wizardDao; - private SpellbookDao spellbookDao; - private SpellDao spellDao; - - /** - * Constructor - */ - public MagicServiceImpl(WizardDao wizardDao, SpellbookDao spellbookDao, SpellDao spellDao) { - this.wizardDao = wizardDao; - this.spellbookDao = spellbookDao; - this.spellDao = spellDao; - } - - @Override - public List findAllWizards() { - return wizardDao.findAll(); - } - - @Override - public List findAllSpellbooks() { - return spellbookDao.findAll(); - } - - @Override - public List findAllSpells() { - return spellDao.findAll(); - } - - @Override - public List findWizardsWithSpellbook(String name) { - Spellbook spellbook = spellbookDao.findByName(name); - return new ArrayList<>(spellbook.getWizards()); - } - - @Override - public List findWizardsWithSpell(String name) { - Spell spell = spellDao.findByName(name); - Spellbook spellbook = spell.getSpellbook(); - return new ArrayList<>(spellbook.getWizards()); - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/Spell.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/Spell.java deleted file mode 100644 index 281128145e4b..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/Spell.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spell; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; - -import com.iluwatar.servicelayer.common.BaseEntity; -import com.iluwatar.servicelayer.spellbook.Spellbook; - -/** - * - * Spell entity. - * - */ -@Entity -@Table(name = "SPELL") -public class Spell extends BaseEntity { - - private String name; - - @Id - @GeneratedValue - @Column(name = "SPELL_ID") - private Long id; - - @ManyToOne - @JoinColumn(name = "SPELLBOOK_ID_FK", referencedColumnName = "SPELLBOOK_ID") - private Spellbook spellbook; - - public Spell() {} - - public Spell(String name) { - this(); - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Spellbook getSpellbook() { - return spellbook; - } - - public void setSpellbook(Spellbook spellbook) { - this.spellbook = spellbook; - } - - @Override - public String toString() { - return name; - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDao.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDao.java deleted file mode 100644 index 0c9ca6c0b0d5..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spell; - -import com.iluwatar.servicelayer.common.Dao; - -/** - * - * SpellDao interface. - * - */ -public interface SpellDao extends Dao { - - Spell findByName(String name); - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java deleted file mode 100644 index 81b3b6189576..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spell; - -import com.iluwatar.servicelayer.common.DaoBaseImpl; - -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.criterion.Restrictions; - -/** - * - * SpellDao implementation. - * - */ -public class SpellDaoImpl extends DaoBaseImpl implements SpellDao { - - @Override - public Spell findByName(String name) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - Spell result = null; - try { - tx = session.beginTransaction(); - Criteria criteria = session.createCriteria(persistentClass); - criteria.add(Restrictions.eq("name", name)); - result = (Spell) criteria.uniqueResult(); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java deleted file mode 100644 index 9a2cf89c3865..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spellbook; - -import java.util.HashSet; -import java.util.Set; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.OneToMany; -import javax.persistence.Table; - -import com.iluwatar.servicelayer.common.BaseEntity; -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.wizard.Wizard; - -/** - * - * Spellbook entity. - * - */ -@Entity -@Table(name = "SPELLBOOK") -public class Spellbook extends BaseEntity { - - @Id - @GeneratedValue - @Column(name = "SPELLBOOK_ID") - private Long id; - - private String name; - - @ManyToMany(mappedBy = "spellbooks", fetch = FetchType.EAGER) - private Set wizards; - - @OneToMany(mappedBy = "spellbook", orphanRemoval = true, cascade = CascadeType.ALL) - private Set spells; - - public Spellbook() { - spells = new HashSet<>(); - wizards = new HashSet<>(); - } - - public Spellbook(String name) { - this(); - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Set getWizards() { - return wizards; - } - - public void setWizards(Set wizards) { - this.wizards = wizards; - } - - public Set getSpells() { - return spells; - } - - public void setSpells(Set spells) { - this.spells = spells; - } - - public void addSpell(Spell spell) { - spell.setSpellbook(this); - spells.add(spell); - } - - @Override - public String toString() { - return name; - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDao.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDao.java deleted file mode 100644 index 05e208d54370..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spellbook; - -import com.iluwatar.servicelayer.common.Dao; - -/** - * - * SpellbookDao interface. - * - */ -public interface SpellbookDao extends Dao { - - Spellbook findByName(String name); - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java deleted file mode 100644 index c7131b843da7..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spellbook; - -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.criterion.Restrictions; - -import com.iluwatar.servicelayer.common.DaoBaseImpl; - -/** - * - * SpellbookDao implementation. - * - */ -public class SpellbookDaoImpl extends DaoBaseImpl implements SpellbookDao { - - @Override - public Spellbook findByName(String name) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - Spellbook result = null; - try { - tx = session.beginTransaction(); - Criteria criteria = session.createCriteria(persistentClass); - criteria.add(Restrictions.eq("name", name)); - result = (Spellbook) criteria.uniqueResult(); - result.getSpells().size(); - result.getWizards().size(); - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/Wizard.java b/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/Wizard.java deleted file mode 100644 index 00cdcc081b8b..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/Wizard.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.wizard; - -import java.util.HashSet; -import java.util.Set; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.Table; - -import com.iluwatar.servicelayer.common.BaseEntity; -import com.iluwatar.servicelayer.spellbook.Spellbook; - -/** - * - * Wizard entity. - * - */ -@Entity -@Table(name = "WIZARD") -public class Wizard extends BaseEntity { - - @Id - @GeneratedValue - @Column(name = "WIZARD_ID") - private Long id; - - private String name; - - @ManyToMany(cascade = CascadeType.ALL) - private Set spellbooks; - - public Wizard() { - spellbooks = new HashSet<>(); - } - - public Wizard(String name) { - this(); - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Set getSpellbooks() { - return spellbooks; - } - - public void setSpellbooks(Set spellbooks) { - this.spellbooks = spellbooks; - } - - public void addSpellbook(Spellbook spellbook) { - spellbook.getWizards().add(this); - spellbooks.add(spellbook); - } - - @Override - public String toString() { - return name; - } -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDao.java b/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDao.java deleted file mode 100644 index 320d1a54c779..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.wizard; - -import com.iluwatar.servicelayer.common.Dao; - -/** - * - * WizardDao interface. - * - */ -public interface WizardDao extends Dao { - - Wizard findByName(String name); - -} diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java deleted file mode 100644 index 0014bf921015..000000000000 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.wizard; - -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.criterion.Restrictions; - -import com.iluwatar.servicelayer.common.DaoBaseImpl; -import com.iluwatar.servicelayer.spellbook.Spellbook; - -/** - * - * WizardDao implementation. - * - */ -public class WizardDaoImpl extends DaoBaseImpl implements WizardDao { - - @Override - public Wizard findByName(String name) { - Session session = getSessionFactory().openSession(); - Transaction tx = null; - Wizard result = null; - try { - tx = session.beginTransaction(); - Criteria criteria = session.createCriteria(persistentClass); - criteria.add(Restrictions.eq("name", name)); - result = (Wizard) criteria.uniqueResult(); - for (Spellbook s : result.getSpellbooks()) { - s.getSpells().size(); - } - tx.commit(); - } catch (Exception e) { - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - session.close(); - } - return result; - } -} diff --git a/service-layer/src/main/resources/logback.xml b/service-layer/src/main/resources/logback.xml deleted file mode 100644 index b070def43c47..000000000000 --- a/service-layer/src/main/resources/logback.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - service-layer.log - - service-layer-%d.log - 5 - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - %-5p [%d{ISO8601,UTC}] %c: %m%n - - - - - - - - - - - - - - - - - - diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java deleted file mode 100644 index a667252a16e7..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.app; - -import com.iluwatar.servicelayer.hibernate.HibernateUtil; - -import org.junit.After; -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } - - @After - public void tearDown() throws Exception { - HibernateUtil.dropSession(); - } - -} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java deleted file mode 100644 index 694fc746db1c..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.common; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import com.iluwatar.servicelayer.hibernate.HibernateUtil; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Date: 12/28/15 - 10:53 PM - * Test for Base Data Access Objects - * @param Type of Base Entity - * @param Type of Dao Base Implementation - * @author Jeroen Meulemeester - */ -public abstract class BaseDaoTest> { - - /** - * The number of entities stored before each test - */ - private static final int INITIAL_COUNT = 5; - - /** - * The unique id generator, shared between all entities - */ - private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); - - /** - * Factory, used to create new entity instances with the given name - */ - private final Function factory; - - /** - * The tested data access object - */ - private final D dao; - - /** - * Create a new test using the given factory and dao - * - * @param factory The factory, used to create new entity instances with the given name - * @param dao The tested data access object - */ - public BaseDaoTest(final Function factory, final D dao) { - this.factory = factory; - this.dao = dao; - } - - @Before - public void setUp() throws Exception { - for (int i = 0; i < INITIAL_COUNT; i++) { - final String className = dao.persistentClass.getSimpleName(); - final String entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet()); - this.dao.persist(this.factory.apply(entityName)); - } - } - - @After - public void tearDown() throws Exception { - HibernateUtil.dropSession(); - } - - protected final D getDao() { - return this.dao; - } - - @Test - public void testFind() throws Exception { - final List all = this.dao.findAll(); - for (final E entity : all) { - final E byId = this.dao.find(entity.getId()); - assertNotNull(byId); - assertEquals(byId.getId(), byId.getId()); - } - } - - @Test - public void testDelete() throws Exception { - final List originalEntities = this.dao.findAll(); - this.dao.delete(originalEntities.get(1)); - this.dao.delete(originalEntities.get(2)); - - final List entitiesLeft = this.dao.findAll(); - assertNotNull(entitiesLeft); - assertEquals(INITIAL_COUNT - 2, entitiesLeft.size()); - } - - @Test - public void testFindAll() throws Exception { - final List all = this.dao.findAll(); - assertNotNull(all); - assertEquals(INITIAL_COUNT, all.size()); - } - - @Test - public void testSetId() throws Exception { - final E entity = this.factory.apply("name"); - assertNull(entity.getId()); - - final Long expectedId = Long.valueOf(1); - entity.setId(expectedId); - assertEquals(expectedId, entity.getId()); - } - - @Test - public void testSetName() throws Exception { - final E entity = this.factory.apply("name"); - assertEquals("name", entity.getName()); - assertEquals("name", entity.toString()); - - final String expectedName = "new name"; - entity.setName(expectedName); - assertEquals(expectedName, entity.getName()); - assertEquals(expectedName, entity.toString()); - } - -} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java deleted file mode 100644 index 05ad6f887900..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.magic; - -import com.iluwatar.servicelayer.spell.Spell; -import com.iluwatar.servicelayer.spell.SpellDao; -import com.iluwatar.servicelayer.spellbook.Spellbook; -import com.iluwatar.servicelayer.spellbook.SpellbookDao; -import com.iluwatar.servicelayer.wizard.Wizard; -import com.iluwatar.servicelayer.wizard.WizardDao; - -import org.junit.Test; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -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.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -/** - * Date: 12/29/15 - 12:06 AM - * - * @author Jeroen Meulemeester - */ -public class MagicServiceImplTest { - - @Test - public void testFindAllWizards() throws Exception { - final WizardDao wizardDao = mock(WizardDao.class); - final SpellbookDao spellbookDao = mock(SpellbookDao.class); - final SpellDao spellDao = mock(SpellDao.class); - - final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); - verifyZeroInteractions(wizardDao, spellbookDao, spellDao); - - service.findAllWizards(); - verify(wizardDao).findAll(); - verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); - } - - @Test - public void testFindAllSpellbooks() throws Exception { - final WizardDao wizardDao = mock(WizardDao.class); - final SpellbookDao spellbookDao = mock(SpellbookDao.class); - final SpellDao spellDao = mock(SpellDao.class); - - final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); - verifyZeroInteractions(wizardDao, spellbookDao, spellDao); - - service.findAllSpellbooks(); - verify(spellbookDao).findAll(); - verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); - } - - @Test - public void testFindAllSpells() throws Exception { - final WizardDao wizardDao = mock(WizardDao.class); - final SpellbookDao spellbookDao = mock(SpellbookDao.class); - final SpellDao spellDao = mock(SpellDao.class); - - final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); - verifyZeroInteractions(wizardDao, spellbookDao, spellDao); - - service.findAllSpells(); - verify(spellDao).findAll(); - verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); - } - - @Test - public void testFindWizardsWithSpellbook() throws Exception { - final String bookname = "bookname"; - final Spellbook spellbook = mock(Spellbook.class); - final Set wizards = new HashSet<>(); - wizards.add(mock(Wizard.class)); - wizards.add(mock(Wizard.class)); - wizards.add(mock(Wizard.class)); - - when(spellbook.getWizards()).thenReturn(wizards); - - final SpellbookDao spellbookDao = mock(SpellbookDao.class); - when(spellbookDao.findByName(eq(bookname))).thenReturn(spellbook); - - final WizardDao wizardDao = mock(WizardDao.class); - final SpellDao spellDao = mock(SpellDao.class); - - - final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); - verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); - - final List result = service.findWizardsWithSpellbook(bookname); - verify(spellbookDao).findByName(eq(bookname)); - verify(spellbook).getWizards(); - - assertNotNull(result); - assertEquals(3, result.size()); - - verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); - } - - @Test - public void testFindWizardsWithSpell() throws Exception { - final Set wizards = new HashSet<>(); - wizards.add(mock(Wizard.class)); - wizards.add(mock(Wizard.class)); - wizards.add(mock(Wizard.class)); - - final Spellbook spellbook = mock(Spellbook.class); - when(spellbook.getWizards()).thenReturn(wizards); - - final SpellbookDao spellbookDao = mock(SpellbookDao.class); - final WizardDao wizardDao = mock(WizardDao.class); - - final Spell spell = mock(Spell.class); - when(spell.getSpellbook()).thenReturn(spellbook); - - final String spellName = "spellname"; - final SpellDao spellDao = mock(SpellDao.class); - when(spellDao.findByName(eq(spellName))).thenReturn(spell); - - final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); - verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); - - final List result = service.findWizardsWithSpell(spellName); - verify(spellDao).findByName(eq(spellName)); - verify(spellbook).getWizards(); - - assertNotNull(result); - assertEquals(3, result.size()); - - verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); - } - -} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java deleted file mode 100644 index b6b4917c8ff9..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spell; - -import com.iluwatar.servicelayer.common.BaseDaoTest; - -import org.junit.Test; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/28/15 - 11:02 PM - * - * @author Jeroen Meulemeester - */ -public class SpellDaoImplTest extends BaseDaoTest { - - public SpellDaoImplTest() { - super(Spell::new, new SpellDaoImpl()); - } - - @Test - public void testFindByName() throws Exception { - final SpellDaoImpl dao = getDao(); - final List allSpells = dao.findAll(); - for (final Spell spell : allSpells) { - final Spell spellByName = dao.findByName(spell.getName()); - assertNotNull(spellByName); - assertEquals(spell.getId(), spellByName.getId()); - assertEquals(spell.getName(), spellByName.getName()); - } - } - -} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java deleted file mode 100644 index fb7eca15a773..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.spellbook; - -import com.iluwatar.servicelayer.common.BaseDaoTest; - -import org.junit.Test; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/28/15 - 11:44 PM - * - * @author Jeroen Meulemeester - */ -public class SpellbookDaoImplTest extends BaseDaoTest { - - public SpellbookDaoImplTest() { - super(Spellbook::new, new SpellbookDaoImpl()); - } - - @Test - public void testFindByName() throws Exception { - final SpellbookDaoImpl dao = getDao(); - final List allBooks = dao.findAll(); - for (final Spellbook book : allBooks) { - final Spellbook spellByName = dao.findByName(book.getName()); - assertNotNull(spellByName); - assertEquals(book.getId(), spellByName.getId()); - assertEquals(book.getName(), spellByName.getName()); - } - } - -} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java deleted file mode 100644 index 64bd72c7aa39..000000000000 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelayer.wizard; - -import com.iluwatar.servicelayer.common.BaseDaoTest; - -import org.junit.Test; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/28/15 - 11:46 PM - * - * @author Jeroen Meulemeester - */ -public class WizardDaoImplTest extends BaseDaoTest { - - public WizardDaoImplTest() { - super(Wizard::new, new WizardDaoImpl()); - } - - @Test - public void testFindByName() throws Exception { - final WizardDaoImpl dao = getDao(); - final List allWizards = dao.findAll(); - for (final Wizard spell : allWizards) { - final Wizard byName = dao.findByName(spell.getName()); - assertNotNull(byName); - assertEquals(spell.getId(), byName.getId()); - assertEquals(spell.getName(), byName.getName()); - } - } - -} diff --git a/service-locator/README.md b/service-locator/README.md deleted file mode 100644 index 479c9ed0f942..000000000000 --- a/service-locator/README.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -layout: pattern -title: Service Locator -folder: service-locator -permalink: /patterns/service-locator/ -pumlid: NSjB3iCm203HgxG7iDdtDeIWX0fZYqzo_MRTtUX9ynOZhPtBzNLchlW0EDxza3nhgs2dQScMdUO0qRenqU6B5xQTGmvh2pFPBM1WF07FSmbnqqcOqu6J_gsNZxvgw0y0 -categories: Structural -tags: - - Java - - Difficulty-Beginner - - Performance ---- - -## Intent -Encapsulate the processes involved in obtaining a service with a -strong abstraction layer. - -![alt text](./etc/service-locator.png "Service Locator") - -## Applicability -The service locator pattern is applicable whenever we want -to locate/fetch various services using JNDI which, typically, is a redundant -and expensive lookup. The service Locator pattern addresses this expensive -lookup by making use of caching techniques ie. for the very first time a -particular service is requested, the service Locator looks up in JNDI, fetched -the relevant service and then finally caches this service object. Now, further -lookups of the same service via Service Locator is done in its cache which -improves the performance of application to great extent. - -## Typical Use Case - -* when network hits are expensive and time consuming -* lookups of services are done quite frequently -* large number of services are being used - -## Consequences - -* Violates Interface Segregation Principle (ISP) by providing pattern consumers with an access -to a number of services that they don't potentially need. -* Creates hidden dependencies that can break the clients at runtime. - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) diff --git a/service-locator/etc/service-locator.png b/service-locator/etc/service-locator.png deleted file mode 100644 index d040da2abd3e148fbb568dfd583bde1f44822a7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16511 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/service-locator/etc/service-locator.urm.puml b/service-locator/etc/service-locator.urm.puml deleted file mode 100644 index 38fe7ea1b0d0..000000000000 --- a/service-locator/etc/service-locator.urm.puml +++ /dev/null @@ -1,41 +0,0 @@ -@startuml -package com.iluwatar.servicelocator { - class App { - + App() - + main(args : String[]) {static} - } - class InitContext { - - LOGGER : Logger {static} - + InitContext() - + lookup(serviceName : String) : Object - } - interface Service { - + execute() {abstract} - + getId() : int {abstract} - + getName() : String {abstract} - } - class ServiceCache { - - LOGGER : Logger {static} - - serviceCache : Map - + ServiceCache() - + addService(newService : Service) - + getService(serviceName : String) : Service - } - class ServiceImpl { - - LOGGER : Logger {static} - - id : int - - serviceName : String - + ServiceImpl(serviceName : String) - + execute() - + getId() : int - + getName() : String - } - class ServiceLocator { - - serviceCache : ServiceCache {static} - - ServiceLocator() - + getService(serviceJndiName : String) : Service {static} - } -} -ServiceLocator --> "-serviceCache" ServiceCache -ServiceImpl ..|> Service -@enduml \ No newline at end of file diff --git a/service-locator/pom.xml b/service-locator/pom.xml deleted file mode 100644 index 7cd4028ff951..000000000000 --- a/service-locator/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - service-locator - - - junit - junit - test - - - diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/App.java b/service-locator/src/main/java/com/iluwatar/servicelocator/App.java deleted file mode 100644 index 9a24d8280873..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/App.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -/** - * - * The Service Locator pattern is a design pattern used in software development to encapsulate the - * processes involved in obtaining a service with a strong abstraction layer. This pattern uses a - * central registry known as the "service locator", which on request returns the information - * necessary to perform a certain task. - *

    - * In this example we use the Service locator pattern to lookup JNDI-services and cache them for - * subsequent requests. - *

    - * - * @author saifasif - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - Service service = ServiceLocator.getService("jndi/serviceA"); - service.execute(); - service = ServiceLocator.getService("jndi/serviceB"); - service.execute(); - service = ServiceLocator.getService("jndi/serviceA"); - service.execute(); - service = ServiceLocator.getService("jndi/serviceA"); - service.execute(); - } -} diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java b/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java deleted file mode 100644 index c72c075d6eaa..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * - * @author saifasif - */ -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} - * - * @param serviceName a string - * @return an {@link Object} - */ - public Object lookup(String serviceName) { - if (serviceName.equals("jndi/serviceA")) { - LOGGER.info("Looking up service A and creating new service for A"); - return new ServiceImpl("jndi/serviceA"); - } else if (serviceName.equals("jndi/serviceB")) { - 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/Service.java b/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java deleted file mode 100644 index 006d98ba8e40..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -/** - * This is going to be the parent service interface which we will use to create our services. All - * services will have a

  • service name
  • unique id
  • execution work flow
  • - * - * @author saifasif - * - */ -public interface Service { - - /* - * The human readable name of the service - */ - String getName(); - - /* - * Unique ID of the particular service - */ - int getId(); - - /* - * The workflow method that defines what this service does - */ - void execute(); -} diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java deleted file mode 100644 index 72d5725e5768..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * The service cache implementation which will cache services that are being created. On first hit, - * the cache will be empty and thus any service that is being requested, will be created fresh and - * then placed into the cache map. On next hit, if same service name will be requested, it will be - * returned from the cache - * - * @author saifasif - */ -public class ServiceCache { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCache.class); - - private final Map serviceCache; - - public ServiceCache() { - serviceCache = new HashMap<>(); - } - - /** - * Get the service from the cache. null if no service is found matching the name - * - * @param serviceName a string - * @return {@link Service} - */ - public Service getService(String serviceName) { - Service cachedService = null; - for (String serviceJndiName : serviceCache.keySet()) { - if (serviceJndiName.equals(serviceName)) { - cachedService = serviceCache.get(serviceJndiName); - LOGGER.info("(cache call) Fetched service {}({}) from cache... !", - cachedService.getName(), cachedService.getId()); - } - } - return cachedService; - } - - /** - * Adds the service into the cache map - * - * @param newService a {@link Service} - */ - public void addService(Service newService) { - serviceCache.put(newService.getName(), newService); - } -} diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java deleted file mode 100644 index e48f4a5058c1..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * can be set in the web.xml deployment descriptor - * - * @author saifasif - */ -public class ServiceImpl implements Service { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceImpl.class); - - private final String serviceName; - private final int id; - - /** - * Constructor - */ - public ServiceImpl(String serviceName) { - // set the service name - this.serviceName = serviceName; - - // Generate a random id to this service object - this.id = (int) Math.floor(Math.random() * 1000) + 1; - } - - @Override - public String getName() { - return serviceName; - } - - @Override - public int getId() { - return id; - } - - @Override - public void execute() { - LOGGER.info("Service {} is now executing with id {}", getName(), getId()); - } -} diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java deleted file mode 100644 index 3e1b1a354094..000000000000 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -/** - * The service locator module. Will fetch service from cache, otherwise creates a fresh service and - * update cache - * - * @author saifasif - */ -public final class ServiceLocator { - - private static ServiceCache serviceCache = new ServiceCache(); - - private ServiceLocator() { - } - - /** - * Fetch the service with the name param from the cache first, if no service is found, lookup the - * service from the {@link InitContext} and then add the newly created service into the cache map - * for future requests. - * - * @param serviceJndiName a string - * @return {@link Service} - */ - public static Service getService(String serviceJndiName) { - Service serviceObj = serviceCache.getService(serviceJndiName); - if (serviceObj != null) { - return serviceObj; - } else { - /* - * If we are unable to retrive anything from cache, then lookup the service and add it in the - * cache map - */ - InitContext ctx = new InitContext(); - serviceObj = (Service) ctx.lookup(serviceJndiName); - if (serviceObj != null) { // Only cache a service if it actually exists - serviceCache.addService(serviceObj); - } - return serviceObj; - } - } -} diff --git a/service-locator/src/test/java/com/iluwatar/servicelocator/AppTest.java b/service-locator/src/test/java/com/iluwatar/servicelocator/AppTest.java deleted file mode 100644 index 1228898f2930..000000000000 --- a/service-locator/src/test/java/com/iluwatar/servicelocator/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java deleted file mode 100644 index 5dbbcdaf7fdb..000000000000 --- a/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.servicelocator; - -import org.junit.Test; - -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.assertTrue; - -/** - * Date: 12/29/15 - 19:07 PM - * - * @author Jeroen Meulemeester - */ -public class ServiceLocatorTest { - - /** - * Verify if we just receive 'null' when requesting a non-existing service - */ - @Test - public void testGetNonExistentService() { - assertNull(ServiceLocator.getService("fantastic/unicorn/service")); - assertNull(ServiceLocator.getService("another/fantastic/unicorn/service")); - } - - /** - * Verify if we get the same cached instance when requesting the same service twice - */ - @Test - public void testServiceCache() { - final String[] serviceNames = new String[]{ - "jndi/serviceA", "jndi/serviceB" - }; - - for (final String serviceName : serviceNames) { - final Service service = ServiceLocator.getService(serviceName); - assertNotNull(service); - assertEquals(serviceName, service.getName()); - assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1' - assertSame(service, ServiceLocator.getService(serviceName)); - } - - } - -} \ No newline at end of file diff --git a/specification/README.md b/specification/README.md deleted file mode 100644 index dc47f4970e4c..000000000000 --- a/specification/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: pattern -title: Specification -folder: specification -permalink: /patterns/specification/ -pumlid: LSX14i8m20NGg-W16lRU1YcsE0d9mCTUNxVkthoxkVJQjQBVJc3bWoZuQeVXh6UbXao7EfhCGTRhOd3Gcp-yxPfs-BOOqF2amVa3vLAnbmd3ffD2_gTLZBPgz2y0 -categories: Behavioral -tags: - - Java - - Difficulty-Beginner ---- - -## Also known as -Filter, Criteria - -## Intent -Specification pattern separates the statement of how to match a -candidate, from the candidate object that it is matched against. As well as its -usefulness in selection, it is also valuable for validation and for building to -order - -![alt text](./etc/specification.png "Specification") - -## Applicability -Use the Specification pattern when - -* you need to select a subset of objects based on some criteria, and to refresh the selection at various times -* you need to check that only suitable objects are used for a certain role (validation) - -## Related patterns - -* Repository - -## Credits - -* [Martin Fowler - Specifications](http://martinfowler.com/apsupp/spec.pdf) diff --git a/specification/etc/specification.png b/specification/etc/specification.png deleted file mode 100644 index 60fb0402d8d3fa8f087053ceb7ada7a931c70b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49425 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
    sHU$)a&qczB*R_nmVVqMAJlHBsO{Y;>{Ja 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/specification/etc/specification.urm.puml b/specification/etc/specification.urm.puml deleted file mode 100644 index fd3cbb20e5f2..000000000000 --- a/specification/etc/specification.urm.puml +++ /dev/null @@ -1,107 +0,0 @@ -@startuml -package com.iluwatar.specification.creature { - abstract class AbstractCreature { - - color : Color - - movement : Movement - - name : String - - size : Size - + AbstractCreature(name : String, size : Size, movement : Movement, color : Color) - + getColor() : Color - + getMovement() : Movement - + getName() : String - + getSize() : Size - + toString() : String - } - interface Creature { - + getColor() : Color {abstract} - + getMovement() : Movement {abstract} - + getName() : String {abstract} - + getSize() : Size {abstract} - } - class Dragon { - + Dragon() - } - class Goblin { - + Goblin() - } - class KillerBee { - + KillerBee() - } - class Octopus { - + Octopus() - } - class Shark { - + Shark() - } - class Troll { - + Troll() - } -} -package com.iluwatar.specification.property { - enum Color { - + DARK {static} - + GREEN {static} - + LIGHT {static} - + RED {static} - - title : String - + toString() : String - + valueOf(name : String) : Color {static} - + values() : Color[] {static} - } - enum Movement { - + FLYING {static} - + SWIMMING {static} - + WALKING {static} - - title : String - + toString() : String - + valueOf(name : String) : Movement {static} - + values() : Movement[] {static} - } - enum Size { - + LARGE {static} - + NORMAL {static} - + SMALL {static} - - title : String - + toString() : String - + valueOf(name : String) : Size {static} - + values() : Size[] {static} - } -} -package com.iluwatar.specification.selector { - class ColorSelector { - - c : Color - + ColorSelector(c : Color) - + test(t : Creature) : boolean - } - class MovementSelector { - - m : Movement - + MovementSelector(m : Movement) - + test(t : Creature) : boolean - } - class SizeSelector { - - s : Size - + SizeSelector(s : Size) - + test(t : Creature) : boolean - } -} -package com.iluwatar.specification.app { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -SizeSelector --> "-s" Size -AbstractCreature --> "-color" Color -MovementSelector --> "-m" Movement -AbstractCreature --> "-movement" Movement -AbstractCreature --> "-size" Size -ColorSelector --> "-c" Color -AbstractCreature ..|> Creature -Dragon --|> AbstractCreature -Goblin --|> AbstractCreature -KillerBee --|> AbstractCreature -Octopus --|> AbstractCreature -Shark --|> AbstractCreature -Troll --|> AbstractCreature -@enduml \ No newline at end of file diff --git a/specification/pom.xml b/specification/pom.xml deleted file mode 100644 index 76732b96450f..000000000000 --- a/specification/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - specification - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java deleted file mode 100644 index d4289f2d883f..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.app; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.creature.Dragon; -import com.iluwatar.specification.creature.Goblin; -import com.iluwatar.specification.creature.KillerBee; -import com.iluwatar.specification.creature.Octopus; -import com.iluwatar.specification.creature.Shark; -import com.iluwatar.specification.creature.Troll; -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.selector.ColorSelector; -import com.iluwatar.specification.selector.MovementSelector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The central idea of the Specification pattern is to separate the statement of how to match a - * candidate, from the candidate object that it is matched against. As well as its usefulness in - * selection, it is also valuable for validation and for building to order. - *

    - * In this example we have a pool of creatures with different properties. We then have defined - * separate selection rules (Specifications) that we apply to the collection and as output receive - * only the creatures that match the selection criteria. - *

    - * http://martinfowler.com/apsupp/spec.pdf - * - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Program entry point - */ - public static void main(String[] args) { - // initialize creatures list - List creatures = - Arrays.asList(new Goblin(), new Octopus(), new Dragon(), new Shark(), new Troll(), - new KillerBee()); - // 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(c -> LOGGER.info(c.toString())); - // 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(c -> LOGGER.info(c.toString())); - // find all red and flying creatures - LOGGER.info("Find all red and flying creatures"); - List redAndFlyingCreatures = - creatures.stream() - .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) - .collect(Collectors.toList()); - redAndFlyingCreatures.stream().forEach(c -> LOGGER.info(c.toString())); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java deleted file mode 100644 index f6c761ff4014..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Base class for concrete creatures. - * - */ -public abstract class AbstractCreature implements Creature { - - private String name; - private Size size; - private Movement movement; - private Color color; - - /** - * Constructor - */ - public AbstractCreature(String name, Size size, Movement movement, Color color) { - this.name = name; - this.size = size; - this.movement = movement; - this.color = color; - } - - @Override - public String toString() { - return String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color); - } - - @Override - public String getName() { - return name; - } - - @Override - public Size getSize() { - return size; - } - - @Override - public Movement getMovement() { - return movement; - } - - @Override - public Color getColor() { - return color; - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java b/specification/src/main/java/com/iluwatar/specification/creature/Creature.java deleted file mode 100644 index eae47df6fced..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Creature interface. - * - */ -public interface Creature { - - String getName(); - - Size getSize(); - - Movement getMovement(); - - Color getColor(); -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java b/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java deleted file mode 100644 index 7f2f0cc51b7a..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Dragon creature. - * - */ -public class Dragon extends AbstractCreature { - - public Dragon() { - super("Dragon", Size.LARGE, Movement.FLYING, Color.RED); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java b/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java deleted file mode 100644 index 21c958a77aee..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Goblin creature. - * - */ -public class Goblin extends AbstractCreature { - - public Goblin() { - super("Goblin", Size.SMALL, Movement.WALKING, Color.GREEN); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java b/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java deleted file mode 100644 index e9e3ff34da87..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * KillerBee creature. - * - */ -public class KillerBee extends AbstractCreature { - - public KillerBee() { - super("KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java b/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java deleted file mode 100644 index 4cee924dc40b..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Octopus creature. - * - */ -public class Octopus extends AbstractCreature { - - public Octopus() { - super("Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java b/specification/src/main/java/com/iluwatar/specification/creature/Shark.java deleted file mode 100644 index c325ef646f61..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Shark creature. - * - */ -public class Shark extends AbstractCreature { - - public Shark() { - super("Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java b/specification/src/main/java/com/iluwatar/specification/creature/Troll.java deleted file mode 100644 index 676049e2484a..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -/** - * - * Troll creature. - * - */ -public class Troll extends AbstractCreature { - - public Troll() { - super("Troll", Size.LARGE, Movement.WALKING, Color.DARK); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/property/Color.java b/specification/src/main/java/com/iluwatar/specification/property/Color.java deleted file mode 100644 index d34fbdb43fc7..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/property/Color.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.property; - -/** - * - * Color property. - * - */ -public enum Color { - - DARK("dark"), LIGHT("light"), GREEN("green"), RED("red"); - - private String title; - - Color(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/property/Movement.java b/specification/src/main/java/com/iluwatar/specification/property/Movement.java deleted file mode 100644 index bafd6e358ec7..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/property/Movement.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.property; - -/** - * - * Movement property. - * - */ -public enum Movement { - - WALKING("walking"), SWIMMING("swimming"), FLYING("flying"); - - private String title; - - Movement(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/property/Size.java b/specification/src/main/java/com/iluwatar/specification/property/Size.java deleted file mode 100644 index 43aa8156b029..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/property/Size.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.property; - -/** - * - * Size property. - * - */ -public enum Size { - - SMALL("small"), NORMAL("normal"), LARGE("large"); - - private String title; - - Size(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java deleted file mode 100644 index 212e46b63637..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import java.util.function.Predicate; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Color; - -/** - * - * Color selector. - * - */ -public class ColorSelector implements Predicate { - - private final Color c; - - public ColorSelector(Color c) { - this.c = c; - } - - @Override - public boolean test(Creature t) { - return t.getColor().equals(c); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java deleted file mode 100644 index 8f07ff1dae57..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import java.util.function.Predicate; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Movement; - -/** - * - * Movement selector. - * - */ -public class MovementSelector implements Predicate { - - private final Movement m; - - public MovementSelector(Movement m) { - this.m = m; - } - - @Override - public boolean test(Creature t) { - return t.getMovement().equals(m); - } -} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java deleted file mode 100644 index ce12d709a526..000000000000 --- a/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import java.util.function.Predicate; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Size; - -/** - * - * Size selector. - * - */ -public class SizeSelector implements Predicate { - - private final Size s; - - public SizeSelector(Size s) { - this.s = s; - } - - @Override - public boolean test(Creature t) { - return t.getSize().equals(s); - } -} diff --git a/specification/src/test/java/com/iluwatar/specification/app/AppTest.java b/specification/src/test/java/com/iluwatar/specification/app/AppTest.java deleted file mode 100644 index a11101670681..000000000000 --- a/specification/src/test/java/com/iluwatar/specification/app/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.app; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java deleted file mode 100644 index 1c969891b15c..000000000000 --- a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.creature; - -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; -import com.iluwatar.specification.property.Size; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/29/15 - 7:47 PM - * - * @author Jeroen Meulemeester - */ -@RunWith(Parameterized.class) -public class CreatureTest { - - /** - * @return The tested {@link Creature} instance and its expected specs - */ - @Parameterized.Parameters - public static Collection data() { - return Arrays.asList( - new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED}, - new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN}, - new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT}, - new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK}, - new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT}, - new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK} - ); - } - - /** - * The tested creature - */ - private final Creature testedCreature; - - /** - * The expected name of the tested creature - */ - private final String name; - - /** - * The expected size of the tested creature - */ - private final Size size; - - /** - * The expected movement type of the tested creature - */ - private final Movement movement; - - /** - * The expected color of the tested creature - */ - private final Color color; - - /** - * @param testedCreature The tested creature - * @param name The expected name of the creature - * @param size The expected size of the creature - * @param movement The expected movement type of the creature - * @param color The expected color of the creature - */ - public CreatureTest(final Creature testedCreature, final String name, final Size size, - final Movement movement, final Color color) { - this.testedCreature = testedCreature; - this.name = name; - this.size = size; - this.movement = movement; - this.color = color; - } - - - @Test - public void testGetName() throws Exception { - assertEquals(this.name, this.testedCreature.getName()); - } - - @Test - public void testGetSize() throws Exception { - assertEquals(this.size, this.testedCreature.getSize()); - } - - @Test - public void testGetMovement() throws Exception { - assertEquals(this.movement, this.testedCreature.getMovement()); - } - - @Test - public void testGetColor() throws Exception { - assertEquals(this.color, this.testedCreature.getColor()); - } - - @Test - public void testToString() throws Exception { - final String toString = this.testedCreature.toString(); - assertNotNull(toString); - assertEquals( - String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color), - toString - ); - } -} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java deleted file mode 100644 index 52b176915a8a..000000000000 --- a/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Color; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Date: 12/29/15 - 7:35 PM - * - * @author Jeroen Meulemeester - */ -public class ColorSelectorTest { - - /** - * Verify if the color selector gives the correct results - */ - @Test - public void testColor() { - final Creature greenCreature = mock(Creature.class); - when(greenCreature.getColor()).thenReturn(Color.GREEN); - - final Creature redCreature = mock(Creature.class); - when(redCreature.getColor()).thenReturn(Color.RED); - - final ColorSelector greenSelector = new ColorSelector(Color.GREEN); - assertTrue(greenSelector.test(greenCreature)); - assertFalse(greenSelector.test(redCreature)); - - } - -} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java deleted file mode 100644 index b9e86193eb55..000000000000 --- a/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Movement; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Date: 12/29/15 - 7:37 PM - * - * @author Jeroen Meulemeester - */ -public class MovementSelectorTest { - - /** - * Verify if the movement selector gives the correct results - */ - @Test - public void testMovement() { - final Creature swimmingCreature = mock(Creature.class); - when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING); - - final Creature flyingCreature = mock(Creature.class); - when(flyingCreature.getMovement()).thenReturn(Movement.FLYING); - - final MovementSelector swimmingSelector = new MovementSelector(Movement.SWIMMING); - assertTrue(swimmingSelector.test(swimmingCreature)); - assertFalse(swimmingSelector.test(flyingCreature)); - - } - -} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java deleted file mode 100644 index f2b6b80b7e45..000000000000 --- a/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.specification.selector; - -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Size; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Date: 12/29/15 - 7:43 PM - * - * @author Jeroen Meulemeester - */ -public class SizeSelectorTest { - - /** - * Verify if the size selector gives the correct results - */ - @Test - public void testMovement() { - final Creature normalCreature = mock(Creature.class); - when(normalCreature.getSize()).thenReturn(Size.NORMAL); - - final Creature smallCreature = mock(Creature.class); - when(smallCreature.getSize()).thenReturn(Size.SMALL); - - final SizeSelector normalSelector = new SizeSelector(Size.NORMAL); - assertTrue(normalSelector.test(normalCreature)); - assertFalse(normalSelector.test(smallCreature)); - } - -} diff --git a/state/README.md b/state/README.md deleted file mode 100644 index 34ad8074c5fe..000000000000 --- a/state/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: pattern -title: State -folder: state -permalink: /patterns/state/ -pumlid: 9SRH3O0m20N0LNG0ox_RO2LQqz867hg-9jxNpKLpZLt2wdG2mrSYuoST1MTiuMAvAqIHSczKQZmCDhhuvcKNBuSkWm4nTMhiNyZ141BaVocifH6jlW00 -categories: Behavioral -tags: - - Java - - Difficulty-Intermediate - - Gang Of Four ---- - -## Also known as -Objects for States - -## Intent -Allow an object to alter its behavior when its internal state -changes. The object will appear to change its class. - -![alt text](./etc/state_1.png "State") - -## Applicability -Use the State pattern in either of the following cases - -* an object's behavior depends on its state, and it must change its behavior at run-time depending on that state -* operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects. - -## Real world examples - -* [javax.faces.lifecycle.Lifecycle#execute()](http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-) controlled by [FacesServlet](http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html), the behavior is dependent on current phase of lifecycle. -* [JDiameter - Diameter State Machine](https://github.com/npathai/jdiameter/blob/master/core/jdiameter/api/src/main/java/org/jdiameter/api/app/State.java) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/state/etc/state.png b/state/etc/state.png deleted file mode 100644 index fb1648238e78e123a3e2f60540ae7701dd45ee8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17753 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 diff --git a/state/etc/state.ucls b/state/etc/state.ucls deleted file mode 100644 index e0be8d7127e6..000000000000 --- a/state/etc/state.ucls +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/state/etc/state.urm.puml b/state/etc/state.urm.puml deleted file mode 100644 index 207a227d83d7..000000000000 --- a/state/etc/state.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.state { - class AngryState { - - LOGGER : Logger {static} - - mammoth : Mammoth - + AngryState(mammoth : Mammoth) - + observe() - + onEnterState() - } - class App { - + App() - + main(args : String[]) {static} - } - class Mammoth { - - state : State - + Mammoth() - - changeStateTo(newState : State) - + observe() - + timePasses() - + toString() : String - } - class PeacefulState { - - LOGGER : Logger {static} - - mammoth : Mammoth - + PeacefulState(mammoth : Mammoth) - + observe() - + onEnterState() - } - interface State { - + observe() {abstract} - + onEnterState() {abstract} - } -} -PeacefulState --> "-mammoth" Mammoth -AngryState --> "-mammoth" Mammoth -Mammoth --> "-state" State -AngryState ..|> State -PeacefulState ..|> State -@enduml \ No newline at end of file diff --git a/state/etc/state_1.png b/state/etc/state_1.png deleted file mode 100644 index 112bb9aff904f93f769583ab2a33d3f7b2181a9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33886 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

    iUE7!eElOdtCT0kf!Fdl4hr*FaKHszv z_E7y^bDF@q{QY1e$3$R;kVg{O-YW_K9~njI!6 zyTjyeea6ZbUD&iZDs+;rfAqyh#7mDauU>uJ-SP`1nkz8Epf=#hhfxQ4g4gooTH)-(?f2d8iS>|4iORpRjlB#BvE0%3kZCm{j}W*&%v$F2*_}gL zQ+{Y~(l7j#c`a`{vvSyF$(^*Oj14ju>&pC@nVUXPdPY&bpQDv}Hjt9{?boEGOP6fK zC8|rye|m3`MB`A7GRgRU@|gIkpvTSG;(=06N$?Ii2A> zC`lS=Zz4OuCS+1jF=fwNUl$i9Dt>LJ)gfo^>}&#M$+XYpIl)h##^V!n_Hxcv@bh;m zzt$SvpLUFka{s7VU& z%>k>C=2do`d9$=47BlVd8Fp17vYj@(&x$V#`nnG-o_&c9k^Py6x~+lSx#!_c(61k z4sl59xi|N3jXrbEG$)+1>`e9@AOBh7K+O03fEj^ZW0L{x_ZcJ1{+Zo4ivXi$&L9S3 zhSe{hsbu)`Bj;=CvOfCwX zDC`-!vjrY2=0_7QqmD^PRCCZGAwmDB&4PUUK)8~Jle49NePdyvS&kT%4JqSD9JLY^ zRHCb^b*ZW~JYCmz!&li<0F`gu&LFvY@}<|o*S3|!GilYfz3ehFPY%bkzh6;{(#OLE zfiEUVlyzt{o(WGltvw2?TiZJ)#Ez7X7OpI~X44w30hMVBs}GSR7%|6%-W!x0*d3LL zp5^i@y(T(`sP+AMLqhL;&M=sf^PX|4zKrsq9I+}JO5#u;tdy%$JiVZ9o)esx=kz<9 zROAr9O|+Ar&8!6b$k0fVi^IWm2hyaI^r^9ONH|OR(&TBuUwNkewhU7G!Rp3f1)Z4V zMRKo$pIg88P|uyMa=!&-_boxI_To!#45_JY#hwH{Q}vB4YTD!;Ikogt$KkHDdheyF z(TOJ(E88na^nGW#m|4osU*DIZq{*_zjT-rrFJ6BYEdR2wgzq67O$b@KiYE=t4A>U8 zTKRvXHM=Wzc3)wIaxaD5CmGnNHl;j`^@acM1oSWe^w-4~=}^6E@ezVV1w2?gcTKE) zxMD(5ymG)Xjf(Sv#`EJC|Dpi!H_W)0S-*C91im&EHW)4KhEvO~k5)e{D^mdT@V$1+ z-D@|3po`lvJFqS#C9GpIO~I;%ohTt6KF}DTo%=TZkD}q9+)fr(#eZu*t*E&QB z)7@D;Fv%h!ao69Y;DAzhrE^P8a9_I>bsDY#Oeyf31(5C4Z>Mat>U zj#OPrJ4X#0$n8^N+xHDRiAoy~B|LK`?FH!8C~OizfK#ZNV9R`k9}b`_I*eT%NfcV2 z-R0Q*Z~(`WrM)Q^UK8QrxRmTdhQigs$HruMPG-Fa|Gpr(V7Th{e}AvojC`H>|D6NC zxqm0`kwgUyN#gaKL73v;;Edp+aB*<58KGtk|Csc{)g67jO({gV2>--Ul2^a{Sk5%y Fe*vgP8^izr diff --git a/state/pom.xml b/state/pom.xml deleted file mode 100644 index 256a5e9e2740..000000000000 --- a/state/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - state - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/state/src/main/java/com/iluwatar/state/AngryState.java b/state/src/main/java/com/iluwatar/state/AngryState.java deleted file mode 100644 index 31401364e614..000000000000 --- a/state/src/main/java/com/iluwatar/state/AngryState.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Angry state. - * - */ -public class AngryState implements State { - - private static final Logger LOGGER = LoggerFactory.getLogger(AngryState.class); - - private Mammoth mammoth; - - public AngryState(Mammoth mammoth) { - this.mammoth = mammoth; - } - - @Override - public void observe() { - LOGGER.info("{} is furious!", mammoth); - } - - @Override - public void onEnterState() { - LOGGER.info("{} gets angry!", mammoth); - } - -} diff --git a/state/src/main/java/com/iluwatar/state/App.java b/state/src/main/java/com/iluwatar/state/App.java deleted file mode 100644 index cb717cbd311e..000000000000 --- a/state/src/main/java/com/iluwatar/state/App.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -/** - * - * In State pattern the container object has an internal state object that defines the current - * behavior. The state object can be changed to alter the behavior. - *

    - * This can be a cleaner way for an object to change its behavior at runtime without resorting to - * large monolithic conditional statements and thus improves maintainability. - *

    - * In this example the {@link Mammoth} changes its behavior as time passes by. - * - */ -public class App { - - /** - * Program entry point - */ - public static void main(String[] args) { - - Mammoth mammoth = new Mammoth(); - mammoth.observe(); - mammoth.timePasses(); - mammoth.observe(); - mammoth.timePasses(); - mammoth.observe(); - - } -} diff --git a/state/src/main/java/com/iluwatar/state/Mammoth.java b/state/src/main/java/com/iluwatar/state/Mammoth.java deleted file mode 100644 index 5d4153f06355..000000000000 --- a/state/src/main/java/com/iluwatar/state/Mammoth.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -/** - * - * Mammoth has internal state that defines its behavior. - * - */ -public class Mammoth { - - private State state; - - public Mammoth() { - state = new PeacefulState(this); - } - - /** - * Makes time pass for the mammoth - */ - public void timePasses() { - if (state.getClass().equals(PeacefulState.class)) { - changeStateTo(new AngryState(this)); - } else { - changeStateTo(new PeacefulState(this)); - } - } - - private void changeStateTo(State newState) { - this.state = newState; - this.state.onEnterState(); - } - - @Override - public String toString() { - return "The mammoth"; - } - - public void observe() { - this.state.observe(); - } -} diff --git a/state/src/main/java/com/iluwatar/state/PeacefulState.java b/state/src/main/java/com/iluwatar/state/PeacefulState.java deleted file mode 100644 index 2b7f4dda87d3..000000000000 --- a/state/src/main/java/com/iluwatar/state/PeacefulState.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Peaceful state. - * - */ -public class PeacefulState implements State { - - private static final Logger LOGGER = LoggerFactory.getLogger(PeacefulState.class); - - private Mammoth mammoth; - - public PeacefulState(Mammoth mammoth) { - this.mammoth = mammoth; - } - - @Override - public void observe() { - LOGGER.info("{} is calm and peaceful.", mammoth); - } - - @Override - public void onEnterState() { - LOGGER.info("{} calms down.", mammoth); - } - -} diff --git a/state/src/main/java/com/iluwatar/state/State.java b/state/src/main/java/com/iluwatar/state/State.java deleted file mode 100644 index 523925d28ce0..000000000000 --- a/state/src/main/java/com/iluwatar/state/State.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -/** - * - * State interface. - * - */ -public interface State { - - void onEnterState(); - - void observe(); - -} diff --git a/state/src/test/java/com/iluwatar/state/AppTest.java b/state/src/test/java/com/iluwatar/state/AppTest.java deleted file mode 100644 index cb40d04813a4..000000000000 --- a/state/src/test/java/com/iluwatar/state/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.state; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/state/src/test/java/com/iluwatar/state/MammothTest.java b/state/src/test/java/com/iluwatar/state/MammothTest.java deleted file mode 100644 index 60f4b18f47f4..000000000000 --- a/state/src/test/java/com/iluwatar/state/MammothTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Date: 12/29/15 - 8:27 PM - * - * @author Jeroen Meulemeester - */ -public class MammothTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * Switch to a complete mammoth 'mood'-cycle and verify if the observed mood matches the expected - * value. - */ - @Test - public void testTimePasses() { - final Mammoth mammoth = new Mammoth(); - - mammoth.observe(); - assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); - assertEquals(1 , appender.getLogSize()); - - mammoth.timePasses(); - assertEquals("The mammoth gets angry!", appender.getLastMessage()); - assertEquals(2 , appender.getLogSize()); - - mammoth.observe(); - assertEquals("The mammoth is furious!", appender.getLastMessage()); - assertEquals(3 , appender.getLogSize()); - - mammoth.timePasses(); - assertEquals("The mammoth calms down.", appender.getLastMessage()); - assertEquals(4 , appender.getLogSize()); - - mammoth.observe(); - assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); - assertEquals(5 , appender.getLogSize()); - - } - - /** - * Verify if {@link Mammoth#toString()} gives the expected value - */ - @Test - public void testToString() { - final String toString = new Mammoth().toString(); - assertNotNull(toString); - assertEquals("The mammoth", toString); - } - - 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/step-builder/README.md b/step-builder/README.md deleted file mode 100644 index 65d356c2e1a0..000000000000 --- a/step-builder/README.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: pattern -title: Step Builder -folder: step-builder -permalink: /patterns/step-builder/ -pumlid: LOZ93SCm3C1MQGQmzUysYYqaAcJ5q96i7t_x8KXkh4soKvfypeZfNm33fnuSP-xfPEtI88tQhW4i-M2WmGzlB9sS3oqJ8yZKOQ0lWOLPzcJfAoZQtwXfeyuSyW80 -categories: Creational -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -An extension of the Builder pattern that fully guides the user through the creation of the object with no chances of confusion. -The user experience will be much more improved by the fact that he will only see the next step methods available, NO build method until is the right time to build the object. - -![alt text](./etc/step-builder.png "Step Builder") - -## Applicability -Use the Step Builder pattern when the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled the construction process must allow different representations for the object that's constructed when in the process of constructing the order is important. - -## Credits - -* [Marco Castigliego - Step Builder](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html) diff --git a/step-builder/etc/step-builder.png b/step-builder/etc/step-builder.png deleted file mode 100644 index b7b623657c589b4cf18160ec268733a3a16f69c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76038 zcma&ObzGJ0)-|dKNJt|{C=Jpe5=tyeS{Blcl#-GH5{r-y>5^EafOI#Abf&w#NRqt+R(9^)4fQN`1tpSc?yc+-AZYU;&i6ef(pr^$z3sN0<^Sm z3?gw;-z;Y|HesHTHN-|(y-yCa`$}uy3nQ3?NV`W2Qe$OJ9c^OmgKTi zy_S4gzjpXy*RHSrRQU}a8ZwfnFeR=ovPuTqo!hU_ki9%Tj|l#L`7`LBFIR$@kbM?! ztT=z+WTy43Lcs^UW4$NQ-DQ*?WcHyBnTj|fEWY)FWr z(}`}%hz!ttSGdd;SEWK^I7OJ#qX~~P@kWF*kr~hNIY2@b*_GS0M{ zh30+Zp5?xz&&kQyufNs})_rO&;%Ll*Lbu0@O-_CfM(F8OD|uc7n0dsw$Wdl58|8~j zJX16l!zMcIhoICtymCM2ysv4{HR~({OPtG;y=-ZD(Q&oVJl*u!rL7gEQF|*O0u6)a zOLz?GH+VK`)cz9!G^S5ZcGPgAj4t0YqSG-whRDd~o}S6zC)@UitGXea!Fk75hy9V) z*J8CFw+7N)ErpP+QNcRGbhG5?XcW}rObrd`<$vJ$ooS;qH5tZWEy5ETS zIas&(bX7x}j^pkVY>a~e7+;MT#~LcuCY6nk4mSy-Cl30tlDxcuA9lXi=Q$BERmBIA z@A6G{fBw8u-ux6dnx8;jWU3@C<C%GEmu8v7^*)$V>%)nJwX#T)Fa7J;N03=MetzA$ zPN(h30(63D7M95*!30gkVCClz5aQe^bvvA%DNH!#`5pUj$1dCDF9!!B@nEMq6zdrUIzo>sdwZ3aJc!)zRW)Fc*JQW6!Ju~lC8|;R34l$N&+9z?7cSs zd-~s5ctwKC{&Od#<*Iv59C{FuD&g|!2DcQ;sa2-gGbPngj7K>#Gq1g%PDkrBk64U| zlpkL(tv}O`JtN%Mkk!_{`1zn8K8K+~+vk0F=i&*3o<@add9Q_P^F{DtOTh7BTmXSz zp$^%>R$=>8nW=A$plQUVFP6SkSUibRVKS%egU_%0+$TyXZ`bd7#Yd5pospqn1lyer z_q=DRT5vTt+`O2++IwgyNK)qO=~>|Q`bhs|H+1Da+pXuM-+E5BAU&?Kam6Uc6P(qp ztj@?84Wq+VEENHSw~`pXhUQlfRxO_M&D_Tv>gvo6RCeFsEma z0m>=h2i)ePl+*^~rzbUM*$KR-lame=CC|2}#xQv3#-pyRK2eo&-?_Dx;L|u^g=oKW z)#ckWw!xvtI3ifA)@Y=F@%^Y#vG|!Z3|&;Byqg7|7ychJ_;e{Xaz8p9?oSsE!jp%s zE36LbkNGpJ4Nc^hj2pindq}!-xqF)4-@Lkud?D=`7##e_pX%rfo35N#rDUSCPspFm zjR-MCWWb}Kw!O%AnSN+?+X$!!!Ms{Lkq%EOFtEG{7KDvTtme4fXhy**=ARn*ckImY zC-KKJ^?3(JDX^uSya}g8WVrtS#7)W|C0c0+BYgQQI#O79R|p7Ws2YjX(ihU_v}1C( z9(gJsXn}DUnb>6Y!$}jK4Sx#J>o=*S+808jkvLE!Av!LAuhUD*->%YVy_fk#r&Kgn zwZ`;Mg!uq9bdpGb_fSW|JD(U^tZvzui*i#9GWa^;UMDvJa##W{!)-7xDd8(?oS{xi zJCXb?*tpfg`w7K|VZZi##J2+xzAd(${c$wOc?4=7X(amRD25W;-|Qi3;=D9q8eFa? zeMd7v90s(!7=O}0SSakJ+qE)S;pwxrRb77ir_1{{PvT=AzN@!>=$FZPIdes`vvnKb; zQJ*(v&>UyNqiiAzbf$bF9*~=SekMG-kp050t!~=#-9_i{uzvfOS2;PD7sp$Hy%9td zi1W4I-rf^>Zsngr&ZWqHWQ840xE}t5_}pgla_!kL8z*(}qn1c-YMOijaH_W2D@)1C zk%}JQB#(QcV+cih4*4k|LxWAifh{-p4E+EI!k$Lv3F*riOAzy{L8{GyW)=A|QvPV| z$$O2s__)?j5n2yTCY1ZSe0{Oi27IunnDcVi9U@NCswoH@7;-i**rZEdVyP7sARPp* z=j6Ak4G5NYhZPq7`a9F_-)onfwIx{b{G`&={nB`48w@9_?2B;isSr4heD-0eC7>A( zq`NBjo2RnX#@(*SWoy=(%Fp<}f86>OLR#NoYh1Lchd7#bX&8`zTv@-}90}((yUHr! zh@|t)7XA8hOB7E+CS(c9tSSf6CoEU>wX0jw3q*!277cKO6r{RyUbUU`+8uSGm`bj5 zftwLEw&_(pJ2MzvP?9ohQ2G^xg2uCGRc zb)28S*qx&YaE_7yMS&`(!Mr+I(A5 z2j7QTIESIyYN_PMN-waf)Z%F9pW+-0Lcip?IW62vmz;XDcRiZbEO}FJrt9&qFXQ7IG?Fis3w3+v+@G3< zRwdWH-3@#=Ty#2Rb^3OU!rhgnNakIBVZG{o@M*PyYYf}Sd&hj&z`2o8P*;qs=CJlZ zqfW$py%#BNF^PxqV1Z7So)dvg;`mz~sla}^N`G9uKdulS_hlp-ZeZYrTV-R&9+7Gx z2iZ_>?f}6o`;L{+6vVt_Y-heWKKOT?iD0&YhNe>uk1*30mz z>+_=D)A9XW1}_Ki))fJ=jkEHzrtxLQ9ch@7qeO8F1GJ(4R zYti8O_NI~H5J-^4#*=)eN4F$54}JE`AWW{#5#YJ;?p6N*Grg*!kh!9t7r58kl>*Vu z=(1Hvun*5t8;)*$3INT^*7MMjCE6 z2pCUt%PO1AN2cQkI?@-W6D992Hfnd1%XvY>iGvLl`-TJfu5fqOHE{}iw<)0=dtz}V z3aRAq-G|yAJa~{v)5yjxhnTnxhU~PPtE`JSPWeO_J`N8TVtHf38sUsuhy0t9*}U~W zMV(&<4n&*!Nx0j^k@6?3|1lttp3ErB){6UX>U*-yAv$X^PM1xg#q9(V^%NfUS8BBv zr@6XcRsO=lZ+=E9Db^m;wfx}GCHP%|Py~^>5 z2Z}vc=_KvI0>gu?A?_r+Dj4sEUhV1cL^0Bk^5pr^x3#rBungHeS6iz7c0O6IW1?$5 zR&abWC5T&8zTIOL+Tx6gw_`^e$sKbeWh-7Ncj-15XvKs&un>kvKXb1xud3L%gKxnV#@=dYuKfKk<1hMH zd;7V6wHssdTaA8^MWaD|U_BT9^{7#8j}LLQJ}8;p&v73>$mUKt2I6v5b`s0;#i*Jvl!@igC2HZ$R zl1u$7$n9ddKYsC6sR;V+sJ7qjE*m5Zmy-)oQlz$b{dkMf_3@-+pppgDcfL-mlti(Pg94gLtM(@^d0+pU96Ez?IYRG*r&9s3ODhbxEI%KwC-o1O6n3yR0 zCC97LF}F3jF6$1coyGi4Y#esBx3)kjK7ocqHrn3Zz26Ukrb*k{ZSj7XE()i4EGpJc zEd&Z%ezTbxg)-GV!9`8FGRe!+_LEKH{blK;mo8TZW za_=sGWoAuDOo4BLK%wyFVIkZkJ1)5FnOGqaF$qbL-I@V%L}c@TSJ82;YGHD86k(uq zgY^QkMcPAtyLXtA;$^|VpR(q!{hmmNT(THn*!Ne?K5M5k36M{ArSQugVP(wo2%$%# zwkbG2Y`4pF-WAjv$I}uE$dp|DO;!!4fJ)0C(Tmm~hGGM&X+E5U!_{+ryOplD7G|b` z&CQ6@?I4vLNLkQfVCf36SYcEUER8g!kyN;#I^uKAQ$s^T`B&21*WzNWMj6or&gFc- z&nxV2R6D29&h5$oR zQlg5CT%}zdA>>+x@W(?~TJ)$R#l=zLuT7R13#okvf%@|NMM6TQPKgn|?C!Rp$=-bO zZrx!;shw3K-Ub)Qeh2BHqrLH5s0s1${XC%*P~mRor}&L!Rc)Y7RNh?0r)TVo(R)y@ z$aYH;U7Ovhe&@A$UYuQ`&W!bN%MhHn^29(cOf>T~RL|?jP^OaagAJb(>;-P~cctIF zj|s{ulhI0F1quj0R=CmczK3cL=V-!uINQ}lXi0A7A}>#kpOPcmPoaObhZ623)Y%qt zIMCKq#>z7J_+=T!#-K+@cz7s8_x|Ts7ungu(ay&iI6_W1321NawkL6)yL(aZ%VN&` zJRpJ0qRv(yFTB5Tc`m4U_4&-Bs&H)io0^ix6%!Q8xUE_jwu&|HzNxYKrHEVzwe2p)U z=dq-PMDP=LQ(%#NeR~9bo514s?%jg}NoiD^oqz)3q0?=1pINj?$bIfJ`MpPugaAdgs1U{DDd%z(q3T_ zNjQU8v7=5*OdP{-aC&?!=(I=4&#s1=_?X1jxY;xB>gfxIg~0Lhw~;!#=Z9!H zLFGdV#X`P;w{@y7CqMmgD14Ed3T5&cQgl){ zaOI_?JsobpH3Z*^DsMUtP?GKi?M+wPg#-u3eTj#-3zcEYem)vtn=T$;V}UN?^m^(! z=oUP9iu0_qzyJM;w}Za1#CfXDc=>z{Zf61BSkRr?lR(LHp&Q^)7mt`?Lc{ToJi8`@ z%(6tvk|(7va^#--lm6H#UYaw^-ewB)`!4Q8-&E8TBxdUgBi~nC4B!dKn&ctUV+ABp;IrZdCK%VG@^!|Uc z4;_ny(nHWL2H=TzjPh-1Kq3$!%94u7f>C!68S}V%r78H-RrmapnN&=!{`>EZKG;Z0 zrvl!xK&#TBP?so{%~CCgIO+k$!F<+4IrB@tv&Wr5Ow185MWH{;#5=;Ml!uCH7+z1_ zylUHC;+-=pv$~atNc^kh$;O+0!zGx}j}7)(*%_HQZ8qsf42 zgp{aH7w8P`?40!V)z{ja!oSws;RKmsXwKcF^21}zGLt%+C4m^<{Lb-W!`$8k8j0Zb z&>yq)-Njooj&6B*aiuLz{i{ifXq@(W{#3W3iI; z^-g{V7Oya~p=B&6)Ng*?vBl@p72n+0*hEVP3cj$P^amNmcuSuRhUk@KD$AcWl}U3; z;|SNz8>H6T3%xT0{d1bBGm8b-)++u-YgsbDR&eHcvkI9{ljPv6_h(iwy{1Tr~>2|c9?tabql%N_Sz2~9;SU-~kB0#X!!lj>NsQ?1>hSgcK9`$Y5*fF1QfB-! zW8@%;mt~YPpCYBmC`ngD%^Y>X;8eSH`p$eHG{5Uo}OCK+sn zR3`emx{81WFdNOg>##X;5yZ}8F4x8uk{e52-QYuXeWH~d+8+jx^<(@+1pX~^84in} zxQ$Ye+u=JcEn8`~o1H77df?g96X$#!tU|ZN&@wgg5dkQ#h8q~9C8X`VHZf6LX*lM6 zpM^+?mlu|a&+ZJr?TUd^f$cog^&^K1F z?L2tfkdcCPhJvgjK>~Njmm)gq;dlJ720)dYi~UGY;FstOc(RZnw|NZl5GA6)t^eIb zOMmER6IZRu4`xQn0OYB%kVM7!yyADiNzL43cs{q(UOP{iE`gP?&rm-Sy2j`VyV_fD zqW?%@H9hXK++jAI1^8+Uiymv)akPxH%zHb(JV4cqQcKyYP^mx$+zo<9&R+(o@Lit~(B6RR_33+I56mpM z3=>r#GS^$fqU;r}_s;d}x19I0VW@?aipnfS>L8y4^OH3qM?-rflJ@VNQp^vHjBQrB z!5x&%qiI(aVQrT$ujELndc$6B8!=GsR=r1$VTUuF1XxFX`^HKk(80*kV^sLaU+?9- zE*78l+swCW&KLLqYKD=n^;`KoS@R8V*`=|L7w$6ogeBriDT7vjyexee!_;61X`}kQ z7Ep?wd8(#k&;*`WMNR!ZJ&zJKUC^P4>NwSHB{hz_Qte;zb&sA95C+$L+}b?LN&T*p zE3@OwS3;%Y=ISlMA(3m7c)4<Pt7gQUqqNz|V{F-1H~gOgue z71Mu#w(Jq)sdHNPC31SDR}o_<(>2=vs3)bIMe+REAm7wc&9i@rb|nXX>`N(xOJ|gZ zMgF|w+n62gJm& zA!NK}Py#%>!3=4F?OB0kYuAwMCY{j>pKSg+2F)z(g@eMwMSs@s8!~81Kt$SJ9ZwR- zzVNr%CLT^s?mXS-u3VH;U$)py7^)H(uFCXO9isA1)gM-}h0=TUR3LFb9(>sfwLV%W zb-Da7z4|M6gMhwj<6!76!|Rq>-2M#)qmE8Wup4dqNj+dO9b-@c0~@XN$=t88#hb17 z4M-0Xxwj_7$*}bc9WjoS0Kk#$ziNoVr{-|0VTgq&1+v?RqGL!%Ncg6w8%nzb1qBt4 zwY7cA&Xx))$DVpQb=v&mKHCRvJ>1YcJSga0r{>Q=Gto}$`^q&QDUU?AAP2aa1d`Y@ zd?MDbalkJ@TIYB-MXCkXj!h@LlIGt{FY zJzgULv~!$ZR@MFK<~$f($-F18?(b-9)RHoGd9=a!^pVz7-}Dsn;wfI0T-l%d;*5!* zU;kV}BB70<2T5(p27DJ_-4c@?_t!B6w!B+EyD;sJIoH)SIZO_a`d}qZcXc!zvhGlN z<&HRZ%9795yS1|iXz9LKWQ%HbxkW_-LqpFvIKnJrjPki~@{guD4acfaZ&sWws3YLt zTpJ~59x1Y(h7Rntn{a=zvumTPLSDT)Q16KdZs;gUGdNdsy=Twr*;|GXHM+hV@89~n2n3xKH^u0kncK^YnA9D#& zQAd;Jg)7U;do;2oqeR8YOG1g9T+GV7xK{=Q;dCmOCGH`-$zMe-C21u6k^=qBJ_%bgn^_gZF<~chvGFv;~8%`rXRi$!wKe)z#J2MV;TQ z0#Z-4w6t(=a6&@GOp8_hmUF~-kPEs4G@PvOB8`tYB9?uXyG27laCQq;ont94d_BFN3&BjF-oEH`A+A&12iD|3b!_S0~iYt{bUN(T&~_Hk3zkwY9I5^~F0viQj%*A=(+cAfr8@3nc@-{6}k1+p6<;zANkPZspw0#!PL{ z=9~@ve%48=dFy7$>{bL_WY?D6)ii_X8O!MkvXPYO5kV9I|K^;>k-N8-bb&@+mFu~! zg+-oBK3r5(v`FJF1Kt0Ih#>d>`+?@w?qBqJZ1v=YKSZfR5SSY`Xeg1|r4QcZp(2fr zjy5zjuxRU3{`(0GY{oek(pNcd`)dRC8oTA>kaqS4YC%>8N?y{FE1mxn2Ge8rq3F+_ z&GczR#H=lGEpHV%`guDYE)GrB9bNUOOM>(rcLxUtf$3y6 zNM}KmsXA~JRZvAyQUX6LK^+YiWq&~zq1!>ne&DoYme$T%4;?Sm<%NCor~_b&3T@~7 z*Ut46uqtFtb;D;TVK?0yS$ozu)6?Z>XBRII8(Z%qjEs~Gm!)MfX ztj`aOq0oL%#g-Pe^=snmB87*CD-wGOKScqjH3Q%lxZymAz4mVT?d`%~+L?af^gA$y zpj3WK6U67D$!;|2XIGJD`!3Pz`FBBA4!4Nu*ehj#4NX|pYKF9Pg8@ySXmt$7f$MAu z8rBR@|H2nkU`$i}lG;{iad@KCC)nZ$ZBU252_ zn!qa={AiHEv)&~(2>Ko2gJR>n{CoXuv`F7g;q&Ql4T%fsWDjKn=HZ8czL1pMI?mba zLjOLCe7^LmjaVkN4Z6)7>}wnHFct1=nY4Ymka&-nw}9PW@=kzN;dIaHF0Mk(ape5I z%f8mV;Vc(X2krW=*u{0O=gKX@a@L2AzjD>?O+X5CAfOf8go?_=Wk||fP`Ix>J#`mw zcz(kA8Y1-~7uNTp2cWnTXWZPD=o2kRk!R&7iKHtnncH&|Qzga(%b!5+z`p)0gDIb# z#ebOQ{W|ON)x5};0BOvah7lLJ>_;3)$oobH21paMA8n!@kh)WMP^@IbTi}ywPq0=< zK|B536U~ik!?psu-J9;?adBEm2sm@F<^hV*cb_cBaf$Fa`+D>B92~BKNz$v%Yk|6H zWwpR^ylB>{aRs0`0D7&{x#bp3K8aDWvIa6g>Uifx5)V_%SvyWkL#jUKZ!*W6PQdf0 zczG00Xo#5;2<<9i-S~6bJ!PbPCSj~b@ocAYDOQBU#QZN`j^-$3c~PJ<;G&hhda=on z=9=w@P!_Zu_?hSvWJi1x`YEV5Kng~>f0T8W@9BqQ=W<-Kcj$70i*ICVvOeDIw{+eQ z@l4{ctaakFTHQhM0UfasU?6aXMdh$fOi18 zI7TF+>96amxP5z&hsVPncW2nO$G-vL$T~V;p^}r6&(F`%WY69@(IJOG@Ro5vy3d$B zRti$@x1s2Zi+}k29UAP<+KPdtaeGJsu%_@34VYLXXbHPt?Q;U*jO9q79&tEmr^?wG z8C_ZVekp`kSj6wHtYj-T)^~2RZeaO9Av5bcANmh&j>ndgUX~N}%oXbZIzd8$I|bfS z$QqRaZ(;a#{nLw2(13;Ybzl&*$m*LQEU^$QG>RQW`0*|#K%|+Pnm%7u-cQ+l9R`tt zFh)3!LGQ-PUgV#Kyug1L`M8{gAHx&2b%omry%ls+qW%Ev-?w**i(YfET0a@Ywa)S8 zFSD@%mC6s>C);z=^)8ImH&=(tz&9oZVY<@xgz}fSq24YoF0wkfNS<#w{`~d8DW+FxOzAE$CFMDHBQ7Xn^t%ECmFOrU zVBe)OGBP-Nm9@3yLU}teo?naqJ*fy+h*C#K$DMk&k;;-gH>tO_$xj(QG&B?#7>K)f zeEdp%6Cdxn$9Guf+B1>{lRM~IIw=Xid4Q`DY7{`fIK9P2@`&+h-R5;Ka2f5@Z_ zhMD5`{mH8Nnsf{dxz{RhfUHqLBFg15`|^;?z!uXAkaGjW!>Q7dyto8JtL^!7ifnWv z#xKT7w0+2>ZuK#UjK@AcJ|L8X>t#A#TJRX5qprJSauq=74j$7%^wF)_u$p_d=1*z&deS2K;iXy%9Z4~L;%DAr1fKW!+HKv!inPebg0 zM>)2lJntfaQY&iW>Y>+q$JW|f zaPB)!3p}1rB{H7?pXqr~-t}XpI~Jf6Ed_-X#X?2N-C@QDMp?+`>B@+fOu{XO5c9@A zECrnP4Nf5O+m)j*r-d=ltQwzkyu5j){TdMaA(_N$>58GY`C7!2^)6WekuSc!Th6}L z6&-lHTPcOfe^WfDXrvXKCc-?$(HjvF5dgZ3#}SBpqU5LRpm_NOG7}I$yu}dxtz0jD z)g#Pn;2cOsS>m1Us>?qB)$-Jcqn|0T`~_-O*4~Z||9VA9g(ueUUx@Tf zFd9%(Q)e&}dMZ%M{DNvGyDOS%UPhaK0lgu=c@9p~!2+GbyZ35>!2SzYn7~DQuai9Q zs1W(=-20W=-~Um&TcdDde{X_|r6s?XM*PXP`N!=^wx(}q=Qh!!f0i=fa7)9C{H0-# zM0SM_H#Rm*_4QNJpuCKahernJB80>4m2EMkc>qzwB@fTLh}bOJ2pALI z^J^pAj{bg}2M?6@W3<9+#F6XMi;BWra6Bd$e}3E?N!8Hw5)irA@NwE2ZJ4dERo95u z)N&MXd->|%AWD1)O6QfF8^*<^*U*y@;pZo5Z~q*NPld-i{dJGL>0SWk``hA48WN30 z>K?&bS6}~HPHuc@!Mh9n0~&@ypdKidNL>NZ3>w+MRgjy7b#;?LSuQ2zFEir+9L4Ks zzAe!NJjd=ooTM*v-Ph4or1#sPv&FH# zJ~kQ}vCTzXqd?Q)Z%uzz^`B2eZf$J^ofuHVC=!eBWXDCjqxqubnA3@HeFy)O8nDmQ z9d|)xGEKAaoH!k`gN6Ww7D1~OR(>lXlmXdsgA6=@k&)5DxaKjx!}9X7ln%8R(kG)d zj|{jGW{E23@G60W$Y22WNxZ(exF{efD9uw({^v=tbXt#U%IWERDoh5e0L4@9tf5^~ z_L%dpzIZ-sfxTH#TIwQ49FY7%VQ{!!+S4}f&X4;*7j%Wl+^+aWbpz1zoo-e7L?+l)n0&t#G@F=C!A>z zt%1$V^C_!O7BfzqtvdRg6p+5%u|o6DsK$Qi&HuilzY&uk|pxj1eN32}eCYtRyO_y2;6zhCjFh*B&rxv;PlKtEa!?8s@k zBO@ClmwwMSc$a^7EW4znB=N(CB3wS+-bGM++%8O@g1WgZ`yrnwm2>%7>WdCZrwYOWNuT{(}k!KD;JNxtf7h&w~h>!T1?ahXFdP<8p2u!UB zhlFjZdbg+U15nWyOzeVU?7`u6973{G_R*a7V1exMfw!_K?VnKo;J+fdE!SXVYxuU{ zeOn23KLc*u_2H~gkk9JnvKTr&AJ72hEZadCRlR(YjKm$b zskSz`L=T!Qc*|q$0_NbN6s5k8U-lhI{t;Z01_L>-eV5Jrdw8ZlSGDV>tlZqk*b~)u zoTR8B;6SQbCeoA<_U1dKJ1=3a7w9F1qb!A3WIw5?+fu*3f8X98$7!}I$Bsq`tggto zn;wWB?=eDdT$Nm}dr8en(LELvUyK@IYWS-X_|tk^pv z5#iy3;Gi?v{12$AVO^cl-m4z%K;v&E%}EZ*AIETB%Rn^reF;h)hYKKA1EThWS&3WZdbJg~0GN%_3B3X?Q-)!J-}f)o_QUzjUq>Eyh+7i>DDKal?7Z?6zQYz3 z1CNKB{i=b73j3sBi;epEe(_;!>Z-zS!-0?sZ~H`5R_yq9fQChSa|$4?u^tT|K&Zui znF#Yry8w*bm0yGG5R?PgsL%3bT_2UPZ46raK2&x8D3Y>ye@Uk*lE+*EOl&;83xJPB z^+T_Q+im?(?wcQdZoFj6&3N=>`YI_U=s}3VyHV7;{s~r%Gc@u)!VBTZkG1=vgZNjp z*B-@lA!vnArUl8`4MxUG?+-eQsA;H|i7mZR40f%1A)-29bG0EaSEml~JUN+3(TsbX zYJ0uk-d=-W^NOH%N*oniWn%W(4-*Si?6m)hE{UcI9Ldp80RX;xPA za8}kpv*~2n-GoMhj>r2~k1t*U;(Sp0#|8!lk8mRBMJ#tkAHfhc-|YvW9Bfv*B536N zF?(Ii5)laj$t+(ic3<4$-o7wxi057wkX-_R?B?pr(M#(;QOO=tU%};CC0LhL6_lq4 zUC@sW=`CFqF+`GRfZ_9*$U_47R}$^kK!r#s^OZs~xS&<~a zJuktMtkySbS@MqqUS}BD4I7x_Lm=4n^nIR4T+hA_0(FzaOB41Z@+*X2%y)RoR9mQ{ zNVr4@snilQ8f7_Hmk>bK=V!|LVV_|JM$cCM-z3{q6skPVyXi!T zmXAKINw%Pxf&-X{YJi3{)EZ=3QIXUdpOU%oWd1E-dxz(8i4mrBo(esM5ioZn!+v5m z3&R=O)-aG?fKL#=T51cKKw|O6@NhkfBogIHEj72eV!G&JdaYv=?TmqgnEb2O&wd55 z(b2cb(#`|I{~vEUaKpiEy>w(#NeoC0JBqY;6MsCMuXXv>8E{*pqmQ9*`S3b{6{#Vp zx9z=pGqrFIG=z8_NU{;E9h$dzpU$fdu8T&S%=BnEJOJrGf1Vh=1FDOn($dHp!f4Dt zzwQ3dzp|GU7e}Uz8p+JorVN!My#41Qqu;@!sc|3R|L=#j!R^H@ELa4ul=uJp!%TR~ z!S+oPrSHjjKlBjQ(J0eC=%)EU3EA1Be@d~*R&cPG(`|z7+^*YRL|=bl0cfJwUKxAe z{j~hQ<>WwFuY`Y_0a3v?)6DHe6^GQLKuKRIj3cSgpew#@gk8L8>?1sh2aD38(KNT8 zd}xvXyR>+^-LO?o2E%eN&1R;i92D+V_NM#>JF|l1gv(7(n#g{uuK2(BAv!QD4A*&E zp6QV{>|(V`(0%N2_s;_ddiWagb(c@AzXo2oU%gawraS2Vl5k0ITTZ5^=6{{3`S`ZG z0?r>B7-Sq&P)9yIl=jlW!q`ap-V12*?=Pj{q}&sN`KmRz${RGr!D+tOTUqYFVZK)4~jpagA#*&kwy7D0Npacp#Jtm_xT!M zT*-x<>cQ0#ulj>3>(TIKm8|L`pzT#H)WyPQ0P{pXuWCUbYjv46<_$!rwgU4Uh~-O7 zm5^IVO1^@5BANO;wN`f<>DfNh27dUb z=-6ZCA7GKpT8cQc0R`YcV4-fZyJfNCB>7$lBpO5NX-<&BCw<%t(+c-dqr#acLoO1H z&d}fWZ9Jdbexru_(p`hlU6nmBP;5bfFm$>Z&Qb!hN08$)q<0D%KWLY}!y+Rqy}3SZ z)^iu!*)&rFpy=gCv!>Sc9Nc!w`{aN=@T|B$QJ~3f2%0o#aS4_AX>HThh8kBuZZEp} zS8o4%B*(}>86XJIYIg&&ug;qu;)7LW4UvDK$Zpyz0s?|H%CImFes*?rFVxNZ6?^j{ z*y25U?nymenwC}xDp{`V-#F%rdy*@%PET?kcFrJ z(g=*?Yu!)W0m5|4DIQ6$s3>c4{~yokLTYQxXBHXZgs;#Qi`N5@I*C zAn0^BPNh|ss3@#@&|^tFPQNJ0Z+YN2(+7n0K8tC8h4sTw1yR7{$jf7Q_kFqPcmLl1 zb>$&3F_#h|C@A?Q^}TyKg?jzM z2Ht~03%`M`B$>~KZx{+-0T8D3N#uuRE#GAA%qCJYM}3EX=ye;_X)jcVq%Lxs9<-h9 zvt^$!9UDpmOlC2bB2w|b|J$ulA=(NE6)G$ymU9aoqAso?We`6IUgEQ{xxML3Ek3(I zuP3~P8VimGMve|>S_M=6{Uluhtwr!YH8T_OS-H5JVuGXJp7&6B-u&!^JB&Fh5{#-D`KU@BUtK*`lKMwbPgxoVn=E5Q zav407aO#YZj<|u>xcmN3xOSZdFWpEYkog6%;BeDnQ>vgP=`{ znhK9lOTs2EwoBCd3OD~A+D)W-koPziSK`5=`34&94fn$NB!P3GQ)_&ujiD0|nKCk8 z*<5T4q^g9yUcY|#u1$D7n2c90Q&r7G9t;=)orTJ8{PvWb^|8V&kdgH#Zq+tdkqjuV z2twd1dw^)A3XU4@J|ZA|Wbk2j+8h@u6Aog9J-K@g0Rj6c6lfzkKY4#8f3%JvVrXjW z^#z3RcffZ*(IOd~q%+odbG-~^z{CckUb@FdMw*yS9`wYs@_A!@_zOzx;{s&vBci_6 z{FrjVMFNWRx`V**k5Bv9#FwTpr>B5aCfZOppfRE>>>V?@jppb~-2YiO%O) zyQQ{cphj)s1e2HOpENb%0iFm5e&7TqCcq$N&d4Eg$LR3zUGxFCgi~Aa8xwpmX@dTu z^+@UR#7eX*hxyz#s|DX(#`Bu2)%KoxY311cdw zn8021zgi9eV)B8^19a3%j!iJyZX}Jq!rt9(@W><5{FdHHHF zQ_1sH4*H+1EYm&_y811hhe=$~Bt=(vf*)}-Z08>ow4~dy)&|D~N(CyN)McOG;0I)6 zWI3`T9FKrJT=pr&nkCiUOHrhf>lL9Ew3f)cjw6DL#fVt(Kjk!_oc~c;NCBNwvJmU3 zh(`VGljFXjV%oW5K_V2?)uo_9op(_);L4lFyQ6Hq@R#(>{U7;ZW9$&R!{c2k2woSS zuW`QkW9f^H7sBMvEylyJM2hzryf>J`$xSBZh5j4B;EQrhihqW>j!#Ssda*vc`(NBa zBvXK!jEF>fZFe-O%J_iJ#V~KPk|2IA&{n3`VH#RU&AX4$)4$B}JA0P@w5ca3SjVL*Wo7*YH(k}WLSo2m8t z>?NRVd^Y<|S2qI4oc1-4JF5sxjT9A4f`~%E#KTN(Y-^_M6!*8-tDqG2*F#Y8B&h<8 z4`BmRyK@j=

    MBpa_M#_enSb3IZfspcBMTYw69OtFmd9_+pQS^*HDZ%%T6z2J;H3 zYH`#H_UMG2AQA56gFy+PRa9*TueNZ0MD=6W7v7nLb zeRH05NAe+|g|)parnrEt`(leTt%J=*kS!Q=4|M|5M^2k>(ouz+kMMXdPb(chmLKjt zQUHNpffiUY&5qBJ4F z55_?~j|7UW0bG|87BMFP3fIj=pg5j>56!i; z<=L${0D4H#l+<06ceQ+MQ(O|dD&aWmHrC$NRc5ZHbR<@EKI5q2cA>7R<>-AO87fuR zV=cV|^}1J0K-C1`khcwBLp(Eqgn@W8&}coes2S)%{PoxbWiY9JWpt7O8K6a~fxWDC z8=KB#);BhV9AYM47fw!7Pvil8f53n+)Nr0Lzg;S_*U%u}U@!=v9b@5@GRY7U5^K0H zyN~JO^x$?x4GEXm+6$MU=d`J}7{)-0C!6yIB4QzuC%nU=MfBV@LrgtRPjxiV<4!D? zPWHp8qyRh{DSFHuXDQqOJIje@aOQ_KML-z|>?oEczGcY81&36iYK?!l4l65|i`q>> z;(;RUXs`y1nZD)XI-FSDUqTjyPb8fo5J5X%+WT@kEskg3~bZ?dzvmfxOq=L!wMn_%(r`Cry)` z_E*fRoe4w5yH9<`B~PQY?dC>DZFqs&`e7a~9YK)NSC|)^^-`VUJ4*}ub6YTn{w4q} zB-px{y{x9z^sl3}P66hNt6pQ@1$e9ZuXwtp?|29Zey37zU!dz}h|>mR_TdTs22^=- zWAod=SH4{$jRZT7&?!|c+3Td%D zXf!||!>-T2ot?#J-+(FC0!8M~FkGvOTzB^^@U{q0`@icu@){~Bdwy4|!ouqs=R4aZ zxAMksi{5-A5bmrg9n*kv0AS&^fRxQM$yCF8m$o(=Q(*i=nN$w~;6tBr&>R@fpP(|a z+z;BpWeLB9oF3hKU?gnsA;%$*w5}N1_-4SXNK{!ljmMy&6l-FXV&*i5pk5o?@NRZ{ zfuK#Uik?y~aELIEA)|dhqz8M!185U83XCWIt-NdACF8J8mP|~{O$qF zkXj#xZWq2cVqJpsWEp@TJPXUyolL%g_V@m=u{34a&Smf3S$=y>))~6o*LvWm<%b61 z)gBn`{byX@Z8eZiha3S$7rf*_jH+0&e7-%Lph5rTI+Xak3JNyuoY0607T8*wR# zG6AByiDb@2fGp!E6pYhW0HSQC3B+wGZDq5Srf!R0CT{_0MI^t0st*5V-~#1uO<%W zrC-uOGM+cVg|I(1d)ZS2LWU9Z`I0Y_*a*~%L>0U=L=FM+(SiT=(9C1Ei@tNQiIrtTXwTaUyL<>aW)fkA>!DPzpPy5FGVVNeB< z@pw~tTnpDbw=tC;tk2Y9BDd7LNCH%s3I}LatstYcEl7#M!9ge0>Q)O})&YoQ5zpcn zOe}@BDY-jf!Vp9*8*$aAodE<}cDDGhUu%JPeW0uvr>j2Yh;2~*7gPqL*GgB7LLU6qnrHX#`fW|ncI z_CSUYD_qgJNy}eXP$x)pEC825`LOHYYWVMq9UfmSh=@D^*2>28(w7G<0Z_EwxaYuu zm|pjXicyJZrbhPj0LQ&m2xCjC{x#k^*Ca%pNsER~=G8OB39r0k zy12;54$VD)3n#|oq;;QgV#z^r#JTboANgya%(w0>oP_l(b{gJtVzuL}gK-}F>x0~Y z4z211Ok(OsFjVUl_4Z|aBjaE1+Ii@cqBdXH*Uf`eYbg0^*@2^;7h)YXJ zFoAAR12TAFz^y4$KE-VLYwi&@tj4s}s~Df#8ZQo3xenM(!d#Vx;7gWBu zY%DAfu(9Q3WQMNQXeOqt8bh7~wu0C1O| zYiVnH=JvT>Zmy^(=>OsDEyJqX_V!^=ln$l4S(LPNqaYp9-JwXQ$RY&kmXdBz=@yah zPD$zRlvuz!mhN-TQ`i5)`*mLzZkTh9G4A@^BTW9q3zSy=;nvpH*;&#h7z`%px-Gsy z6;2i&5urnLWbn-e6$8V3i=3RCmWD=K6c?go?kP#Mq(58phGnZ%+LUaf!lLhdZ?+&e zH#+9=1NHP6W}xfA3y-pu)MH;;9#l(=i7#M~3w{g~z-+I2RAA3P&|Zaiiis{|w!|2( zYcKIw;->I+!rZohE06l(OAIMeYC%CkOw1!ZB3w^qF174nIWDz8zpol_yKOuq)Nx># z(sgHYO+6T+ z0(lop!NcNG1%HTtgsqK&G!=?Ui)(x)ZEgu6lJ^p*e!8=i|7DD8(ZT%T;8WN{^f$b` zHn1Rm{?rm)q(dNPQWbwdRHO!%Q+u_<(nNh;+4d@IJcWwn%ztRVrV1zOk=L*(LioA6 zv{deKWLhMzY8U-J=CQ@|fB%%a*ps=YhZQ!XHH-Dh2V69^pyp$l{;rQ1f;s`IK_DQCbzdUO#4f( z(@-?8$^7i#f#WXp$7+0NVPM6WG8jDHCf++YT%VhJ-G!uac;OS(--lLd$R92i^BasF zb6bYLnyHci8WQM#ijJ?o7qc;#xBQs*O(^3+#m&uc$jL^OQRCYLwvhkGqZTQ`)8uRK zM##*cx48}g-xip^K+}OqfZ5*6C6c1$tcL0t%45@Bn~8w|loy6Y!Mcn>H#~3KFzyC$ z`O>a@<5#C9+P*lO{Wh8lI|Lm7@|B6k2N&b@`d46CebFj?==YdXY^*igVB)g|*v`-X z5XwJQB5JRCU;lK=qPveglZg@S&i@MJ_1QnZpR=wj@tmo$A^ExR)CJhhXx4SopFO@8 zLYK*zy&Gu~o=tB-x->-hWks1D=&6L;L%;1Oa``#VoD<`|EbuivxTeLFhiw&*s*b}| z$`de81bih?Z^6K=0$^i-UFB@&XPTIg@VTg`8V6__+9@RkOTVqNbGPa4hJ*cJS{DSq zusS!GwpLi(8I4hP^xr@zl3#A_FtD22klvoXwfsPWPRr&X3%lBxr>6b|BLbGzAsuVD z=}^i>S1TBW>DDZ@% zpLJz3L{RZnKJh#x#Q7F5SOIK`Io#^sd1o&@>U`|>XY7CUSc8U!D#~D4Wg}A?o9uE9 zdV^qTNur~~(+|eFm6kPfji+^u-nAeVQg#tZu6J`9N729{X!vQLhaWWCF!sUHq$`uYPwU&_u#cl?TUQ7Yfx@Vat^)T zqu9M#iHgz~8v4QMeF8@Nnzf9)AJE7~lcIno5~Qf`3$Q}v2mH1myn84QJ{*EPw2BdR zYj}iF;PltOS}gb~ak>Ff-YH?kpNZi4&y0)p<2fuW5tW=_K4U{7ERx$kFa&s2cNorG z4JF|p29*wg`aJw9*8s%K=Mjx`8?KaNSu|sqiyJjS+8+1FZ`7XutXs`IYCQzra4=o`+W=qrkUmr}V_8d-oEZ?Sg_r#Pi6q38 z=@jdUw4m*d?E>}&SzVo@w}kM$DLguHZ?ha$1u;;e5JkKaFmQ8i_ImPb%QArDq8`yN zwUeg5xxU0N^+}GeHf=@XL;CkfCas48e^=A3AZk7PJ}xMviHZ{Zsy6hj41@5=r|!4> zpk~fQ$X{{lUckLRL{DBjeM49Hv)AuPm)$9} zCx|6VdFk;S+^^sJ26g!Yx~Y`Do1R7&+!3GawV9)3iAAZ53U z_u_p{yTusPX89y^$h1ycclywOvUf@6UezfjJGOf9DJQFnhsn{ z6bi-HduJ1VwoQD3KAjUZ4UWNS-?1P{wvb?=T4M1!Ekfis* z4j%7s68(-`SnpZ7CSdQ0>|k#__)ckD*^TdY8A2)A|NQBzsWJ+>;D`v~s$h8Ki^J6x z;AMrl)vtfP1)C$v)QsCY3&oLP{M-FfgNF6)dM$SJbv|k%;Pv8D>_<81>vQ0dVmZ3k z%82=9kk)zqR@;P-fdSCHEUD{vH)nPPrSzcb<$EJCfCflvsN|0ESC>aX+03?EV*D6! zmXue_=+p@ie`8}K%gM#dvu+7=X9BiC1DM$QlTHSjOBWGdE)M$5i9Ssvz|R1P19!LAaR*Hc*uT4^FOs`J@#Ei6D&yQf z5EC9^Rq50p`v4-YY&(VXfd_1lUvmWP(7VCgc7b3Dquly9!x!hTZfik0mRXb8SyNpOz#V1l=E<;?bMIz@V%H7jftvx{JSo3`<9sE15X-DMZRABQ=RWdV8>2qnmuU4lVfFKvxHs3MY6 zOLyTzIxHbttt7RyYOw#_N7g*fphSLD0uGWHgqjdZCtS+q9egA7!LU1Aaz_w?1kHIL z-+_X=sb_NgTlNyuRYspKzAsl2rN(IL0#*Czr}#R-kT3LB3I%SsgFPV+*jRaq8G0mP;)UP>f$*4?GWw^(I{T zC#tK(+X=>ya%B3xX~%WSlX7%b z%|yO;qs1K59sCt6ojIQ3^}o`)y`2{zK;WfZz=~%?GRO0FYE4faL~!>QWnRZeKQxcU zmx8+~jCw!y)zv{K*O$~(vLbY~5ui4sF#@gSZ~iq{P_?FnxR*&#P4hpdbQF&RBXVx$~ZC8{7uEKq`t7w z8YF+?mxPi*xIg@3p?&Yb3sf?AE-7#m(wR7>4E$YIZ5)*!Th$OBEPiv%8fH<5arlN5Y7T%rDCz=GWUA3?3-p8qr*fK&x4d@*HD?VCv$X4=s%s=C z4RrXT(KxaJsS~AgDDeMb7tMmM36Lkd00ehxcVS^>Vq&n(OdPaRz`Ix)y{{3J0zQH~ zgt*w!xIfVUqh+7R5C{ke0HNknP3qkC zL?uYbQ!@~-rTQvvCV?c4IKJa+R_hUX81Z(u^5fQ+$imw`vLNxWRAB34X%$uD(V>$n zKYq5X57_jE+!+vpfdj}-W?{A!BcNx*4$=)ZZ&Y72c^uJc?t%hl6X##wtynaQ^@+n3 zpTL_4GQ6AcD=;?jt@_wMC@_as1xH4fs4w)eqW;g{6gVtXa*de)@W6YE5FByIU|8)) zddI^P6Z?SGqKH2(|44F%+fLAqwmMj0Awer67!Y`AVNr~N;!y8I?|tEL{fPEzb}FeH zX;=zwR)NHgei6uA?QU$?+Wm3^=?T`x+TWQVdhz3Aa2C94N9o+5?qG@DC{bNLt3e`L zOH0vNVc?(7$iuxk$B3V$R)ypKs8_P7pe>54h*8b2GxdVeo%Tte3|0LDS>vR?UD$p^ z+GMrRKKWI6i2Cp$O6I{hD5D1Mc21KEsM)lP0-%{)>*8;N#FJpW3`xQY`4u*mM5pa| zCk{1#>CFb&wO1rFa$qJDRQe!<$)Nj-dJ=P6B@~W0Fbe=w=1@5{mQj3L>9X~aTIy|i z;HRHolLy+7yb3|MLo(^f29_9B`SC^u1Q}yf)Wn~3JS0AzNj(zuJHtzn#J}#&5{4bZ zE>}P;5^@qCO~~;ertAmeT7bq<|Nrw!n15uyxEBnOm+u2QolO`u<;R8?QQ%p!!<@RD zSoB;$q?^-m5X@9i@tqP%F zU7F#-T42ajAM;qw|3`{?Nxp;_G4TYEz^GqGVi?pkfsvOid-oLHi$p3qM-hIgc-0iuBPkS*v-;lU0j`E6~ zUB)`?e-({M*h?L~n)v_jMuL9x zxhtg78&$>ttMSpJN23WKZflndpYaUEq5fnj$H8asb@1yE63NrIi-}`tJj!DgH=cg0xi&Q2bwDID4(H;Fi*B zhq)ip+14UWYf$K9`_$SSMmE!Bg-6`jqFM}fbP)(WRFZN|4xdOQ`00-uTsNlCJ8u~y+-1x#NGHxJ~E>G_IN2WPcenSpMXRh(sT#Ks3pc_Kr%+% zr{CR6F}6KcJA*s5_9{1odpN zry%#=-n2g_a1WtFDeij{_ps7=t?kVuG}ejRxHGl*D|Y2R9rPB7qt%EoadK6O!ivD_ zyyeEBx9vv7YG)G5p(!-9xX#t&H93ZWKs{_%AhyA8mbr@`)&o^5@-O%>+!FW9ZE0O#qs<9sn)7B8O_i;}G zND$5;Hl2=!`4i|^4q^~g*{5#3$8}N#POjavb`M!EM#C4|OzaDwZyzJxcyHI%&28?h zPD@oRC6uwZSNAdAc&Qe7{+^Sj`6iH-fm~l1nVKm@KAq4wW7Ls=<#cTp)2ixEz32V%KnL>ymL@{2k4#QG<$>!w3qW^4(`?y#Y2 z8&(Ma;JL+)?=T}k@37dPXW5&dCI7h=M)-S?mxuY4sj4d4T0v4$&*}`?-VA=!m+kd| zu%WbB#2=5I2_sEXQ_703R<|y-?Z9B)#;Wz}qThSzsHGRn42!Pyb_X9HJJC1Z@2I?( z`0nYu4)G4@My`MM>zAE4CZ||TrwTM1yBS3+D<&74e!ODM=OX0UBbu}?I41+Xh=x`} zb}|F2^T?++zaKQya*7e#L9X>`pkG8~>xp^I1~n&xblgoZQ5mtP?qU07OjSmuGc7{Y z(huX5AP_4WuVn{E=yELmbG89kbs8dg*@6r<`MZWV>6CdIbhoAi==2>3g26{gL{GOh z<{Uwrw9INOT6C+$Y3;(TM;ec_#cWivM`COfZKS4_Obwd!ga$SA3 zqH zK?WHrR5?jBT91y@)HoiSESB$)@1&Jc19(RH_H0a9#=u~9__w>DmfvRwbVHp>&R*j? zU(*ZyJlw!3(rntY4F7^Am{m)p^)%ht~!K%hio zb<~x-iu3cH`*Pr*3c9(_^o%;_xVzhnc^;QBU!v;!&$@qg+@10}y?iOrqU(6)nD#|n z!~4qRfvMa6-2Uc>I%`V}2=riSWSQiKuim8jxm7e-?9_I~eN0i{UbnUIPI858+n7RI zw^r8H(Ejx}SVeJrLUKGf)S^z0arx{XS03U+sHw9+M@%bAHI0|_onqu&zJL_p2aAt% zZ0!1>sQt{)tRg>CQwFWq#&T)QOtQ3XG-)CY^IcsLtYl(PhxiN=(l|`{$bQwPHDxtB zu7RXVjRI^vwNr(U&dcM>B5fI9vBl7{54i8o6@C3$HMRY993vz5zv#M$23^7q;qE8s3iLPT(%(zuO2!R5pK#A(H{(?&obfNPP?UoDrK zQD@#`nrImv2WAl6+-fW|tr|O()!0J##fl~`reDP^!`kWP2^x4ZKpP+z*C^Lc#j6zv zQ{uDK4E5JA+iKZAtD;Z;lc&Ao<^S=6bv#|2omeD1-E*(YiU0QxqU(QZYi;#NSNQKg zTOkL6w^2?mRrYfi^}ibD!TvyP?OZ&VE~2a7IhQds&YOHT`fh8K{zSv>Oa5`($G+ob zSg!7h)fdIytBb9jQfDC-kIT*oNeQ7t|Dd2sDw2Y@?O%;*;_=JH)x^mMqx!0XqIye>*sXt-;3tp?o?;O*oq%V-r6kmg5UaA@?3X)POb)%f(SF{c>Em+u*k z?P3S6SL2=l@&ulZ`Kjec>igf#EC&Fgf3 zz<1wL6Pmq*4O0gYgVPMw;}m!JQlWo!bo6X}llMMF;iNT(?b>9oa#gMpG!|p2{=JBj){*Ar6Ns)M;nuZeI$gnAag~D&9@T)enAdSCu-ri$wI8sr$ZC2bl?2K^+!?Xl8n zt+2XA&ucUKVt7bddw*vZQ)si{01Ls+ldQ9&O+;IW>Dn5pV?VIgPS+9zZm!*N z%@1+0HUdx)llYzJs(}K~yYI~sYjYX0@KvwchKI!0f3#R7C(uT5OVi!%W%XQ2(rljVtxd=pzPo78)AFJr-2+sCBhrv*f@O&Q8_$dZtgl~!6&m6~)F@(d==LR$A4@ z1qJ9knM*=jF$J-kHD5Vz41%?x`VIe8EeLMV(a|x^quDWYc~e*KSNN{c_pQjU+^OgY zTb8S+0ZH#YF|n$lVTm|RO(J@qG6K0Vng$Nj`Jk9i#p@ z5z+hR>CztZhe2IYvzzrYh|Hc-kKRR1nANfUR7+r{vurnOZP z6j|NA%adzk+ny??z2k}@ed3x zY!PC1H6;92UFj+c-Ex!nrAnFRoR9wSk5;K0(3~$nBW5+2G?+GI6g zL+9wZq^4l3dGw`Go0BuH=jXf57gn{&M=Qu$EIxi{9hV{U3E@kSbja9e%&roU2g1k4 zm*Z={`dU_2rc-GN%OdA%qjrVfzKU%^zzsFprvK(u8}LrhDtyY0o2noXy^HCGt90lI zZXzpjoAUdIn7ZFR%2g97?LtYq7D!0ZmCMV^Qwv|E97X>F0G_TF04#VC&aY_>Dw}oa^CZ?mav%E?P z2??0cyEtuI+uZ>^$!IHpv;5AE&mcX4;;8(0fUd5%$ax}IV` zs&o6PM_se%DVKq^cK1-&jOD-oeas6RaIuoGo}X(nnCiYXWMyUDZ4befRyi*)w0Ry85E+zBTYVhLJbT%KV?Sga7;tuq;PHyrA9#e_?NG6yb#g3 z(2}JCQU*CWQsC>79aADIJw0WVk-6@S$k>^my_u^g7u4&h`F>ug3u`x;)hU`NHKH65 z5fVzlE;D1+t1u6d&Y>nxFS8dB7UqbU?`sgBV1}R1Tq0ry^%X;7V-Fmh4-A=b0-iLh zp(x(B7jLd8F%SZiKd|eCwL(vD0~^4~iXF-zjy;>z*0;zlky7}ptxd=3%jp}{H_`8) z-(0rTKoaUQ4)TTDaRYMv1C^7aoDwP1w(aXo8EITx9HK&GWF&Y=;L;ZY55mG3tJDlz zwfqeTIO)L=Oh!WTf**Ab_wnP+-QB{Gi@1?jW$zZn^_AyzYpQ5%wqzoA?^@A^K#-#K zRL@@V9@KSbT~aO5KN^7(3u_=>fmlhc1J~fk_k-aqcNDRk^V#yAxFFYqUm)_9uI_R6 z3cB!vLgcNBq?sK!rjjkX=tP|v(C>=B!jk&;r^@x`m}ef^-jgjMA=@P+nnD(?1;9$8 z&n@;%l}OJ9B)|lG&?HZ&sZD@p6TD+=gal>)AXZizySuix`8{;f=bwQ?*3i(9lA@Qw z`{twFBfdW34M>W*;>A|0?;}&$+iM^>0O-ps>^=A~nOLgAo}52=JX1oXVh(Vo`3Cw# zwzZg}xUIPKzn}-N%5x4lBES3CDg6z6nSeB5yVje$+rZtbj8L?>sUmUhAEjPr+7Vt= zg`$v~&&JFmpV%LYJeMW8c7ConG7hkjiR-fF2(RxK6fwVv{|FO|&2~9^vRGnEn%ARw z@|N{52kxe`{rLuo_Yc7&Tr-2Ds$6aN?m0&7%&UaoJe7tSHuksy#UPYNh4BcJcvRk~ z7Wb)3ZoN;F?PzY6k@uN|`6^O}nLg&J!obBp$mq*z0l+gV4=%L;&o{p$wGXF}?_T8p zsNUMvh3G3RoSFqt-j54Y2v&c8a?8cfPfwj`X*%U6pJUHLGHhjKQL#}`=~e{d5U~oB zFqzquOsvjOf5pXD(=iqrl^X6ZOBCCXZZ3*eT0RJy9fJQggZNh9)(XqsxT4*>gp{Iw zvL7blfR&()%jx{WAK0_u(KX4IiBekjDXOPc{0o_q#CK~t%k|TXh{Z-?HI8u$>BW37 zFA0hHqsjH7DR@~S?2DNPP3+B&vXR#hmt3LH`Ma?X=mJ2lp}Pa~tP~XQDbs~&@25UP z1I@}Dw6wi_eNUgdJ`!S4RT`92m$YhZoM&dP3BBw&Tnygjok{=veObQ=nr2zYS%1WD zbsun-yvIcm88l&P-4{<{o(qE8HO{ePTwJmm6}6#iZ)8Y#La>y+`}nAN)SY2&s7XO- zhBEBv^3{8k^=jGDIH(aSWg>HVZMBVt!HR??OJSkjuI6 zxDiEv?`(J;EmQQc&iatGI(AT(8Z{YqMJkz3RB3>B+YnI$xv!N9V632^AhYY)QU$@E zzhS&h`G4V~wsUL~p>ISUJ_X=6pPqKCf?zyL_ts8))v7$9CM&BObDq39T{-LhZVqq3 z*tw9`Hph=e3A7VEe;!DqMajnUc%xwZ)p(&+m`meuOzHLSKAmTX~W*BG%rh zVv9`}5R`p4_k3pqqht>2VkHReE4z`Jie%F`jzbd~UDN__*jfXr{;Ry@M#1Z!=fAhc zCcx(Gb$+^~(7`uF_8D`w@Fdi%TsWCI#926<7>FLG)C|)sJYkOR8SZ-@1=)--3g>_Dg zd9hWH1KtUqJBArqNYp}Wp4Kit@*ya|QPM`k z{F#D@C^SB14Qp5coUQgK`q#+6kBTDI^F8C^eVqpW_9-#CWXcA#RPyGVNbKt zu*yb4+i6`P;Rk&};@b<<;{_h8&Cas$*!HzRc}_o_NvrS!%IrZU1^|PwDGh@{00#P* z0DGWctzs$z*Fg?Z+}E97Pz8r0Q_JwHFIrEWV>+kUKuFD5dbeECK8_MSr7 z-BZ~+99K84dH|rJ$65m?e;>*&0!`$lsZ26p;DEkOIG=G!3#aR_raMAu-U4EkuQ-A* zDI53UF=ZU{+2b&>$tba3 z&1}h>E9?N#fPwpwnm2mOMCJ2N5B6x4sSZACRB{$qipSqFfR}K_=Z0TjAL5YS6{QTl z^>hO;cS;ToJ#Gv6Z}i> z=w0;0k&wl9alfpOUK8mmJ3=?u!`pzc#RbEGXbU}SG*FQpgR1`SeSdzQU>V|8Xmv^B zzTtoVlJ*ZeBTjfG6Es?d%V1;j_U*@<9PgFRp|kxxDCi}T&=Qq0t7)CdvprnVq9nxu z|8_k5-+ahu{XmEQWA9nG(sZVtlOijhcZKQ-|{J0gYl?qCfrCdr) zji;a(^e=h$q0=_7It=`H%%5`vY-U^`3PZ~9)<}?<&LkgPpDK6fTmt98UM*pN#@$b# zYJdY0)yct{7YZ}xMW!0SO-dsVx<@V~2+WUX7e$4Pfu|+(-`;sHWJw+1Kuve*-#%@! zH^Tnfy|4h3)V5e1HyEgBs5o5c?TzZ$jU?}Tpeiag!wkfsa7xymcPKUJsHiS(ZqE=M zl9rJt<|0i!|NGymjtl+9VH}_xdpDR;FkNeZ7Kkq3=B5ZP-Z=pf2hg?Pg?IDcJ%R4D1;^T|KOISt7^}Gj=3}9IJ zOj6O-U;}#eXoY?!TSiGu+4EAG%vjyOy0Y@&cMg`1ZNig*4JugEN%r8+D5ue{?!*Hcpi$1 z2JM4#0c{`THow-^>H*yj*d3ax(AamLk(28irPT7>!{IfMLFH${gA>}R8K+FIZwed= zrUW|d*{_pO#(Ae1}9c*Mw!tcoT3TcTm)Q5l2?@W!Lesw#wW}cS^MnvK% z$>#)GjqA&?h<3b$3@TqNoM*$4?j!k%VMabT!ByB)fg*wAilOBK2uwxh7Eg%z?4mO} z7>;kT8hQqb-@JW`cYXo7&m4AtmfXC5H~p4?9g98)M;(uVSCXsm-?G#F5Rn%YnkM)> z87A?tfcvt)cqs&8XMhfv$A)H!zX9><5?E=!lr2~kHpy|0P4xbFvv1`&y%Ee2L9ab% z&_@O~cFctuMsxRPEgLC(9}A4{RmR?ny@l)!CoFF$yY7ghTT@-_Rugp2-8Pt8E#=LA~4t3FT83-Ulg^@bezrUP0BQcO7(rKQd*_G}M9@$Hy?NWL9BUuF z&iyququK3c!9$Y?(4f9Ll+kY@JUH#kFIIka)u$IHv#XD9Q1g0BtON7|~ zmgY{tyl?50O94d_tJAD>Zb={d<^37+56qFh!*#QkzkhJ>qRP}O$ymVq5uFcA5%)aX zk8s3}!=G4iC>R+U9j+XTS#S^rznRK1u6No{YQl*wU99rMA1kCcU8EsRn4(H#!U_6W zGZpu=ohZ50fVRdR$dQ6srIHj?;XEBT%(UggZb~De!8t1HLK)GTY5Z@KS^W~&g{!vq z#&S9An0CgCPJr*_*!Dq4oF`p){cbY{Lt$lq`W|NI4P=JHAro7(*0@FcYa-G(0DWdx z2R=Shj(l;nXNNE6EfD+U6S@*R@3Ja9fO(snRCk9eRAmtlYd_~Gn!ZS3*nR%qXdtEF zQU9c;G?znz$2&Cy;u~3U@gZQ%jWyE!dF{(Eb*ZHp#Imzf7r*;yqG?4QUj13RgUS=3 z&R3@43gxi&_X)`gj!n8e0zQ*<*z3yuv^2$nRR=W5X(G4xQ7m380Zy6KQs*rOg^4JD zrVtG{$}ehfpH8ALW&Q>AYUyKdI$aKn=!_seE%hPyJS`*}xmOAHU8%#1g}Zt0<5dPc zFbl=AU-rmsvLsEJS?1Z+Xx>f6?RcghAK^2S?Vv+GU~(7w3GcL?MZi*B+FQ0ODiTm; zs-6y6N8rWrNG-^{j$+w9;pw6q_&AT=dXiHW+HM4Qv%_=Y4}^a2Rd!Uy6a~XmQlGJa zMr-jWtMu_;-&@ReaD79&Ur0-l;c|V>AJKUSRMtfHgSI_JZ=bGn`2GNn(9tjdei%O( zX;67t#f~y97+%hm=7-M-m~>y`23basrlQ7ZuDubHw=9R9wdgTKO-Y~`HGYbE$ZjC` zrYE)tA(FvUvRgyw9h> zwbh+nL$J#YE(sxmrvx-?AbrC&i;>1stWi=pG?u?syxT-gcch|k>Nxj#nP1^_2n7!K z|E`3YiFWZjM_KH+PZ3Q_NhO4s-RY;4g#E*w`I*MWb$4}#3oCJ^dCu$MEgiU+ROG9& z)q-A_J??Zs1beH|cUh$CsALpALi~Knxa}AhTi24S;|8stT+p@3Zgz-*+3JjR<34V*|Ia2{Lp;7Eq#Bvltwk!owL^-vN6_fmS-!5_Xa? zyBGkNc{$FA`o)1vmMynSNtI@OHlp&$|A6Xo_N9VeN$u?lof>^)DIdOAR38(LgVU(a zyeQ%1rRz#+CQIjLIE`)D$n>48RiLmnu}$dpM1HMuP{hnr3v;*4;Nm#{iWgsw-P7B6 z62!;+-R%_bh6+%D=`$pD2Z_dsMybrq20+r7r90)(+?CnY?G2ZL575o$l<()O^7HU; zu(Lmk5nS}^p@o$C52SQxu^?lPuGhch@RVC=)po0 zDKlh`SfIiuP0+QBrktf>V7Pu%cP;dT$eVxk)AcDs*K-ay0RRf>jN*NPC;I$@Tq(_P z5%!gUmRv4#X4hpHQHgs8{Pa(g~$e{6bED2F>UAb4@V<))I1R}>~BI{u-ddqUl zhM4;7*VM8dY2_c}b$#|z*-&8>oZ%t~kz}$rV;LmP^x4@Ats1`1AWF9H&Zi+%&%b8_ zZ0e_p3&CpfxjTyL2XT~(gT)q+-}?p+c#{F@E(?$mRlF;sxI>q4d1~oax)c;gQpXXpdkb=l+qUf9Nb91e(6v~xqslu zzQ42-KK;}1r1Kfz7r|NzNjQtEtH$;VAJ=hzHG1Wx=;=kj1a+wLa-#tSH(m6wfGup% z3nBeSqLXz;&TSvg=#`5zAJM+c@VQk6jBna-Qk(g<5?*f1ZlNC>eFUo~YUaf|Y~v}3{M%dT>hJ0C2==o|p#kAX|sk2fGRX3Jz7 zkOu}Y3W~Z)>saA}HABoBxGVJEI7nP+ug^u6H3%~-bL}FG>pz6ksuzERkUxZmxBFkx zE}tD9+RWS`oNF)&h)jTIyrezH)tdv_bB}y?Uf7Kd^DGP=#eE0kWB!OmenW+3& zuK#Xpn;_o@8toUL+{MRJ#!Zt8C7{nJ|4?P6HklkuV?j^@vM&$lARbaz18sj0Ny&R@ zY2>Qn>s0*J68`|@e@NDU$cMiNNOyQINk*m_#7%tJfF1V*HRu0JakUvo)YkUc92OcG z$c2YESrmYWpt|0RFT;UT5j7KVYmw}>>!P^YA8T5Y`4M>QwD1pyzCr|=O|JgVy8$Hn zlUZ%SedIutGZ&i8{M{L7b?RuII&OH~26F|g;p9M10n zT5Fdhy%hb*Fu0_!Du)Kh4BmhNxTLOvL~53BZ~rHJR)JK(2R{GFa~+{f@PjPkL-gz; z7dm`EPfT&UV+o$@Vtmck4EZ-Dou&{QK|nUvt=*T+j|GPqh)e+;D;{riyl1P6GAv@N zTCyu;XQo<8R~IRp`IVHul2W>n88kE`Szq^?;qY>rg|t3r@vCm-D!M-9se(qYhWCH3$xV*(Y+* zXbrd|s|1&1eN9cFT*4GfKzVe@a}kzg18W7CO)m$4B>(>P%&a|oVN1bBaO2?TNgOk$ zUeF{1ihXsebsJ1OFt}bM%jN!urp(9-Hhg?>)i#X99E8=#Z6fKLc@vCweCPnudmdXvc!QlIhOw*<|24y3b;NqHGPS{O(N(% zSDb-6Hb5*DS#$N^!29~#q=&U842$}&3>^5-fHUsD5E*0k!UwoH(v35JnG8zMz|Y#* z_sCsM*ZT;Ws~{_ZL>klX`&Z_r2_isls5mw|uE7#=2N1}kALy)((YjS-vn|rMeAwBmaQc5eI&8=WKZG7*KFZ$%NleqTZGl}<@y8m| zZyn~wMrneFKE?z0LOFeo=beX<+WivOG(iETeWFhOSeq*`2}eg0xJS!Nef+xA6Mg2< z7SNP8wr3uGM;&dCg}d%!i^Jfi1~UN|LQsuzMhOBtKho9{EMCxPiD9W4tHK*51m`oz zs9mLi&mdS;2zn#|d3x9}9)@I>BKQ#HANP9%1bxOBu?9e)xX%BFQN}EK9ek%7!f>Ja?g*ZK*Idd$MQ?!7!Tv!*S zz4%gQCe#{I5~LkD6~05q7E%{&dOo4$6;8Aih7vJrARE_S+z7xFi)0Vb6_%W|t8;Z7 zxov0h&pdT6TB<*#p`X7y-+%e0`Hv25AUAc(v5ejSNNUMu)o%<$B*6}{$mM^{D1j$l zK2(0d`ceZS%F2iOYz&rM z_1=LHvqszMWlL?f?WKZmefJU)S)3-$RFMuk8RsA{%G%K6x zF9WLRda^DdfoJY$-Hpp6A@r+0mmPDB`l}#FBH+=MVgW&TW8-I9&0cF@>eiS{?6Iwg z|2Y$(ersP}d^jb2dPnKvw<>0T{Ym;kWi>Fu)C9glpu{)?jupg{*=uNkGhw-e<8($GBKHc1#bR@W%Xhulwl)q9tK; znR~#Os_R|qmFlfLTO57HkF8btuS99wZ}nkiF>+VeH#x!FNxd<)bUqA;0_I+TrX~lz z2O2*Ii)X~~@1`bB7i;@t6_fdI&&}`RewTePz#3Z>HOx8cI(m-s%q3OSn+}W7?sAc+ z4wsQhRtk~KXpt-5uOl`v*8K;HjROW%Lxb1#d*lUaPY?3?w2RH0@Z;kMMoL0L2J36H z@4tU7aD<`uml#o^X2kHw&dn4ShUBIfy?j3`Su?|IBr+Qg_-K`lC(E@ximWhRBA6NZ z%#Ve8!!22^qW@t}t@S)8i(DP)O-2H6P!|QIprXLJI_6UH=v8(o22BA%LP9`tLAz}` z&&z@#l_G2!Qws;3D}QrgV*l%V@i2gV_JC3IB)B^K2T&rKxv$SozI!-EnG?j1-L5=% z@cOmBT81$-~}He zUlb(w=k&SC7>9&iH~aIkpz3jGhNaFUA< z^C%9E56=GsS7S+}Fj)OT)y%R@HeV`W_%gP=hOg?Ad+}VT)6OxXURA3lxIf>w;VrTn zANm)@UgbXiE9WQS6nudI3jj|g?*gk@gNYP&G0_Fb=JND^en$`vDKQ*4m<2bfL@C|g z{;IX7{8b4t8P3%DfPFAqngJmXIV`Sa@O=Bt1>_;59}t}23Q>S=1)aiTaNu(_m~}b9 z$OS6ILg_(pqV!*&nTx`~q0GqGI0HmHqVYztDbrE@(eJtZv9&P&2Q_%QRDgb8I+*_Q zAQYdw+xSaSQCM&9C?Zd028eSW{Ca}e4!gZB|KDj%ypyq}I|JyJT6(UMZ%m{27;wn! zXKOH?qGWF^1_NH^S|GZxf$%4S0&&W zLawj4b*4ZQ3l|py-s8u?-PQ_(gyYf-c5{s5)-ZCiPbRW1E{x>g^B%hXYBBIuvnUPh{8Lcg7_bK$iaC1mvW@tJOb2&B4xs-*6RMul5^oZ-rB z)7Kssb-ZtMJwSxBSWoEPQO6+jwO9=Kr~gC|mhz8SxazQ{A6y8%)-3ZN3;^>DbARR= zo}N(rL6>rAu=ZlNPirCr@2m(SJ|N_~?xbTZxBv>0Ve}h>>tgQ#fPBn&Ek`}Bvi zfj7=@ai1H$-Pqb!lNHVUiAI#ckdPP}u!nI8c<()tVkvhYJ_Ya2_;opas9@%5-W?f% zN8?{WH=;2-BRUAo!INJd_mMeKeOZOF$&U38lLQB&9C!o~uuOpWo;G*SIrt=FHh^@4eRA zuN>bqmx1QBTXxd#=JiK{%U~FZd>1aA2U-{1jLxrue%>GTc<0&Q_4tu;u(jMh8kVF8 zzIwpURzayzS8oOZ(iSSJcJ-Nh$JN^W>f)p|Xq9o&4DfUj=7Aicllzs`ZFL@(9pP(O ze)r$WJ^)7h{x7)%NOsP5=JKX}wE!70);ZKrpfzN{g?b!}pGp?ApKkInwcdIAK{jt~ zwTMs*hT^<`dO9>HPX{^wiyzI_bo~DQHoiaCsABUid_*A{K>FeK3o?*?8fPYJ2FHww z6m8g7PN`2U#qtnSQJDN_ge6Akyy&@1q}ZOMsSeqKx82Kpjzy^0uc{oUp5yhv9U#iX zov1>zf8Fl?;yCHY4oRfd$Pvjrqpm7a0Ce#K- zpbsH(IT|Kdk@YY2PSIcL9i&RQ_;67eTJ`c~6EgJsLmS7Z++j@4^BMXLvS|0PDotgJ z02Wd!G&6SpXPNxvm-eXU7UP;4?WoSrc1xp7f1Svn<&v6MQ+^W^)A`IHw9BC|Y=!*` zgq9GftH5zFiOXKegOz*p<0cF=Kaj8Qw`73ozuOJHpm+?t-E?U0;$pqfOtiT@rnn&a z6vVa%q5NRrk!bANmuyGSdqPqIyPqb(R|*NqeR_%uvA(NY0dzbk-RTAs2i`l5`slJh zyGeiZrfT_m<;_nbs_mQgG+mL)3rFC=1$yDnkfqQ)m5YaV6Mjg6h<*$Y^05UtFfrE7 zCmuML$8+{UR26$ZSa~zOJt4rm0s_2t$Wp}bzg3k|7eUG~X(@{vGvjLbKg!7!^?vSz z1f1u97$%|qzQSh+9Cw8YEt&9-hF+GtTT!i>PvjfDP83})@9PoeP^_&d@s~u>bk98O zO3}x`WyiQBXux$5AL8Dd=V5voDx^VIc>mLbDLedL>xxvpFQs{d!}{`vBnIt8LYa@| znsh{kGB_oyZzyY*!I#WjfdQV!q__JlzmGTXD2_!EA5?c`=~;8eB6|CPUbaD}1{VWx z&OS#q$+}#Fszxhr-qg!Q4bVnitgbbc6&OA50C(Xhz1xvH@r93uIBhscKHj*@S>O$K zL6yzSA$Tyb*`8~7o=i|p5?OS&`P*UDE4|}3KHfw$Ia-2R6fbdC2*_`+Dt{$%0}R$* zK#J=qo^LsQNY>>Qy3?wN?9<=3gKYAjZoiRTjNYSlN6_o39cD-|3n<_?F3tCvtmNMb z(d0h@4uh+j9CJ~b@|B#fd&%f{Q9L%&XMpLIV^&F==5t~tL>{VE`bjD+HYrKU{isO) zp7aHb+=8=VY*H_$mg(?MVsOD4BWD-paP+-+hnb+OtaR07AW38C(}2f zH4_!9yWCqGLYPMuiDR;9sB(ErPW!Hl7<0zCHJzm+bBZnc8^*VZpFVd21;N1qr}W@) zBxf?!jzudG2ymo(D2u&7W6hPE0_ zG+fywsVc`;MEM7kiv(l9LAFCI7eRjV$l~yuK7^*>ty#&JUd15JV=3j!Qp;D9cgl{} zD(;kgi`#NpUT$9>AbWNlST#Ar(-o%V1QpVgp1%**cHCzRWePhYz56sZj4Q7BXVA>R z-V+y+hkIdg8Z>j8;>5+RkKO0o{e7bjjGsS=D-Z0Wi{)NP^(DgBML&Jat@qQOL6o3H z{^vmF)W=$GJwlA1dHCF}LCI!}R;uFL<|-pHnfv6pkoB(@;&pD_`Mt`dK0_fRy;Jd? z$UeNE#%0U|QgPIqbI?r{(IC9N@mN%4cPBOGv*X{l17{ic?Z^8?`xcyF#Az}^wu-{8 zd_!jW?*YbKFC^~KBbkSz6WLSbAAY?rW45WCS5y0c-5HnJTK>UR+N%#UB3ForT(HrK zKD}S50w7M8-J4baPJ4g*BCf>aZK&%tU<4R0fa{Nzfv0%O2|g^q;ZvLJ>2YD)E4KlNt<}rRDWdRPlXW#B!pcbdVe-QMq;UET zLiut!2NYnx&Fcmko%J8aw|d&^6i55^FkimH+wyz-%1X(hY>&t2;tV`v{d=H70=&Ue z8l{Xg4e)fBS-8xbd-LzEXnMm;qL>r_FB}?c4tO@tJ@M@S2z$E+1d%FXjI|`kIX|nU zCt{!$(uvSXJln#PJGWCzTlU&IfmWN7<9%bJu8PVBK5rENtIu5!!c+4 zFLxbFDEJysE*oAsiBy>o6ltv2E?YcFt*m^4j0#xzE1(YZL6(GS!y1(6YE@~f4&s-v zTlvQ}WG-q(ycys(@GkeK8tj42WNg6|TyBKfuegI=1GaC-Xz1#9s@tS|^#-w^E^)Z9 zAnpC&dO9S;(+QM;DBxG7d@B@N?vk<+rlP62xw4Y|qh)PvO+i5cC|`<;idO%DAk|V3 zlXuD5f7)f8o?A)TD=J?;@_x&*BbB>#)9L-!(hesuT>?;pWRFIu-&iYYesfU&3hK32 z2f2f2B&8O2FRX>z$n-Ee$65kBB|^l`?k>}#N0UBaCTq)nI~D>nA8xNH5eP$oT^tNu zH9;`*2r9kO>HMKK9<%r&Zu*;g*O7Uu96uzkoDAGF0U6m;krpS6h^-NrT4aj&dwP1Z zx7{60{FQ$y<3W0R5e9x@8(!9goJ&ukoQf@vH*+%&DKZdT#=d3gRnT z0y7yOJg|3m&bgVZb22|#9|S~xlNVmKMex|GN^`OwpN`#XJ$$>`C%jfatQ=!6FfZSW z2+~LF@~gRQIzW_HUe3YE8P5(HSMJ){)4<_!%g4*p6B7&TxfytmU{M(r(qnu8eU}D& z1?*UYG7>SYJY|gzk;I)=H8a&+i3h?5(5C!VD9DG+nS0BWaEjQZR1B}2f|UE*;Tg$ zEmC>{na$RJGJ&hy@yToSIF(^z)5w63;FZz8P|$t8uB1_rP;e&w@ey)qphpmC%Hlj_ zz87fS0^JGSMi?@_ql?Sl7`ny=w3Sa1fpm{?%qWR=h(Y2UL{C~)qeytO;f9=QJ8X_ML+5#+?q4B-!@kSyXpqNG zezj~2EEbE;$z!3Rtq62}wu`vd`|FHUl~y~VGAZD6o+RY8PNh7dTgk#W+RPpSyE3pR zoVw!^fD_DFtpFx_T;}E^`(=Ha+%>9sUtRZC6r`(LCL|^XRs^E5V5qZMI|CoCWgIW# zW*GX8I1~rl2tb!YZPpw#P6j5tG^Akpc-oI_WO(A|fD4+K_{na*5##=FDHBM}#m>`| z?#4F%`wC64&d9V*pm?jOsF1GjpPZZw2tYY7cMj9_k|W(fVW27{@#1C=IS0#i{*62# zS*Rs0J|XxDCG_`oqD|7#eCIZx=EhAq!6?Wuq4HS2_7Jw%QZwFOna@m+J4QkRd5=+#u!l@}_5G!uzfPmP>@I_jPBq zXg*WBPb#+!?0d;QB9gq@Y<+`QD~5TKL~Y-J15tZ>NAR~l-;N8DRodSWrVkC`^qDW? zz_)3$!cSyC5yZ+V5G#K_!wD0&d{kztiQw|5*Cy$O;DAL=^4V`&K(%Q(S?ai~e)$da z`|j64@#V0OEX>v@)1XC#aQE9ltCGf!OPS8|nZGvy94D|3mHqE!{IK*AwA`3!XQaAS zR*KouiSZXRWt3V-cV6jjr5Q}w>B zmJku#Km%kjZ_8k-uJ)AFc{L@C(HLDd!ToZ|ED#K{@IU|0@8ARIi>YE72cD;I8Yx>2 z+2pNRmmhVhD;(ja>Ebe%kZ#`^*D0qImO=R5L?(QD%g; z{E$Ieg(M;2Lj}0JuFA7!4`e>?=R}i$A_6L9bSFUGycnF!Ykxl<80+SUO0zDr=os}L zh3DkBz5F^bF(s(_iSwpZ>u&FptIrOVJ?Il+aGsM$I|B~oCbG8m)M%7Ft86o&LfHcS zP5XQb$j3DCcVN*zCgh|QZ`9wcN#MFrXL-9g<6=RN`hF!$|A-|Fy)wB9I7rwS^&D$q zP^^#C3r)?GEg?g6Zs;PE)$e|5m_?PB?}R$tLB764`*UmT1k4NCwx)XYEy-unGm0)8 zs(|-1L28vw5wqyU(_pXh0C`6TOPn0~mC1&)DqF3x9Zf5l)?3Qq6=LUt~8 zGt^?>J-+hS&2iqv|8@TUra%7e(tIXoqv)ccu*>UuRxM`cJ0zOF{Y`pHN~Krt zfP%#UJ+(e&-cC!Yz-CX$n_K?QQF$UvcOocuL`ARABsMy4c4G>)cq9Y)J-%2qWiXNp;W`{g$-g48uO_CX&q3_MXve|-QVs9+UW&x+%qzApin zGm9Q@Idg`gbaf%9yE?SvH-kKNXsLPdJ=gJ`*_(fD>qK_EyrF|}mO=>8=W!(cGSVcf zt*y=2SazwQ!7ylV0_NZF-or%Cts&E!gtRnX;7z~_12cwk6glAUx$~@zm2P}EYRJ$n zS=UQ5pODEc+rLXAe>17j{F)%URmjX#jn|$*CB;~;7 zzW%4oh`zBt3}rS$6D`P$k~csK;-JRVlXxVfFv;PX?SR;*=Zwc zwFQW-DS@Fn4Ng2ME;yo+-rAz_IHeeRFPAH;L802UWy+qM5lNKZ$`hNE#KaqnI#obR zt8_p{%4yo30ZC;#gohoM)5g<;Nw=T6d$ zD39gJKg>l?W`U)oAtKjt+s&s#P|Dp_s3#bHv9fp}Q;onz&l*??%G9)*pc!C}rtU8^ zWvW)C0K*DQA+(NZzIv^0xDNM^cF;O^m%o;&=?D6Fp48zUl_xNHDXIIi7Hkic-qzIA zyf0RX<>Tis$U#pYr1&$_?>z6F&3$K(8)r5?0Pt!?db*5^3|+s7f{>8VS(41V+MK++ z@0aW&M!CG@->Cj^Zz(gX_yY>*yjfH|AN_V`>r^%<9t&q>WMs%3>cuu@RI!|U*l;@q zj{{4kRB%|QDEzPYNCjG)dn!X_^S||&+0j;iJp2R|@Z(UzFz$z#zEm4~PV8`O_&eRp+KgXOwg^lJ1*ECydr(5WTPiHQmc>M&@I7JEHV{T7 z;wKK~-xjY`WxMZ>&&}!4vy{1UQYzE_mOf5@S)g+V_7L~GK~ycnuofe3KKV+gsF-9s zr`wZR2P73fOMx2%_+}Y=@e|pSc|d<6T?VLN@uj>LBTOB^r@P;Voqo)#@xQ!%MDSG# zooS{8l3$IZu3l04QQ4d3ei1?8LuZw_1`SNPSgneHqNOLlRW`m0nePC}iJoz|gbdPa z{nrf_*)25J)zyK$5`&oh=FOYY(b2cIQd~tjIbu&sBqxG)xUJDdxBo+Ni2<74phSV+ zfjPNnSfA7DLP`!~898A1RSWDei?=Mnt-f$_wFu_ z-3z%sK=;5BZu4`yxte^Q{i3V0*-J4<;jQpvRKpBS`78>_yYnjm3kBf*Fr3LGSi;b{ zS-2s}#vcGws^cFEk+wa6S%7=jJ@|~E0Yjr?{dD)cAH(^j2bc(<$?>wbYR7E55u%j9 z3rU$7Cmy)H6^uiX>&%2rwr|@TM=w+J-d$ZwE59InV2~r1E$2U0V{#T2_j^L+YAg&- zS2dPaz*Gdk8OM*WUIqhGl!tYEH%r0qi;Cz)M6TRV93_v%JVT>!>2H7`nAY>M1o)x= z+CPx`j!lEMK+bCf<-CGHMYVPgTq0iNj~-XzIzBFLYPuDt)lqE96W;_;n&rgi#pJQY)HXEC0xlaeR7;ak~l^o-_fpY#rnYd}XXq}a%toW1q? z&eX0o4)AeWa65WZ8JG0J{rLexj)Gb=bhQ;csQ5R)6o?O16q*9rHWfa;R1``dyuDQJ zIa$j18if^6xKxQ5(GWvD{M>SVz+lPphOrulxt$=i*ZmKzQJNemU2tbLdS(MdpVuyc zbS3cXwU(cvhj|1cN-mk<+o?c#4VtBIy zh8Lm*#&KqSd#Fq2&$Y#u*?@6}E|}B#0q&W%+!H$vhy?NM8-MGN#R3KP*;)pu*%ZN$ z7+qa$C|`WwP25N4?_a6kN*3i8!OliM2nM_Zor+Sfkn^qa{6Rq5GTDV(Igd|NMgH3V zRFGajQwKcTcGgzI(mNKXpf$srzRckp2dKD#d9WOUFpOK@JFOmr`HWdGI!om6eKDhQ zq2KKqeh;AHJl>*}9^7FN{#UCsg=<#Zg>&i>x$CL_tGA~8iLovFw}ot?w!qxxu9^EO zpMZR`qC!Q{BLdqPlRR0`#%^ysbcfsWLUjB8wi9DTo)v*1b;3T?95eP{RJEb-3L) zAR8V)f@}NyS@c z0b0YX?C+BYY*8zMjXZ5z^2nfP!h_a8$GE+-@k!gH<|$|EFLuakJTnl(Ho4e9-Xp)k z5?uwDiL2KAn=f>4o`rffKrMYiyLeJb@7*@mwalpdF zRCa2nzwOKAeVAL6PmuNzMDX}%YGblLe6JiPL>;_2YP7`J3qO8bRAe?GU+n$-dE=K8 zNI=?Q_p<`|Uu7f!JQytEt+=hmrC{$Kb8{y`l4ufRV(z~i1YhJig<_$w%M3e}vW+sl z?E??2gW7LWOk&8Ya0Ig7`aJ|uAi-ArL~gAl!lw6MKqgWmyBao*W(~@5CPv*6WWZ9Y zk6QxAWw{e0mFfui3K@gJv~C-WlK`3VU26Xu1u59|yoUxCMo1f8o2rTV??m@4(zp(dPgI z0;26*ZtG;ClUa^~XcnhWSg&ypDFS-U=0Zyv;GCa)r+sDgQ1&hJ z=r$p4&hH9^2RlFiTij2|{u0^|C0@T-;8bT_;Wwmoq_zQ8gYFh<)~TNGjRdT85|Wab z<}kG+&JFtBJ{-#fGoVeRO-yn|Bb6sX?Y6J4uQgU(L;-l+1U<7dd5$S9eK-Fu-Lv;V zbbk5sWb;dQd`rtI;AEAp{>2$m)=Z9=ilw~-_2VNj*aG;$iI%}dzId)XnhMKc1+{Rh&0d|ZiuY?kVaV{$QB`VraFq@zQcs-)BVB8KK`ghc_|)>oTSSDCC9~+vAzb%Z!L52dLJ5 z;gIqAstywUowu{3E4Glol+Jh7?QNo?u2-5Qfm#uWhu~}2Hx!k|#iXfkV+6N-(|mm) zjN-FZ(nCwbj?fdzYzgQH>XSLrwEQ@}PJcU;&GXEYqE^%102TK);37kvU_4`~D%zj$ zp1#BIIWa^Hqkj@>^&!@jBe7^1u-xI&OlHr$FRGoPD|g=&?yMvG#IdpMK_>)|$mob< zeDye9N;iY7D&h>i^a8Z%_Sw^s#l;`m6K2fx+hTc~W)h6j+i*5o?zm4?k=hg5uCpJZ zaw6w(CUNztGSd27n>-$K#r^s}P9HL1fDQE9EQW|0o5aQOC63pPmtV4_qoexXG?Aju z+U_ozHvZArZ&O%vcuI4)J)tbz{=88*!0`8aF=p+1Y6?|)^=qum8h?kjLd70 z;qr0g8zc>A$CZT6fC*LqqV%+Jy|QI%VA+}TSCC4o9Nf<>`)>NpsP%bmO2@zjO!@!| zCkdlVQKFF3Ya{c&`0!v^>5V{U3TU9!s$X8XcmN*?*M++XNsD{H-N>n@KP4{i3E%>l z51A~r&}}byQ>{5o@QWATx2%0OD2k<(1km`y2WnFaD^XUHrBy**roO zxx^fvYr2BlN;G+Sq)V*aoE`K6Sp{{@=&5T6;K<;J`hhyT*1@F!Un%nvBeCezUHO%I zAyx(fAZ{1X>;GL?qq_;z0LLT-M9|e1J?inp`)Dq`MS;KdRFjWOBi2lYL6TOaj z&jTb(=^Nq<`1+9DL$taTtJyzUhHUA{{6LdwZ-K^Q!7uX~SYmWNQRfGS_>}}WnRjKC zSW;2!#nceWK{uTcg81rPsM^t=J7p&-SE?{NytfS)0H(d83e>~Kq~aYh-<^hBMEf&x z+eQ#qX7u+|+`}l9HDek0=5hMz&5_@H5A$Y@tDP&y;2&E>NQ$K9&#jUx%gy6u)(q$A zcAFH$JEVM-Qzqi+Fk7TN{vW00n0q+v$LD-Nc)SN}2YOCu(1JuR}QO zAly^~@oUK{D+2I+zcM?cOoz6ldd3A}#CymB=NzCB8?E|A3dsETK;B&gh-7(+=0+HA z*p{P~^P(}-cCS|^0!=e+7t|Jol)PNLTGs?es#6+{pbrh(o9KH!!>#xghoDP(_eq-! zj(TLGEcq~NneSPz#jD%`4^mc@{An1SDnX*wEj54e0|0+=jxyWtUV|`{#x34ZSLFq) zcn}CPWJ7L2%G~(rQjRB)RNq1;EAKjTWEt4SpfK$`67~QSA@+bj0t5!c6jL&A5spy+ zn|Jw34H&3I@F!^s=kk;F_xFc~h5dR%;Ds@$5qK{b1TMo&Y&rGWIZwBAmE+LX5q$KU z8x2|5J)a)3!R@K9}V=h6oky0}(|%X=0l9nB(4zs@Kjp>8w{9||70nT8kYRL;1ej}# zzZ`FTv;N2N#tit^t_l$qAMIpTB)Z z^r%ymjqMw-;ObLX^@o%} z6AK;fr=f;PTquMZ?bN^GbMzmM0R?L7opwc&)UU#3Yei2O%p5JZ+~q){H>^UU0+v&u zz&*nvUjy{Y@FJ#MGjDIN*4ENeQAHyxH}&Cgao|}msX`8NoPnLylWQOvEu{m1J8D7M zpC5x4D>q0tvGdg@(Wp*j{yytGtuFB3F4wSgU~80`Z8oIH&7hJIF*P+s9@$N&29#4l z!)<^S9T&&1tP$Y@>Xryypl-Q@rz%1$!_g4N`S}IV@&KcRV7w9v_SSGh2}(D>p%W6a z1q^A(>wO!MZ%2&U$dRsbYQLp^e|H=s)V~;x!0mCPwR3-*$LF9qq|tA=04KKJaC{iR zan^YW;My+`fL+Yco87NcczLrmSdly4^kG#e?|$GJ_UN`P32Yn>5kh#^?l zj~cj&#{gIP-aj5LF)fXPkkBM5l@BtNEcc2d6>q9edZ3k$*K_85%-kJRsNKBMyEhmE zGMI2LnzXqn@u7C*Lr)r7bEK&lzc=W5NWH-m*Xk6BozQpmn{K2 z{mdWrc~5qo{jWx+oAcCD36n#?8m=YAj?##3Lp!5oAn_IiDr1pL<^y1B6f=kZF+ezK zQqTp4(w6{ggb#eZ!iwo(s;X~Ao8=hVqlBC{?>e4MxznW=;-$;u)*(GxhTF}f;kcs? zeFH4%`KH32mdPcC2fzLHGfoOu;|ArS2OB_F@&}kP_>V#k@cTz8$yl@n$v(at+yU0f zC|HNuHthkvV50mR?$i+y+LGq!6@VAvwsT=XNfZ(Ux@N#{H}o>(%M%Y4It30;52524 z;o6q1xddvgzYL+HUbCz-#$hFa2H+RdQ_|SpqgnMdXhFalC<$KvEJoX$n&Q%Ga>uPD z%F=^j!rgK~TMf=D7w|?}>pPvlq=;(DlphprR+CVJgV|qC{t^NHcH3u5=k{s zYDQ=&Robv8SUz<{o9?|%EMBOLY9FkZ!+{-Jp1YETu3{R-{j=j2Qt$yKxDYjFG7&xUVdX~HhG~>mW%psq9dzZkga(1v}u`r$jO6DAR z90pT6mFOX5g|{oq1b(?C62%g>h!^EW65`<-WZu-)qCGy69^GAEEt;)jdUriLGlSDf zi#tfitn3}P`q=O^IpuIx{Z~EIz-X!6fr3ZkbGHKUMu12;0co={))!~Wmf2Y`WlavS z95U7rFMH9yoR)U8E}tt$2RPyQSM*YA#O+1vfteGn=%^^i0p^>OwxR=y|5yr2vyNeC z`BxuI>#z(J*w6ClP`F3WCtzZ#3PR)HXMn_#d@%i!f0Lyi|6!U0rm8w`BG)2=VDL9R8RyQF%pDP2?<27dn3NEj^?Y3 zXWxy|ex7J%6_^h>z4^{Ov&ZRSMrvU8Q+NKyk&xia60M4#0%=+=y?#!=oagGqutvP? z;!vhv=jblo>vB!d-5J29$)1ux_ygLiPg1I2Xh_4_rs`Yql{zUUrZeH4Xb%sq1U3wIbX8EDX5ce%`Ov$h)_d3cxm3N9n_FE{QWC3G zVj>hl`c4~q+_#J&x9=70>1-*~k(8?hqFn8j6QnP#tN?YaN|{KyNwuntFOZ_iHJJWg zh%9sDj4pX_fa|oJ31&ZnEBjXjr5Em&gcKH?v3ln{Wl>Sp?G$GB`y1Wj*`v-b>Z8dx zNns8b&g6O4SG@Yj0))`z!!=r<*Y8LcvQEZAJH0$LgVA?el3m<>{7wSt;U3w&1Y$Ob{&u4f8St~Hy}eBX(Ju(J;m&zKRX&8 z+aW;8LEv}Y6Le3fn}_(duue_A6n%EZ%g0@|;aW=rra&ml>-FAuAAb;CtaGpU9?7@t z*1CdLt?x1Yp;EeA50%tzu3cWex|fOl39o@dseTUSvT$DUz@zJgLLo_BnSKt(4F7Pf zMqeKb8q?sWCjR20C4klI>RfHL@s5t4#&e0Y#5A7%FB?KYp8+GVcm8~K3zO+w=+c^v z*Mr9z^OS6{qbq=)`Ypb1x$s*ro^W)c;N>H+T?GMvlo&4aS%-f$uf+>L-eN8c{`0FLs$+5v(w>2 zF|-H0z0YYS>z#aPd$8D!QQan|rjB=}OglsTmahn2n;_00ImciKizt3B5ck>s0qGen zzx#li+lBaEi?D7q(nbNIdGWJPNTEzmQ47fV$H_tf(LDNeex~@7+# zQ|EN9p}%%G*|`D6kvw0uo~{(mm)%4}Ft0`I?+eo_U!{L*f`vTZ(w`Zz4vkRQo-t7U zLi{tHnXa>BIW6>>awRD(ZAJ2)sm%4s3Qi4wMEYc|T#&JQgAvXP$O|@Riok=#Swa=e zy40B3PuaQK@4c59_4?^HpozgGP57zzxSC?fjy5`Dv3A%Ut%R^m1MD1LRY`u{*xj`< zortDxw4)z3%A7FQx1lQQioh2 zCiSJ=ooq^Y{St=Q>1mpwq>fy44zz1|0RaIaA-AxPl#d~~C4GG|z*SvuoY`>U=}V)% z%Exw!_tNh2^AmK#9?stI35Z?yXIHc{3gSMxJouclPaNlok#0N)*AcN`qL&pwNY?tP3$&f%k{riJwmeZ3pfk%o? z>nKPsn_-6;H`k~8V~RT16zlC*gNh&`udGsE$12E0sCFo}Gdj5b@Se=-sNgh@VtODY zw$2DODI)+v+)H6V0YHw~`f;=GO4{!FSk!8!nrP?V&1>@Ht}_hPV2zhAqp6!5Ry;8% zvRRuM>E=R%RO6p4Gjc@AW%au_IvyS!6&4nb>Enr6713D_fvp;roX+#oXlMY#!yLto z(<z{O;uJ z5AL^C=(oH}he^`S&wpCv{JGs3IKN$i5~4Tls(%HT*U@_0`nG z!~_);6`1J8|HDsCubyHc$7V=NKqy7X<>sYRv`r`mw zVeDA74O2D8Lsr)JvLs9|zyGvm1B!qE4Mw?rtBLItaM-B>8)N9r=}qcUgXa2%9TEgF z0_;4PN}z_i;Itc^}J$rkSykj@$B^`pJet1;gyYKENuYe zU9!msY;5!G%lV6ocjWVf4^(XT&@4;nIJIv~oZ}jC;Z`C${@niAF9*g-&#myYB`qZg>-8VQGtG_?a%PH+W zdbd2D(Bzg)jNEq#m{@Ks*T?=(g@qO6iRBFLa=linC@MvW)6 z{h^^PBDErvY!E`0;XI9Y-lUWQ5Cj^^>++AK=^Wnmuf7u^1RfB`9&wdElUE=oAn@KE zXMGHLSS-@^Orcqgoph}O?*@$1L2Yt>dIJ=K>7EUf*H^o56Ti)t#l`J1f2ta3Z|~-^ z2qrt&%2~~GrzW{MblTu}EvZrRuGhz!@arc|%x>P)F>cgCqxsxf$`E-1Xq8dqUb(D{ zjJ1so;E1P9BBnH2T!+d%%RW(*U_7y5uQw6ElD^AAerBlgiO|jcr>m3G@yRQ55ipp_ zCMZ0-sj$$?;jw!}@MB(JMw1W<6gKUzHg^l_@%$?ggvlMM+$z^Z6+s z#v`qUJw$1(H2&NHt@Jz^M7#$@d=|`K;VCIO1NC8@ur%-F)&5R6kZ%BAzX!=dLNB{g zM@_%=26ny|4}UP}cP$PxG0J7}7A=&Mk{XdwqdNg01oN z#d_I7I?xSJHY%$g1HM0j0~jFF+wA25JNSIrE(CdKdGKCbg?%4PFhX-~?+qqh?Ao0n zGDrpF8$|t1SPuJ>aK)@eINu}3W}e8&6XsAtJw{8LK`n_mBWb@4_+bBAw0FG@(k*D`Axx> z9>LREBD+&&R}w>xUOG@dVhK2)-ve&R#O#4HyOysh&-7nVbnxb)al z9JsBS52w3@#}jl^+sG2$cO8F#XRp68lt@Na_E(Vrc9f%~xnBA|jtxAE}fcJ^orx++ZO*(%S7Dhzg z!NC#V`Rxt}Mw_OJUWNu6BowUqGX;fNfHWNn&ZV;i^&y_$=Nc%s(FZUV0`IU0c*q+p zmbUq4uv224TVBKNH*3R8H`cDbGr67Cd1DCrx5j(pO7=nM5Ef?4d#9%6p``#ALgyN7 zfdEoV8f_|Vz$5t^)Of#$oez(V(R>c2i3RS$Hqd2sZ=bL{r}Zu%N%UiujIu_&($cP; zDL187!hKeI1~su;I9VTb4Dv{aQIlT^3ZuaM9U|@LWM!&X{HawUIu?u73aNxv0LU>? zN8aw#KsO1qYI}TN{ex1zaEYL#6Mv=w>iSx$rxOAu8W&C3OO508!PsptV*Muv^rJpW zgQ|LZHa0f$r_G{Uw(PXt9FMcl8MEUHxF7Ezy;=Wb7b^*jV`vrbZ~mlc~2K@Sdr98O9;a9zJUJg zuwrT}2ZGU5`N&fb^{(!rRNgNXq?I6GFZ5~(4N9mD__lAV&A;Iw8ihe+9I;0$w`%cJg^5Ro354!7K`qq3CXR{B0 zF)&!(BWM?iyl3d~g6R>G=-T>vIm&MC=aexRfi3sQry3ib(GYutTE>S=Gg)(on+sFx z?x`LPh8=Yh(bt=F5aAXL4MQfy>7irS zgZ-=1A8$zQjbSI>(AjA+g>`j1+XGc58t)RyS}6uQ*$O#q>U0`@ROO&c2m1 zYWQa5LBWqu_#GKPwrjci`Qpd?T!0gqmR4CUxiz`b&2??e?FE2}ja0k#2O%vTt>nNy z6>0NXog7FkcyZw9KVD>g_Z>Er#Q;nTu5GD~j2$eACNlYql+%nsK8F!2^C zR<@>EUi@Be?5zHwfq}~MawEuB+AYzbZp8ue&x)J$4muy^4!6&x^J{Y36rbGW@POrY z!sK!Pfh#L`CrOjMrtS$Y#*fOB9>T;r&-0#4kt_COT#EHKA}AfOa?`9#KX@>EdU2bO zeI6MVI6(;TPhCqf6(8;8EckbMx#;aj`bN58w|-sjA(WPz9p)is40Ej*Vd-KL@*(6h=l(5tbHQs1vx#X8_~{WSuy5IOWRrA zP|oWO2&pSoJ7sN!-2&B_5=@&U{nkB#{op=7i`wdK9iuCF>e}JyiDtkoX>_={RLcrD zB-#&GF-wqk_Ll~0JuNMnrl`?g+mp(MJCIs;a$7xMmNRh@d@$D1q6ZJNmUmeTAAKZz zm$YF~tisL+Ai@G=>%4~@<517n>B3Vj&o7-xQa5_l%31f!`?H8yv^%ROI2DU^Y7|H& zwxgh*^w}sN^8_{ghK4I6Jk)n@FNO*L;?@v?41>Zk+MZ&{a(LQ<)rymxbQt5uMIs40 z!6aWP`)?r((LziRAJEXE>d^(6tFw7L!+B;b&BprRVUj*oq^$xq!AAQnzb9#*Bz5+W zJP?CC)v0Rg9#E3+F!CIV0ev+9xeP`$zFQX#%A|%`Yn2N zJQpM|xg2u>b8aNVvh4AwYNB^eF3v?R8)X9{O|hVZ*MT;j{l_u3=xSyLhDH(2HhvE5 zH#-XJV2f1*JIL5=(z#8=5;z)jv;xm8D8TnJ_I81)f+VCz^J%E#)l@$xy%!NBexetzrmB2_hRqNUx|U-om|NQd_FYIDO0Ah96NzN=^=C03X6OY1eez{nObA zx0iQ7MZvbTbawMBM|;WQ17Q)?y7<-gbtJap$lKeW+?y4F4i#`2IctL5C3tS07t3oqF_qR@JwOP#51le7J`JhA3z8Ki1N&RXz} zU`mER)Fc@QPg`NtD>@U-c5e_%C)BH!V*oR|mR9}h23;g%m`3#$n!pkM6Dt}_F#y!d z02ajAGGjh}jOve4Pa)KiaXr`=2dG7Wg>43kN=_RJC>fbtevSaaFRcf}->fcgexb_& zL!ygg@=JX&22tKR-82vMZW+qmev2+zR#!HbH)c})6mACA*2~y)b3XjdAq0i-MvDnS zs*OIYhDk%g{AA$W-CKBF6JHymWSAt50HR-JjDIrS5-3L-zn{p%&Hc5#9j;)0gnpb0 z8dk&>stu!hPS*gMf#qy%CD15IL`X0I)X_W>VY%DaWwiI>{e5&Z5Z za>}=>M1I#x21bB{_Mu8HC?ck`)<2-2pwRQgv>IYCga1oWm$)|{aZ+>cfaKI9Xh2a( zO^t{V`Zg>oihKS**!4(}jv)SP3msj?b|?dOK6oc$5@?0)V4%~7$jDb|+$_P^4!|eK z^=+b^(rW5V4U^dbsmFnlP|IVclt&(K&O+q~IKx;Qs;jx_=uB37VwDAqG~cgV8|8L& zOC2d*JXe{{w7*e7z5F@z=0(#x^8*n8wkBIzGDZ(;Y%`ElEnnAz%0YFnm*ym|-j17* z3K`SsV}+x&E*P=U??`4Hl2ao%N%J z5er8ig9tN1SZC+g4kLq*kP!Ay!S0nH(Igl%G9LdzYaI7xyryjvB(Zd_D$C{b85NFg zXR6gi+nJ<*SPh=8DHu`MXF#C4>+6~tr-)4FLjvCe*B&b%{+Sfo2!N!J({@(LeB*_+ zov+8~qsQyhQ&X9M<+rv^kqV3;DxLEcs-He4iw}Y#$XTP$+BNenu5cP`Dw!w#*tEDj z8vellwCYhU8e}QFYZM*N7GT(#(HhPejV?v!@207T5$BD!3Bx7e09O)S#|e*yt^jxGgij;>jaGR>D+_R_~EauF*lb#h(HMy zf3?4_<>xdu35kb>hDY^}9~lDX0I#h0*clsV#FnLIbPfMNh2;g~I2r0Z2pN7)SVOd! zx-hHJqv+;#z|68rCn42-o(I0e&LlkZbWX;Yrh;o*VOZT;Z_JJ-*(;1$>8l(t2O2J} zs_JU>qr_Je|#iwn1~^?_FByO5>SgbkG8AE`WcXvS%Xg&TPw8J6%13=FMBHs~6k#R-8V zovBD&2ac?U8##lM$C%)GW_)@&Wjw~~jvE#52Vg*RQBe^L2J5`1bnknL^hH8-vnYU3E=YOUYf2gw&7gZC2+sr|=a+c=uB~a5-PBNcu44R`3Ynp3r&|2~#mfk7H^kdAfWYjrZy|NMI5~;^N-|1rowmT97{&d$(UB*;4#aVX8my-}P@VVvm^>uU{9Y?vY*LuDl<9wXw`6T6x6&v;RaC1}F)U?*uA3)&5 z#YIFIK6voJ!Xh>$MF~Kn-|1Mx)XV=F5}G*Gb|VcqffzzO>#DNk zQlZDOe`ka$G z(L-|cGQ!NF2=DCX9dqrWb6fd))mW=@#9sJqb>|a2RTb_4lnprc;w-i6UC!~iNH#K^L> z=%)}0mm?@^q-}W?KbM`~=h=dk7ybeDYV@W4&mR=#_i{k~LqPBxrdvqe+fytgd@v5< z=H?#u)g{7|H4p=*GJVX_1QKo$;=c|;$%qR$U;BQExByA4MN1`|IeO9GuP*!+cG%q{I|_0{(A_f_u)VD_+^$)e zvI|9^OI%{LSX$hQ)f@3-V-sOqhvBgm`2kUb;Ya$_Bg85u{5N|dtdA=!)mU5a(&FMX z1Oz0?f^0Gio$->Bb6)rI@in31Jc)g)tn6#?9iC@rGIlxo*{)YU^ya#bR(sbSOP2g~ zuksWWM!#d_-?IkHS^F|NFu&Am+txQg!t6&$(BT+^Z3Unu>GW z^I?5&>1Yfm!O_n5Cm|bz1?-)9pq0qC1i>iqkzhK8nl_;rAo0 z?G7D`@ute?kzG%IEYqCTa%4P-&|Sky>_}b2`&k;QnV(R`Jc9S_-6QMP^DKrfegpyc z?=Nb-PSRH^)$35kfBHq`4J_|etYgscf&KW)XvWr`1L4K>U%wtqee@JKgAHVQ!{xDx zl#~OZ4{-2tIJg4`cA;?5rY&CiAO#VfsKS1gO#0fIlf1lqUhU@~>jw{XE3D1z9G8Mn zt?E?pdSqsNP|$ez#Z(w84tfN_T^Z;EYXFu2{3BuV*|p;L*x5}VB_WRb&3uC_Qt`+m z-iAoU1PZ^E4;2qsl9JrVsfx%iT9SU^I*+;Q3^Aru}Br zMg2D{?hGp3wgIFc+5#wGe7cQ0cp(UW-ASF^>yvEMX&c-II z6I)&|JUslRP`At~Cn15VEa6%23zYMPYf@H$q*;zCq{dlic7vWZ{pf=GnF{jK_x1zn zKOAd<;>oDL*F0WVQ&TI~pq34#xK)Dd!YCbfs*;(7 z(W|F$3?y}=A$5F3dKsY_L6PyJR5m{|V_)@89HqT1Ec*&tV3$1mZ*PojZ9A8@I4cZv zqE{?j0pMzGf!mr3xikmML{RmAei2-kX#$0SlnMDDwigEn$LQ#2)|TW0;;!q3+GVG` zb0e&V^HC^g^4}NskF)q$Dr=kRiC56#TtOGpkq;<3!=7F^}9d-5Ep;ObofJi zb3OVOb~EeQNQN*UhOn0m(=7PJCZu}TWnZ#S_qtbL%4~?2*;T$n^*9a1B_&4l@7~?K z7EpfpL&oMHx?lf?#_=~ew2Nm3eoqZFIliwHlEB5udgNqPtMiZB@Dd*%KRqKOYfF62 zcmb8UC0^8PdGJQ`WV7WZRL~84;*8&c2Qwrj$!M10by!_Mbx0>PbAQ&YkCURu#w<1n z{WT27QvyZ}Ma9s092yp$o=ZhLhuvkr3MOex~5h$RR-_>%tdZt+-c^%KbAa^qYZVsYKvlAkxFu>b0^^TEQG zgkUFAuKZ9ofR-!1hZ17Kix)34pa0SzLW5R)1~6sQ07JiXv?;bU2!Si9b+aRQ#d`RH zJ=xeh^q{^loA<%J0d24D{D`0EnRQCUyb&W7bo**g**i=RgT5fOqD@LQRMhTD!?voijb-Oop_y@xUWGuE)d7gI!YHe*wTc=evB*Is8f>Am7CKbxDE9v%D z{-x{0shFGGv&S;uV#C|W15sB?aY*SlO)}lL^N_o6)_~O2N9R>Tv>12m@y;u4EW)UI zd>ovh2^L3L(G4%;A@iRTD7)jBc?g5Ytjt%pyI?jmnePyb?Wc&dGw0fwc*CcJE;9Fb zlS8(US$wT$_?-wx_Cn|>2*Hnh7nw=`lVt0U!FvvgCkqoxG&D2C5dowwZ0GIR zq0AO>b0AB(r(Mz5qS~#T8-wDXs!E@7u8H&}qs|DsL>b*wT2jJ;Dont7zJU%4S^OQ% zC@Cq8jEr=OD%nQx0y8qOyxrIv+`M4O^F0S~bZZoBWzc9vVVA2GXeO? zxCxyy=#9SB^75A_aks|aJ`}2x$KspJ#%`E%z2=$3{l2yB({qcuT1gF?8!R|Tc7Vud zhV;L?56XCB_&SdsJ=zB*`7pr&Uh%!VcNr_l-7f+Y0uy8Y%EiXW;W`A2skcA)l*Mw< zVkxh5FGF1|3`Gfy(0P!=v84X5H3D_Y~Nvp8L8*;ilxy~|~lIF5JHzn6K!$v~>ibr<2+edZGCc^-^}%EaBJBAE%nO-0x67hbH-bkI zwpva4!}#t~e;r2bNo&C6enj%f=1xr+ul$Zwn3q`3zxO;_LL4@N(u0Pak#~wkgcUZl zXJV3A7@%r(fjvBIVzKpX*gv0%jzL)-$`V1h%~$pDHhk1fhis}w6x}CXRT{>+-dBMr9vZ3C(<{S+Y?`FVmJRYF1DSTdPDJd1jC?HfO@-K zBqztk#g$*ek)4A`UVibKf7Zo+#nR)?U|tLUBZ=%FDE*;mgud7sDusJJJw17Od1@YM z_V5y4S<=+SGI`-IbD>4-LW|smwP?I1M;->u@^R*mJI)0pZS|51s2AnBwm2cGR1A_d zxRNv+lC8?j=UYAohCl!n508$I&)c-dAWpeFRL?)BciK|WqrFJR;+L+5FDt;R9m#7}ah>R#u@6(35}@ zU>NZBEj6hfOOtNVN)K9~Zab9|SI|Aqj!8~dmZwUHLLVORp53z!hmhq`NYi4<8=>-h zR$btH1nUzRs)K29DBsCL?Svx%4&naktK~B%q}P?3=|B7U`QdbaNel;ukvi45S%yJz zSs4c_Ys3#->-L6<0i492?!s7up!-`It9__F6n25}bScfXc9_KjRe*4gn_QJqVBjKk&dIMA(D-z!HSs=T-ic3!J#85owN%t3u_`rBD z$7L{0F#E{=EYvxg^cHhnGxSWuPPe~NB(g%a($)cMB$KYJjj*Lj&jkS4$A{$-uD$E% zXtFAj6H>)3*7Q+3JG)6qdOKI-8Uv~|wB`mrDNn^6Ui~!;2vSxS(c{2M8kGSG+0$3} zrynf7Kh1(G}uBAi_Heg;~y)pYM*E+ zbtxBUA&d$B9^pGGcrgL2;s)*F(~};{-`*zuJ_0pof>*DfgDe1InOn~?wE*YN<9CeJ z)6$BKib@|Z$_-k8T{+*__qkWR8&jg^;sOpm+pCVzYC0X=s@S$IZ&m+uk4~H3uXbr@ z%VQZ)y8RU8+keUi&70SG+Ya)Gv6F|M`6S z<5N_QiXXtK_qK8<*oIUlnsq!8o~R~ z3QI6-7DcH0>({T@>zm?J{BtauSSFAN9G8ail-|Ev?})Dw6uM_KQYmry+b0;d!pgqs zS~(qSdY#8t!C~dh7C+YSCO9Bim97s*1554?*{ZN!CD6sk{kA+nqpbC0@lNT3d^)aU zC%%8~A2I8*Url)Z?%g}6oC~$&!@nzblv5+_l81+MYR_&}^JV>xuy(arCgAcRu#%-P_cKK;{p@dn3JG1xny@HjpK z)L|&O(j@UapekZFd-Fk$J_;q8&El&dl3IEBDsJtys5lha)wquKbzx-z9^a1t=!wO1 zDKvQWR0hzyVo4L^xAA-I%)4j;l$)Fel~d#KOu8*cA8(4v69;6EaZ$TcfB5j>=3#Kc zo8tm`Q~5LpHFYA?^?9`snD`}IJ-}qx0b??MLPuZbarASIjg13z+^e52!v775LynxoQo@^M?yNV=5Y_52Hh&HkM~%{9!Zet#cv=!c+V&t}uqPifdcb1Kz0#kj&`--m6-%5 z1Z;aQ_638%8c05};Qk+{yDut8U?XQ|y$HRlr>6&*uscO0%cY6c%*aUW(=tD~)RX%> zdA0QM3FqiU@9XJt{#8~!Xkt7`)ttcKvI$IKONM+gIT@K$?i6NYt-Q+0FW;Jl^v*23 zAbWy;k%Gd~uHXYEzv+CBxu5z#zuYo%>wUU;4)jL4y1L@5Q7#%_{bykzJ)Ox3<$icW z1pdqTcq_YcF5q*&{33{K5P9w6}DA-yw=deHljxyIu~wQLZ;V=GAOdKv9Wxo^zt)B2BvR(X1e!xB2h%Q@w?kn4J5Dv zx1Bi}ZnhRC)K#;CifluXd|7k}(l|@rno`#nR-Y z*flU`g0kC&*E_}Lr?@QueWqIH3%#O{9n5?*4;T<>xN~1uBNB4^`}^nnav&5x#izaT zAxp*5{a}AP2j%!froSvQZlgu{;>A2cNhKv36rXeMx-Xu7XfFFP=NEnGfg{|}IhuN2 zR;}hi`#`}Jz>x3XX;2z_uLo|-gFsNr$jD*yjQF49%_rw)%Q%e1>dQ^ov1LvOXI|x;}l9C&e6)9!C%AD5Ikn!e!5>H*!1B8nQ6UC70&hHD#)~^lwGi8k+w<$ihebj_Ix=m4(E_`jc}gQtS6lS*?9#b%}`?MMe9-1=#+j zv8H>0P9%Zpo6x;~OfALfRw8qhXhXXNEtKdzHi5jKRPg%O$*maIG41fWnrP!~l|x(8!5lp#y} zuToIJfXh)_mo_&tN(b~)ldy>4?Caqwds@%gQ|robFR0xJw03|%>UmFd?A}gL5b|}p zURHLtj;?OsLk^|GiTZCh?Qr5JzZ4P&pLyA&jzDmVycb|{ZA2<$8Gu--FGh z>h{>l~5Y$On?Ko8Z{8{6^D|^4}c;aW?eeNpflh!*zLXK#bXB7{= zCMW}(LUbv~k3~~+X~hu+l(3;jsDu9d`~od`=#)>LK1Y3P5YMw&n9YT#qEJU5y7tq! zmx{)KJ`AnDm8;TFE#b?w&!%_O+_}++i!1)Ixfv?=&)pw3==pEF>&jPGQ!}=!;@Mok zyZ-2K;nUX^RIr!n#Z^IxY;43TM+Ak)iT`i3;mpsD)_a}$dy@es^dZn(3)qhl${0Nu zDFKG`(o!`qQm1zBf-Z>q3~J&GfLHuLYUDEMQ$)XJ@b)U zmn`^>`aoWERvZeSfJA#2=o)j=4^mdh-V?iSi{54!lP&QOM^f<^Pk@T*#!aO7*E<}1 z&X+f|%`chv+03C>#h<3UOi8&!LBU!ffZ&)48Ponb`sY za|?mx4(swH>(ze^7}JQ3#fK5vnw37aI{GQtJHlR~)S|_C+=ATBY9BJ^6A&2a>+Aa#bEhy`9?%7*Z!n1aG?HI#}8 ziasaSQ1;=5DRTPDoU%VU?O^IP-9&a>_Ca=&vcd+ba*nuxxhSGFKLYawmm^9rKvAgL zX$BDIxx3{^!2@x(zRX9{$A-Yv1%alcYop)i%6QZC5JD%?lr|&&H2**!e&u zf86#uw=2Ji&S*J*^J1cxc)0xXBLg5N zXu$d|x%2VzHeh;Dah9p?9zE-JRu^e$6_2nt^K)~rRk5jI3ZiUWWWyU#KsoeKA3HSk z^g3q;6gTHjijGb;1^_a?-!NBNQIWM&b%ngOZFpG6nwwBhRaF%n>;UIEZg53bNOXyG z!FqIoB+~BNo5|^E37?V+c{MdjhX(%iDO8>v zGt$%le8^dp2^jqUhRHOD2UqF8b+2IJ<&AqFL)i8=%M4Uc{6!V&9L5YKU7Tq?Z?h^MrOj*Fp$|0sssJ}kTLkGe`%yDs0?tTX|N=Pkrpx?i)C zJvk6sTEgwWzvx6LCjA(#v@P)U)!Nz3`Kq5d35^DD4YsKNYn^j+NhBe&c$2&PU+gS# zx?f`l4#0-kp$9Q&sa7|tyZPBKtpq$+$bySqvmgm@Xe~f3{7}=|@@BVdd!Wa-eoiF5e=uv4kp+Nfaq+LXHgT1t4)?;PK{KA5gI93;$5C&_4_A$J;2kgmwQl4smjtaB+l}Spue3_o6R*@2 zXk+<66ceJLJv#1D@O0dRwy1ul)4m zCx_OTH}JZ_T-|%mC+NH#Y0V4acTCw=Na{j@F1G^W0U4PJhDC22CRKnT<4sywNh|E^ z_GRon$M>9p0=g1E$a^3j-30wEu*W?Qd;Z^0K$>N}8bROfvvb7jBxS(8K(0zE z>FZ;J6oL{O$v3rwck_y`MZR1fSa_`TeiqMuk^=b1onK_u&c> zB_)yN(E`{n7WOD!*>aibepUyVbMEB+^7zuXU88^1Glmuay`EX0L*)R{#J9o5>bBvl z^y3aZ!_O)R)0me_hD9-;+B@t*b^8<9{3PfiNLF_s68gixx@0!RCwETDzgzi7r2^aS zNJl)aOBvM;)901eDH0|Uv$DV&m^0LPh9vP}y6OFIjCKm-~4J& z1^M{$5Ua0O^kuIMLY0N-s9}Oyxs1*4@8=0xeg(;JDBm}zA;Y7Q6D=>O`Y$C`~l1oj28W|d95sxhC$j77Z*TEk@hrj0cD6Sx)+sX&?dOUh)Wetp$nl**8mH&D_2!qB_QDoc z%*@U0?ZG$kzuQVPoz+lL0sbD8MpDc$X?S9A$6U}{@Zde9O*y&Xe*L&em<@W%0nB^( z@@1R%rqEexYik1wtY4MFUYNlOW)bWU?>x;03{7_YYXoH&rBa;%sQj?0o2VjzH~}mh z3|j5v1e)&M&6{wl#~+MzX8HSYmItEL{ZI*h8+Z|hQ5;=qzwX`p&2IelL=~3GHN~x! z_pU{~BO?R7rOE!nRtcuU40&2&Vpw&_43I)Guur8Lv#+S(ce(%Ki^aRAyd429pYl>e9I zuLA>;5)v?=l3xncmj9*-O1Suq4Gj=idhO2i*ciw=p5tp)##GoubO=LlpU_Z&=bpkY zixFiOeUZ?tZ>;=a6BBZltuWnh#JANH1Q5Cv-d_<{Lz!8g9t5`h}&} z+`{R&aB*`gOI})iW~F&&9<;GTVNyUv?$~k91Oe4CoVcdaUw2qRq|Wr(S7@d42JUPJo&;GE#)Mad8_<8CG$oHfvtyXH^in764OLKGt9Vty(5~z>UM*QE-N^9e>Y% z)rMvyg*c=)N7#EqkaWg|zdF<*3MvBld2k(v+6>vM>!A?=i)hsByOS-;oO^s?CV zJjI)K7|+xtJ`-$V9lju&Cly8`D=Zz!|H5SlZ}e{MWd^^*^fT+)<1OyZlzh$lHF4d) zB>en6nm{WEz|b9|ZvxP9YF3M}31~mI_BSs+5N*CQtRu!AB#aS)C@32YRM``i8#F86 z3rUAFr{OVr^)jIVp`M-jSp8PW-1OBUh#)@aYGXEm`5+JAui&m!%oO&w@mgPpXgQ_N z0l7nsiOVi-NMaN=jvI1sHu2A8aOixe!*RYyE_w zdrzY7S$_%7cm!Ks**SKBgAWWe4wtI7F;u(RI0VA7J4J(4m#`k*!+-asohUP|EiW1w`daT4-3&NU(4%( zs+hgn8*~#kM=_RWbvMMe0YRhwMGM#%W@s7H_>g#E6sU+lUS=!NE=?E;W8koh5l!}c z&#N^iv+H2&pk39v2z@?_QccjXROnhgWlu%Ph{WnM6=cs3D4zO@E)JN^%zyBq9=J~z z&3|%v`|jPlzj5A%#r{BQPGDrd7tyIY#2rzdhplp@Otv>4NmDP5R*ygdC$!6Wi{N?A z;W`Ri1LqCw#@Kmj%oy_kmc{*AF&beD)Y3&Q6P+uWiv4+dm%saIxim z>mcVy*r{_D@l!ouPXn>9E;Dkfph*GDEW{nzP&-?0b(n;n4d3+tql;Mk`a0Rcxg2Mz zzn^r<0kYLp9&^9>u{8RH(I>=50`XnR4B$p<)M=_mzsxZdZF?%!Z9Z{;1aUKLCz1E5 zugo$nGpK@*m}HLx$lC61(!KXL*Zcm5fc#|Z1UV;E^O}0eIVmWBr*3(=@p-(&QUrLp zj*65ysoV=*UJgwKjTQU~&U@Fi?;%)p&bM<@U98J2{(Wq7OaJlZKGSN9VSxKm;3*&& z^yRl_2f|3h3f=j2w}{(-&WrspQlkmbwFX}Akbwe=((>bC3$z(FuMdw7mA~XgUtyWb zX=sqpe6LkBr+xN0dBDm=d@tv_nw5<$7AL%RFae<}nKh-BocqiSH<%nmfsAv}`3Kab6ItB{`}(MYYyfKJqbSg)emZ52ucgopvW#j2d%uoqj%E z);F`7cadTOic!NRKB4q6FU8U6x^Yp8a4befY`qUF-F^F4GotQ}?H{YCpL7E4CJSF! zc@RP5zH2}3F6*c&YNjNlQOeiRU5#NW=xNfx!TS4?MJQf z)m4f6##Y~Edj*+l`piKua5`dgVL{Zq!%(GlzRxPjQ^57Mw?+6RJuryT(_4CbG?N2n zSiq<`A={U|3+mh{jp>!&)d~B3L|0n|@%}zhX}Jw7_217nz`wt z+d~S*TMCt7a0S=)9(ZjTP5R*T%GBbe+z*f*hi$l-GuycFuU7wKs6V15wD}0%eKAt2}tR^ZW)?Q*Wxbo|-+=ya!XIWn5 zw{LTm&_B@6XSZLxs8-9fh>#zO_*@l$OC~^eVsM09AHpy6)CZ4$lVRSH&y4w0#eXIwz*9O<{N6moGgc zz{aR!e>q1;c-t5arnN(Pccsg4pB?*OVZ@^Sckd^KbO6MAw5u!z!jOOW!YbiAcWH40 zTnYwXy;P`dc{LnqRZvs&t+DYAykX7xN0ThXvSP$YfyCFDnN07>`roBkE~5Lu_(y>* z_Mp^@EJQ;iZXKr=+=)V;=o%fuzA}z1%D-;8*en45QLv*eh-B@qb-o-@P9a2M3UV83 zOk~MkP~BI=hr`XHC-f}f>e9Ng?e#|N8C)4-W~Hs}2aIvkQ|-kNfP394Dz_+lsc&?# zAbBY#4};C~Dz232A4#aezM>16E>AOYRF87?1j10Tib#2c?7uW6#glAxo#`;wxHy9h z;&(E9_{?cL8_7PMgYkK3T(0xl#@qGmefyA7W^p9Ie|H5hnH@P?vwIn~6IhFA#^{)K z*uWfVWMs4MNTlOul3>q%8w;w&%Yb=02fT?g?Z;o=rn<7q{yj&pIz1BP1CcCL6>7md zL8j+;7dDlda8!#dup16Q52^@Ep#HG9Ft9n$vPLHIGH_T+88tj$@vG2?`ATmw-@#Cm zzp`HqUM{z@s>Z{TZ#@<~S7jHvw>5&z({Rf329>@|5fWjrZSb}`)VFW_}2Ug9^V8WJFktTjGl+Vhm{$v7aF3) z;vGI}WPmus^jv;kUfM28FC$R9+1PI0bO%l1@6X{Q9M=w(U2OC33sxA;`ns;TZpW1Q z*BsHVM(5%CJh8PcgoN<|DA?F1PXf?fle=d<2A~UK3bRQRxPg0;)~QP0BhKbQtLUm(JI3 zq0JSb{JRSv3t-}HvHhmd3@z20@lx6$SIFm~JC~M}EO}!GPZqejA3uJSu`oAxfBbl6 zdfH))HVM4WR$Y{kUro)-UcPwY%Rd%)bY@8*_4tTzr|<|4*nWvYM_FuYWHdQ97qBXI zP$;w-t-4N9?Pa(h!)iwE9mwvImz#V0U1sK~GtcUhl1%EkZ2CRs!OK9lTD5LXJhos%+JR8OB#yH0*6%dl9wt`LG(bk3y#s8nP@#-y^5LHm32N5 zk>p*xZY+&OtlE`_lhF)f+e%DJ?cP+^gEDWVp9rQzo&(%sV5pQN(m5}1FO?U zftdUOgEANqLnZ47yoAs|0*9sHAQ+|$bJjhabE;$snH{qmyjGNH>fy5!6n>l8oc#LO zckb79YAzpYlhj;*WU2a*D@5LR@tK^P%LfBUsyx-Hr>~W(xnS+(8k5iRCEieL=Q>~V zyp7<V&o~cDBhd6a`sdchQ1~V-+WqNL8;g8+G`1n zoYOB&W}f^~BVV%z3~2xg2>C@(?1y$fa39)PO##k4C`Vz3ge(~lB>VgCLCQR>!t0p6 z4FULW_Rj13LbSVVY#f8ty}g>xv?wB1?qf4N-X6`od?yKzqM12+DuMQs@enT5??N=+E zh`Wk97{=7{|AgA0TF&+pN6)g@7FKA#AjP||Dq0Zra$LKIfg4Z^!DD}^~ z*+%etpmK8jB!SY}-7||lL`U~BOG~2^5%f8!sotE0l21cI2(Ozo{RmJrQPCs}3@#i4jEa@zQl-AaDG(Ir2iTmmy;xIl|rog>LBfyZPK z3anCRhm}B3`qE>)2?}<z)7Z_OSwDVbELfJzjGFPW`JB zZZhBy)83`u=z&Q_;5-VYQ3<$KY9fdEkATrxw=>o1_}zahgw;SLA~0&X4pnLVQ607v z6}{!TT$^mjjT7rTHihxm!6A$TngZCJzOhT~Zic3p%$}KN! z*LgOk{PJPCM|G>o&CiiI@#}>(lH!v!4c#ZPo(wt};+!MlD#K}CA#`QXmb zWYJ{i=q0h;H-hM*?kgldSC)6;O8eqGmEmCHI+i=IRLhh?7P;xuO zeqV3@0$e$o{8BD#i*61&D6(5@99w~e$b-%4Oj*%uD^0+Tx_xDEx~1jz8*A55K|1^N_5Ka zM1Gtu^}{8ILHn{31b=-&L|%G63*YlQZOSkaOQR(iBB?R~ERO9z;wP4!d*}H5G{L;F zC?dE5m^E{lyx=?jpppSEs<0g;@3#2;d-zix2}?Cj+W5 z%n31t!2uZrWH33HDeB%|7sn8EWr)hgBF|2n}1yaX>u?8LG#k^g5&zz``zvq};q zVI6_V^Kjml2PE?)Fna#`nhLVBo52zjhV$&!gY1&Emx7qcR!QJ9Oqu|VI60O6b;AGU zva?sf%F{nLmwX^r$e9((OvPz;E!J-rc$6hgKxhXim|8a;#7*~v1`jWEi6B!`6=?WX z+y?UF0oOIFuzK$MTAvf7CCr%O1e6@W(8QEYn1}Fs7c=9nCp`{qP@OV?JC5EPhd^$J zW&NzOhehC?b+qlptIliQF)=;Oy0q3;ca+TMzCn+xFUod&l-@_ndF1RO$c4vecL zZGgmrG_6N4rj)4j|$f^GgCBs-Ku3oIfFuCeh zo6|3HWC!nBfrhMM&j{riRq3RLo-w$bL1S)aCJb!pl>pFm8~*wRD3@{w%0cSJjTU&q;P|Qp z6I;h;7J*Z-5#8$~?9;n=k4kYpiy{1-p8H5p2``xWm4B@~_0{PAMAY!n{4iOx{MTd= zLv{+x{5LlR6PqS|5mzoo*4BW5tr7d>&0nLTUdVu9Xd_Y*-bD={tY5T%O&9Dzb_^yb zq2uWj-%s^Oqls%0KnDoJKboph|mNJeB`P%<> z+h$4aHpXaU+!(k@`0XBA(GZVW@kQp> z6{~V`EUW{Ft6p0}`VPd!+_yY$t;KQ@NK)1~LnX6aM=%Li222mnV?uWSi9Bt@uf+Eb ziz$KSYfYOUAAp-`ev~2@x&MR0RBwn0+|0m_i5SMI4W_D;JB}uMJ2+s&a1V{m`F693I$gD)kLJ*s>3JJpTxQOXK1Y*n@D85L5p|q~o9{F@=euYCZsd!7s2~ zgou49=pT{sIKJk7WjyZ4{?T*&743tXFyTG(^gNzgdr|_YBOio+o5AKdU z-jr1y?8yFgf%`@#U!S_GTEKSjd2t!STSpRy4TmI`eb0-(`iwdQf3N8cdNFtz9tE8j zKNG}MafjRL$w-yVk_J8eid?i#-_zg;rV6d6=fwlt7B<~QQMn9^-1|>Onth{<;_uRTE@7w!atvP*ox@tTb40PuLR^3AK*X^qA zNYS1PV7I@Xh^z}|U$d@&Pvx?^-b~*03=0{ytI|kO$_bS^sbL|Id8cr|ntkrEexAA- z_1KdhI9(=M{kq*XckeDFk;>a2Sh+A|UB=37zXDlCk(rq)x(5?nfox+$ygPV!l=3{j`VK>RYioJT-^>I^u=)Tu#h%;F?X?WWP zVtw@5ILb5)A!KwE6oCpKqF(XvZozxy5i&%5#@)N%hT$k9czS;-O~rlVe)5aRdpM63 zpH$o*i`yq&emrQjM_-z7#Gb?&?CRVMK;ekowpjgE7{)q=YVz~0!8vHdxKDd2bcCFs zmg)$pAErLjbw;Hm?X*b!0Ciye1^SkbGaX~zD<_og>zA=Eu@sNh{XXoEv#dn7D__^S zN$nqq{=j-Y=Dm4v+1K+7`!kX))cZScDY2|WaOu6ArM&OEOMSMv?!$*2OVZSFW@X#N z{M47R+YVCR33HEsAMo#^oVe_ZX8ob8+LS~Wl5}BWdq&#gR7MZ$EZT6MQmj^=$lY61 ze&<)n34!L55r~_N_pXv - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/step-builder/etc/step-builder.urm.puml b/step-builder/etc/step-builder.urm.puml deleted file mode 100644 index dc60873408d4..000000000000 --- a/step-builder/etc/step-builder.urm.puml +++ /dev/null @@ -1,91 +0,0 @@ -@startuml -package com.iluwatar.stepbuilder { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Character { - - abilities : List - - fighterClass : String - - name : String - - spell : String - - weapon : String - - wizardClass : String - + Character(name : String) - + getAbilities() : List - + getFighterClass() : String - + getName() : String - + getSpell() : String - + getWeapon() : String - + getWizardClass() : String - + setAbilities(abilities : List) - + setFighterClass(fighterClass : String) - + setName(name : String) - + setSpell(spell : String) - + setWeapon(weapon : String) - + setWizardClass(wizardClass : String) - + toString() : String - } - class CharacterStepBuilder { - - CharacterStepBuilder() - + newBuilder() : NameStep {static} - } - interface AbilityStep { - + noAbilities() : BuildStep {abstract} - + noMoreAbilities() : BuildStep {abstract} - + withAbility(String) : AbilityStep {abstract} - } - interface BuildStep { - + build() : Character {abstract} - } - -class CharacterSteps { - - abilities : List - - fighterClass : String - - name : String - - spell : String - - weapon : String - - wizardClass : String - - CharacterSteps() - + build() : Character - + fighterClass(fighterClass : String) : WeaponStep - + name(name : String) : ClassStep - + noAbilities() : BuildStep - + noMoreAbilities() : BuildStep - + noSpell() : BuildStep - + noWeapon() : BuildStep - + withAbility(ability : String) : AbilityStep - + withSpell(spell : String) : AbilityStep - + withWeapon(weapon : String) : AbilityStep - + wizardClass(wizardClass : String) : SpellStep - } - interface ClassStep { - + fighterClass(String) : WeaponStep {abstract} - + wizardClass(String) : SpellStep {abstract} - } - interface NameStep { - + name(String) : ClassStep {abstract} - } - interface SpellStep { - + noSpell() : BuildStep {abstract} - + withSpell(String) : AbilityStep {abstract} - } - interface WeaponStep { - + noWeapon() : BuildStep {abstract} - + withWeapon(String) : AbilityStep {abstract} - } -} -WeaponStep ..+ CharacterStepBuilder -CharacterSteps ..+ CharacterStepBuilder -AbilityStep ..+ CharacterStepBuilder -SpellStep ..+ CharacterStepBuilder -ClassStep ..+ CharacterStepBuilder -NameStep ..+ CharacterStepBuilder -BuildStep ..+ CharacterStepBuilder -CharacterSteps ..|> NameStep -CharacterSteps ..|> ClassStep -CharacterSteps ..|> WeaponStep -CharacterSteps ..|> SpellStep -CharacterSteps ..|> AbilityStep -CharacterSteps ..|> BuildStep -@enduml \ No newline at end of file diff --git a/step-builder/pom.xml b/step-builder/pom.xml deleted file mode 100644 index 432d5477a123..000000000000 --- a/step-builder/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - step-builder - - - junit - junit - test - - - \ No newline at end of file diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java deleted file mode 100644 index b5354e04a03d..000000000000 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.stepbuilder; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Step Builder Pattern - * - *

    - * Intent
    - * An extension of the Builder pattern that fully guides the user through the creation of the object - * with no chances of confusion.
    - * The user experience will be much more improved by the fact that he will only see the next step - * methods available, NO build method until is the right time to build the object. - * - *

    - * Implementation - *

    - * - *

    - * Applicability
    - * Use the Step Builder pattern when the algorithm for creating a complex object should be - * independent of the parts that make up the object and how they're assembled the construction - * process must allow different representations for the object that's constructed when in the - * process of constructing the order is important. - *

    - * http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html - */ -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) { - - Character warrior = - CharacterStepBuilder.newBuilder().name("Amberjill").fighterClass("Paladin") - .withWeapon("Sword").noAbilities().build(); - - LOGGER.info(warrior.toString()); - - Character mage = - CharacterStepBuilder.newBuilder().name("Riobard").wizardClass("Sorcerer") - .withSpell("Fireball").withAbility("Fire Aura").withAbility("Teleport") - .noMoreAbilities().build(); - - LOGGER.info(mage.toString()); - - Character thief = - CharacterStepBuilder.newBuilder().name("Desmond").fighterClass("Rogue").noWeapon().build(); - - LOGGER.info(thief.toString()); - } -} diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java deleted file mode 100644 index 4b29ba6c45ac..000000000000 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.stepbuilder; - -import java.util.List; - -/** - * The class with many parameters. - */ -public class Character { - - private String name; - private String fighterClass; - private String wizardClass; - private String weapon; - private String spell; - private List abilities; - - public Character(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getFighterClass() { - return fighterClass; - } - - public void setFighterClass(String fighterClass) { - this.fighterClass = fighterClass; - } - - public String getWizardClass() { - return wizardClass; - } - - public void setWizardClass(String wizardClass) { - this.wizardClass = wizardClass; - } - - public String getWeapon() { - return weapon; - } - - public void setWeapon(String weapon) { - this.weapon = weapon; - } - - public String getSpell() { - return spell; - } - - public void setSpell(String spell) { - this.spell = spell; - } - - public List getAbilities() { - return abilities; - } - - public void setAbilities(List abilities) { - this.abilities = abilities; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("This is a ") - .append(fighterClass != null ? fighterClass : wizardClass) - .append(" named ") - .append(name) - .append(" armed with a ") - .append(weapon != null ? weapon : spell != null ? spell : "with nothing") - .append(abilities != null ? " and wielding " + abilities + " abilities" : "") - .append('.'); - return sb.toString(); - } -} diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java deleted file mode 100644 index 0cf32699286a..000000000000 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java +++ /dev/null @@ -1,187 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.stepbuilder; - -import java.util.ArrayList; -import java.util.List; - -/** - * The Step Builder class. - */ -public final class CharacterStepBuilder { - - private CharacterStepBuilder() {} - - public static NameStep newBuilder() { - return new CharacterSteps(); - } - - /** - * First Builder Step in charge of the Character name. Next Step available : ClassStep - */ - public interface NameStep { - ClassStep name(String name); - } - - /** - * This step is in charge of setting the Character class (fighter or wizard). Fighter choice : - * Next Step available : WeaponStep Wizard choice : Next Step available : SpellStep - */ - public interface ClassStep { - WeaponStep fighterClass(String fighterClass); - - SpellStep wizardClass(String wizardClass); - } - - /** - * This step is in charge of the weapon. Weapon choice : Next Step available : AbilityStep No - * weapon choice : Next Step available : BuildStep - */ - public interface WeaponStep { - AbilityStep withWeapon(String weapon); - - BuildStep noWeapon(); - } - - /** - * This step is in charge of the spell. Spell choice : Next Step available : AbilityStep No spell - * choice : Next Step available : BuildStep - */ - public interface SpellStep { - AbilityStep withSpell(String spell); - - BuildStep noSpell(); - } - - /** - * This step is in charge of abilities. Next Step available : BuildStep - */ - public interface AbilityStep { - AbilityStep withAbility(String ability); - - BuildStep noMoreAbilities(); - - BuildStep noAbilities(); - } - - /** - * This is the final step in charge of building the Character Object. Validation should be here. - */ - public interface BuildStep { - Character build(); - } - - - /** - * Step Builder implementation. - */ - private static class CharacterSteps implements NameStep, ClassStep, WeaponStep, SpellStep, - AbilityStep, BuildStep { - - private String name; - private String fighterClass; - private String wizardClass; - private String weapon; - private String spell; - private List abilities = new ArrayList<>(); - - @Override - public ClassStep name(String name) { - this.name = name; - return this; - } - - @Override - public WeaponStep fighterClass(String fighterClass) { - this.fighterClass = fighterClass; - return this; - } - - @Override - public SpellStep wizardClass(String wizardClass) { - this.wizardClass = wizardClass; - return this; - } - - @Override - public AbilityStep withWeapon(String weapon) { - this.weapon = weapon; - return this; - } - - @Override - public BuildStep noWeapon() { - return this; - } - - @Override - public AbilityStep withSpell(String spell) { - this.spell = spell; - return this; - } - - @Override - public BuildStep noSpell() { - return this; - } - - @Override - public AbilityStep withAbility(String ability) { - this.abilities.add(ability); - return this; - } - - @Override - public BuildStep noMoreAbilities() { - return this; - } - - @Override - public BuildStep noAbilities() { - return this; - } - - @Override - public Character build() { - Character character = new Character(name); - - if (fighterClass != null) { - character.setFighterClass(fighterClass); - } else { - character.setWizardClass(wizardClass); - } - - if (weapon != null) { - character.setWeapon(weapon); - } else { - character.setSpell(spell); - } - - if (!abilities.isEmpty()) { - character.setAbilities(abilities); - } - - return character; - } - } -} diff --git a/step-builder/src/test/java/com/iluwatar/stepbuilder/AppTest.java b/step-builder/src/test/java/com/iluwatar/stepbuilder/AppTest.java deleted file mode 100644 index af1ddfb58f32..000000000000 --- a/step-builder/src/test/java/com/iluwatar/stepbuilder/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.stepbuilder; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java b/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java deleted file mode 100644 index 962feeabb671..000000000000 --- a/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.stepbuilder; - -import org.junit.Test; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Date: 12/29/15 - 9:21 PM - * - * @author Jeroen Meulemeester - */ -public class CharacterStepBuilderTest { - - /** - * Build a new wizard {@link Character} and verify if it has the expected attributes - */ - @Test - public void testBuildWizard() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Merlin") - .wizardClass("alchemist") - .withSpell("poison") - .withAbility("invisibility") - .withAbility("wisdom") - .noMoreAbilities() - .build(); - - assertEquals("Merlin", character.getName()); - assertEquals("alchemist", character.getWizardClass()); - assertEquals("poison", character.getSpell()); - assertNotNull(character.toString()); - - final List abilities = character.getAbilities(); - assertNotNull(abilities); - assertEquals(2, abilities.size()); - assertTrue(abilities.contains("invisibility")); - assertTrue(abilities.contains("wisdom")); - - } - - /** - * Build a new wizard {@link Character} without spell or abilities and verify if it has the - * expected attributes - */ - @Test - public void testBuildPoorWizard() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Merlin") - .wizardClass("alchemist") - .noSpell() - .build(); - - assertEquals("Merlin", character.getName()); - assertEquals("alchemist", character.getWizardClass()); - assertNull(character.getSpell()); - assertNull(character.getAbilities()); - assertNotNull(character.toString()); - - } - - /** - * Build a new wizard {@link Character} and verify if it has the expected attributes - */ - @Test - public void testBuildWeakWizard() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Merlin") - .wizardClass("alchemist") - .withSpell("poison") - .noAbilities() - .build(); - - assertEquals("Merlin", character.getName()); - assertEquals("alchemist", character.getWizardClass()); - assertEquals("poison", character.getSpell()); - assertNull(character.getAbilities()); - assertNotNull(character.toString()); - - } - - - /** - * Build a new warrior {@link Character} and verify if it has the expected attributes - */ - @Test - public void testBuildWarrior() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Cuauhtemoc") - .fighterClass("aztec") - .withWeapon("spear") - .withAbility("speed") - .withAbility("strength") - .noMoreAbilities() - .build(); - - assertEquals("Cuauhtemoc", character.getName()); - assertEquals("aztec", character.getFighterClass()); - assertEquals("spear", character.getWeapon()); - assertNotNull(character.toString()); - - final List abilities = character.getAbilities(); - assertNotNull(abilities); - assertEquals(2, abilities.size()); - assertTrue(abilities.contains("speed")); - assertTrue(abilities.contains("strength")); - - } - - /** - * Build a new wizard {@link Character} without weapon and abilities and verify if it has the - * expected attributes - */ - @Test - public void testBuildPoorWarrior() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Poor warrior") - .fighterClass("none") - .noWeapon() - .build(); - - assertEquals("Poor warrior", character.getName()); - assertEquals("none", character.getFighterClass()); - assertNull(character.getWeapon()); - assertNull(character.getAbilities()); - assertNotNull(character.toString()); - - } - - /** - * Build a new warrior {@link Character} without any abilities, but with a weapon and verify if it - * has the expected attributes - */ - @Test - public void testBuildWeakWarrior() { - final Character character = CharacterStepBuilder.newBuilder() - .name("Weak warrior") - .fighterClass("none") - .withWeapon("Slingshot") - .noAbilities() - .build(); - - assertEquals("Weak warrior", character.getName()); - assertEquals("none", character.getFighterClass()); - assertEquals("Slingshot", character.getWeapon()); - assertNull(character.getAbilities()); - assertNotNull(character.toString()); - - } - -} \ No newline at end of file diff --git a/template-method/README.md b/template-method/README.md deleted file mode 100644 index 65381d0ce12e..000000000000 --- a/template-method/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: pattern -title: Template method -folder: template-method -permalink: /patterns/template-method/ -pumlid: NSZ13SCW30NGLPe1mFTkuu0Lg6n0vZjPlpttzlIEFef6bN1zDM3jDv7paw-E5cTiyJ87P22NQTGr7WOxVVZcL6NtQwJ5WFZOPBn_88WjPKWoGPkL1EN_ShZb5QPV -categories: Behavioral -tags: - - Java - - Difficulty-Beginner - - Gang Of Four ---- - -## Intent -Define the skeleton of an algorithm in an operation, deferring some -steps to subclasses. Template method lets subclasses redefine certain steps of -an algorithm without changing the algorithm's structure. - -![alt text](./etc/template-method_1.png "Template Method") - -## Applicability -The Template Method pattern should be used - -* to implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary -* when common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is good example of "refactoring to generalize" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations -* to control subclasses extensions. You can define a template method that calls "hook" operations at specific points, thereby permitting extensions only at those points - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/template-method/etc/template-method.png b/template-method/etc/template-method.png deleted file mode 100644 index e197813398efe850f7c292d052b9efef8d9563e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17911 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 PkmRJ4B=f~zefs|ZY{Hvt diff --git a/template-method/etc/template-method.ucls b/template-method/etc/template-method.ucls deleted file mode 100644 index ec0ce620a3ae..000000000000 --- a/template-method/etc/template-method.ucls +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/template-method/etc/template-method.urm.puml b/template-method/etc/template-method.urm.puml deleted file mode 100644 index a6e2dc3d20fd..000000000000 --- a/template-method/etc/template-method.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.templatemethod { - class App { - + App() - + main(args : String[]) {static} - } - class HalflingThief { - - method : StealingMethod - + HalflingThief(method : StealingMethod) - + changeMethod(method : StealingMethod) - + steal() - } - class HitAndRunMethod { - - LOGGER : Logger {static} - + HitAndRunMethod() - # confuseTarget(target : String) - # pickTarget() : String - # stealTheItem(target : String) - } - abstract class StealingMethod { - - LOGGER : Logger {static} - + StealingMethod() - # confuseTarget(String) {abstract} - # pickTarget() : String {abstract} - + steal() - # stealTheItem(String) {abstract} - } - class SubtleMethod { - - LOGGER : Logger {static} - + SubtleMethod() - # confuseTarget(target : String) - # pickTarget() : String - # stealTheItem(target : String) - } -} -HalflingThief --> "-method" StealingMethod -HitAndRunMethod --|> StealingMethod -SubtleMethod --|> StealingMethod -@enduml \ No newline at end of file diff --git a/template-method/etc/template-method_1.png b/template-method/etc/template-method_1.png deleted file mode 100644 index f7cd1a07771cc6da554474967af2418b13ef0112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34592 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 P1%FC%NZCATQ~&=1?cAFf diff --git a/template-method/pom.xml b/template-method/pom.xml deleted file mode 100644 index 916d61b0bea6..000000000000 --- a/template-method/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - template-method - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/App.java b/template-method/src/main/java/com/iluwatar/templatemethod/App.java deleted file mode 100644 index 5ad51d3e5893..000000000000 --- a/template-method/src/main/java/com/iluwatar/templatemethod/App.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -/** - * - * Template Method defines a skeleton for an algorithm. The algorithm subclasses provide - * implementation for the blank parts. - *

    - * In this example {@link HalflingThief} contains {@link StealingMethod} that can be changed. First - * the thief hits with {@link HitAndRunMethod} and then with {@link SubtleMethod}. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - HalflingThief thief = new HalflingThief(new HitAndRunMethod()); - thief.steal(); - thief.changeMethod(new SubtleMethod()); - thief.steal(); - } -} diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java b/template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java deleted file mode 100644 index 0b1fb044ee6c..000000000000 --- a/template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -/** - * - * Halfling thief uses {@link StealingMethod} to steal. - * - */ -public class HalflingThief { - - private StealingMethod method; - - public HalflingThief(StealingMethod method) { - this.method = method; - } - - public void steal() { - method.steal(); - } - - public void changeMethod(StealingMethod method) { - this.method = method; - } -} diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java b/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java deleted file mode 100644 index 0b7ff9d911cc..000000000000 --- a/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * HitAndRunMethod implementation of {@link StealingMethod}. - * - */ -public class HitAndRunMethod extends StealingMethod { - - private static final Logger LOGGER = LoggerFactory.getLogger(HitAndRunMethod.class); - - @Override - protected String pickTarget() { - return "old goblin woman"; - } - - @Override - protected void confuseTarget(String target) { - LOGGER.info("Approach the {} from behind.", target); - } - - @Override - protected void stealTheItem(String target) { - 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 deleted file mode 100644 index 61aaf4ab4562..000000000000 --- a/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * StealingMethod defines skeleton for the algorithm. - * - */ -public abstract class StealingMethod { - - private static final Logger LOGGER = LoggerFactory.getLogger(StealingMethod.class); - - protected abstract String pickTarget(); - - protected abstract void confuseTarget(String target); - - protected abstract void stealTheItem(String target); - - /** - * Steal - */ - public void steal() { - String target = pickTarget(); - 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 deleted file mode 100644 index d8b16af3dab4..000000000000 --- a/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * SubtleMethod implementation of {@link StealingMethod}. - * - */ -public class SubtleMethod extends StealingMethod { - - private static final Logger LOGGER = LoggerFactory.getLogger(SubtleMethod.class); - - @Override - protected String pickTarget() { - return "shop keeper"; - } - - @Override - protected void confuseTarget(String target) { - LOGGER.info("Approach the {} with tears running and hug him!", target); - } - - @Override - protected void stealTheItem(String target) { - LOGGER.info("While in close contact grab the {}'s wallet.", target); - } -} diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/AppTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/AppTest.java deleted file mode 100644 index da85062f564f..000000000000 --- a/template-method/src/test/java/com/iluwatar/templatemethod/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java deleted file mode 100644 index 6cc80446c0d2..000000000000 --- a/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -/** - * Date: 12/29/15 - 18:15 PM - * - * @author Jeroen Meulemeester - */ -public class HalflingThiefTest { - - /** - * Verify if the thief uses the provided stealing method - */ - @Test - public void testSteal() { - final StealingMethod method = mock(StealingMethod.class); - final HalflingThief thief = new HalflingThief(method); - - thief.steal(); - verify(method).steal(); - - verifyNoMoreInteractions(method); - } - - /** - * Verify if the thief uses the provided stealing method, and the new method after changing it - */ - @Test - public void testChangeMethod() { - final StealingMethod initialMethod = mock(StealingMethod.class); - final HalflingThief thief = new HalflingThief(initialMethod); - - thief.steal(); - verify(initialMethod).steal(); - - final StealingMethod newMethod = mock(StealingMethod.class); - thief.changeMethod(newMethod); - - thief.steal(); - verify(newMethod).steal(); - - verifyNoMoreInteractions(initialMethod, newMethod); - - } -} \ No newline at end of file diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java deleted file mode 100644 index 3bc7b28b49c9..000000000000 --- a/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -/** - * Date: 12/30/15 - 18:12 PM - * - * @author Jeroen Meulemeester - */ -public class HitAndRunMethodTest extends StealingMethodTest { - - /** - * Create a new test for the {@link HitAndRunMethod} - */ - public HitAndRunMethodTest() { - super( - new HitAndRunMethod(), - "old goblin woman", - "The target has been chosen as old goblin woman.", - "Approach the old goblin woman from behind.", - "Grab the handbag and run away fast!" - ); - } - -} \ No newline at end of file diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java deleted file mode 100644 index 98ac62613e2c..000000000000 --- a/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import java.util.LinkedList; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -/** - * Date: 12/30/15 - 18:12 PM - * @param Type of StealingMethod - * @author Jeroen Meulemeester - */ -public abstract class StealingMethodTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * The tested stealing method - */ - private final M method; - - /** - * The expected target - */ - private final String expectedTarget; - - /** - * The expected target picking result - */ - private final String expectedTargetResult; - - /** - * The expected confusion method - */ - private final String expectedConfuseMethod; - - /** - * The expected stealing method - */ - private final String expectedStealMethod; - - /** - * Create a new test for the given stealing method, together with the expected results - * - * @param method The tested stealing method - * @param expectedTarget The expected target name - * @param expectedTargetResult The expected target picking result - * @param expectedConfuseMethod The expected confusion method - * @param expectedStealMethod The expected stealing method - */ - public StealingMethodTest(final M method, String expectedTarget, final String expectedTargetResult, - final String expectedConfuseMethod, final String expectedStealMethod) { - - this.method = method; - this.expectedTarget = expectedTarget; - this.expectedTargetResult = expectedTargetResult; - this.expectedConfuseMethod = expectedConfuseMethod; - this.expectedStealMethod = expectedStealMethod; - } - - /** - * Verify if the thief picks the correct target - */ - @Test - public void testPickTarget() { - assertEquals(expectedTarget, this.method.pickTarget()); - } - - /** - * Verify if the target confusing step goes as planned - */ - @Test - public void testConfuseTarget() { - assertEquals(0, appender.getLogSize()); - - this.method.confuseTarget(this.expectedTarget); - assertEquals(this.expectedConfuseMethod, appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - - /** - * Verify if the stealing step goes as planned - */ - @Test - public void testStealTheItem() { - assertEquals(0, appender.getLogSize()); - - this.method.stealTheItem(this.expectedTarget); - assertEquals(this.expectedStealMethod, appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - - /** - * Verify if the complete steal process goes as planned - */ - @Test - public void testSteal() { - this.method.steal(); - - assertTrue(appender.logContains(this.expectedTargetResult)); - assertTrue(appender.logContains(this.expectedConfuseMethod)); - assertTrue(appender.logContains(this.expectedStealMethod)); - assertEquals(3, 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 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/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java deleted file mode 100644 index 41105c43e42d..000000000000 --- a/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.templatemethod; - -/** - * Date: 12/30/15 - 18:19 PM - * - * @author Jeroen Meulemeester - */ -public class SubtleMethodTest extends StealingMethodTest { - - /** - * Create a new test for the {@link SubtleMethod} - */ - public SubtleMethodTest() { - super( - new SubtleMethod(), - "shop keeper", - "The target has been chosen as shop keeper.", - "Approach the shop keeper with tears running and hug him!", - "While in close contact grab the shop keeper's wallet." - ); - } - -} \ No newline at end of file diff --git a/thread-pool/README.md b/thread-pool/README.md deleted file mode 100644 index 473494ef9349..000000000000 --- a/thread-pool/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: pattern -title: Thread Pool -folder: thread-pool -permalink: /patterns/thread-pool/ -pumlid: JSV14SCW30J0Lk82GFzq8uF6a1624IUx_UIPt-xHhMXK2TTN0zP-4pa_-UfeSSOMBzCWXbpceAxnCDZfmpUdAhjVbXO3uhPfyFw1q5oufZMdag3yFuUFl6Be5m00 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate - - Performance ---- - -## Intent -It is often the case that tasks to be executed are short-lived and -the number of tasks is large. Creating a new thread for each task would make -the system spend more time creating and destroying the threads than executing -the actual tasks. Thread Pool solves this problem by reusing existing threads -and eliminating the latency of creating new threads. - -![alt text](./etc/thread-pool.png "Thread Pool") - -## Applicability -Use the Thread Pool pattern when - -* you have a large number of short-lived tasks to be executed in parallel diff --git a/thread-pool/etc/thread-pool.png b/thread-pool/etc/thread-pool.png deleted file mode 100644 index 9e88a91962466ff5df7768abe04e8f5a9301625d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14796 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 ZnWDj8L-gf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/thread-pool/etc/thread-pool.urm.puml b/thread-pool/etc/thread-pool.urm.puml deleted file mode 100644 index 251033c8157c..000000000000 --- a/thread-pool/etc/thread-pool.urm.puml +++ /dev/null @@ -1,37 +0,0 @@ -@startuml -package com.iluwatar.threadpool { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class CoffeeMakingTask { - - TIME_PER_CUP : int {static} - + CoffeeMakingTask(numCups : int) - + toString() : String - } - class PotatoPeelingTask { - - TIME_PER_POTATO : int {static} - + PotatoPeelingTask(numPotatoes : int) - + toString() : String - } - abstract class Task { - - ID_GENERATOR : AtomicInteger {static} - - id : int - - timeMs : int - + Task(timeMs : int) - + getId() : int - + getTimeMs() : int - + toString() : String - } - class Worker { - - LOGGER : Logger {static} - - task : Task - + Worker(task : Task) - + run() - } -} -Worker --> "-task" Task -CoffeeMakingTask --|> Task -PotatoPeelingTask --|> Task -@enduml \ No newline at end of file diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml deleted file mode 100644 index 94fce2b1608c..000000000000 --- a/thread-pool/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - thread-pool - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/App.java b/thread-pool/src/main/java/com/iluwatar/threadpool/App.java deleted file mode 100644 index 0ca3e9453c1b..000000000000 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/App.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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; -import java.util.concurrent.Executors; - -/** - * - * Thread Pool pattern is where a number of threads are created to perform a number of tasks, which - * are usually organized in a queue. The results from the tasks being executed might also be placed - * in a queue, or the tasks might return no result. Typically, there are many more tasks than - * threads. As soon as a thread completes its task, it will request the next task from the queue - * until all tasks have been completed. The thread can then terminate, or sleep until there are new - * tasks available. - *

    - * In this example we create a list of tasks presenting work to be done. Each task is then wrapped - * into a {@link Worker} object that implements {@link Runnable}. We create an - * {@link ExecutorService} with fixed number of threads (Thread Pool) and use them to execute the - * {@link Worker}s. - * - */ -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) { - - LOGGER.info("Program started"); - - // Create a list of tasks to be executed - List tasks = new ArrayList<>(); - tasks.add(new PotatoPeelingTask(3)); - tasks.add(new PotatoPeelingTask(6)); - tasks.add(new CoffeeMakingTask(2)); - tasks.add(new CoffeeMakingTask(6)); - tasks.add(new PotatoPeelingTask(4)); - tasks.add(new CoffeeMakingTask(2)); - tasks.add(new PotatoPeelingTask(4)); - tasks.add(new CoffeeMakingTask(9)); - tasks.add(new PotatoPeelingTask(3)); - tasks.add(new CoffeeMakingTask(2)); - tasks.add(new PotatoPeelingTask(4)); - tasks.add(new CoffeeMakingTask(2)); - tasks.add(new CoffeeMakingTask(7)); - tasks.add(new PotatoPeelingTask(4)); - tasks.add(new PotatoPeelingTask(5)); - - // Creates a thread pool that reuses a fixed number of threads operating off a shared - // unbounded queue. At any point, at most nThreads threads will be active processing - // tasks. If additional tasks are submitted when all threads are active, they will wait - // in the queue until a thread is available. - ExecutorService executor = Executors.newFixedThreadPool(3); - - // Allocate new worker for each task - // The worker is executed when a thread becomes - // available in the thread pool - for (int i = 0; i < tasks.size(); i++) { - Runnable worker = new Worker(tasks.get(i)); - executor.execute(worker); - } - // All tasks were executed, now shutdown - executor.shutdown(); - while (!executor.isTerminated()) { - Thread.yield(); - } - LOGGER.info("Program finished"); - } -} diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java deleted file mode 100644 index 208b1ac2c678..000000000000 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -/** - * - * CoffeeMakingTask is a concrete task - * - */ -public class CoffeeMakingTask extends Task { - - private static final int TIME_PER_CUP = 100; - - public CoffeeMakingTask(int numCups) { - super(numCups * TIME_PER_CUP); - } - - @Override - public String toString() { - return String.format("%s %s", this.getClass().getSimpleName(), super.toString()); - } -} diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java deleted file mode 100644 index 86c7bb00ed29..000000000000 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -/** - * - * PotatoPeelingTask is a concrete task - * - */ -public class PotatoPeelingTask extends Task { - - private static final int TIME_PER_POTATO = 200; - - public PotatoPeelingTask(int numPotatoes) { - super(numPotatoes * TIME_PER_POTATO); - } - - @Override - public String toString() { - return String.format("%s %s", this.getClass().getSimpleName(), super.toString()); - } -} diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java deleted file mode 100644 index 9ea4996d1b96..000000000000 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * - * Abstract base class for tasks - * - */ -public abstract class Task { - - private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); - - private final int id; - private final int timeMs; - - public Task(final int timeMs) { - this.id = ID_GENERATOR.incrementAndGet(); - this.timeMs = timeMs; - } - - public int getId() { - return id; - } - - public int getTimeMs() { - return timeMs; - } - - @Override - public String toString() { - return String.format("id=%d timeMs=%d", id, timeMs); - } -} diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java deleted file mode 100644 index 578800108bd5..000000000000 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Worker implements {@link Runnable} and thus can be executed by {@link ExecutorService} - * - */ -public class Worker implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(Worker.class); - - private final Task task; - - public Worker(final Task task) { - this.task = task; - } - - @Override - public void run() { - LOGGER.info("{} processing {}", Thread.currentThread().getName(), task.toString()); - try { - Thread.sleep(task.getTimeMs()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } -} diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/AppTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/AppTest.java deleted file mode 100644 index 2d21eec12eae..000000000000 --- a/thread-pool/src/test/java/com/iluwatar/threadpool/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -import org.junit.Test; - -/** - * Application test - * - * @author ilkka - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java deleted file mode 100644 index 00bf1e60a6cb..000000000000 --- a/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -/** - * Date: 12/30/15 - 18:23 PM - * - * @author Jeroen Meulemeester - */ -public class CoffeeMakingTaskTest extends TaskTest { - - /** - * Create a new test instance - */ - public CoffeeMakingTaskTest() { - super(CoffeeMakingTask::new, 100); - } - -} diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java deleted file mode 100644 index 89900fec4da9..000000000000 --- a/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -/** - * Date: 12/30/15 - 18:23 PM - * - * @author Jeroen Meulemeester - */ -public class PotatoPeelingTaskTest extends TaskTest { - - /** - * Create a new test instance - */ - public PotatoPeelingTaskTest() { - super(PotatoPeelingTask::new, 200); - } - -} \ No newline at end of file diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java deleted file mode 100644 index 4a2a06de8c54..000000000000 --- a/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.function.Function; -import java.util.function.IntFunction; -import java.util.function.ToIntFunction; -import java.util.stream.Collectors; -import org.junit.Test; - -/** - * Date: 12/30/15 - 18:22 PM - * Test for Tasks using a Thread Pool - * @param Type of Task - * @author Jeroen Meulemeester - */ -public abstract class TaskTest { - - /** - * The number of tasks used during the concurrency test - */ - private static final int TASK_COUNT = 128 * 1024; - - /** - * The number of threads used during the concurrency test - */ - private static final int THREAD_COUNT = 8; - - /** - * The task factory, used to create new test items - */ - private final IntFunction factory; - - /** - * The expected time needed to run the task 1 single time, in milli seconds - */ - private final int expectedExecutionTime; - - /** - * Create a new test instance - * - * @param factory The task factory, used to create new test items - * @param expectedExecutionTime The expected time needed to run the task 1 time, in milli seconds - */ - public TaskTest(final IntFunction factory, final int expectedExecutionTime) { - this.factory = factory; - this.expectedExecutionTime = expectedExecutionTime; - } - - /** - * Verify if the generated id is unique for each task, even if the tasks are created in separate - * threads - */ - @Test(timeout = 10000) - public void testIdGeneration() throws Exception { - final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT); - - final List> tasks = new ArrayList<>(); - for (int i = 0; i < TASK_COUNT; i++) { - tasks.add(() -> factory.apply(1).getId()); - } - - final List ids = service.invokeAll(tasks) - .stream() - .map(TaskTest::get) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - service.shutdownNow(); - - final long uniqueIdCount = ids.stream() - .distinct() - .count(); - - assertEquals(TASK_COUNT, ids.size()); - assertEquals(TASK_COUNT, uniqueIdCount); - - } - - /** - * Verify if the time per execution of a task matches the actual time required to execute the task - * a given number of times - */ - @Test - public void testTimeMs() { - for (int i = 0; i < 10; i++) { - assertEquals(this.expectedExecutionTime * i, this.factory.apply(i).getTimeMs()); - } - } - - /** - * Verify if the task has some sort of {@link T#toString()}, different from 'null' - */ - @Test - public void testToString() { - assertNotNull(this.factory.apply(0).toString()); - } - - /** - * Extract the result from a future or returns 'null' when an exception occurred - * - * @param future The future we want the result from - * @param The result type - * @return The result or 'null' when a checked exception occurred - */ - private static O get(Future future) { - try { - return future.get(); - } catch (InterruptedException | ExecutionException e) { - return null; - } - } - -} diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java deleted file mode 100644 index 81962ab2aa62..000000000000 --- a/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.threadpool; - -import org.junit.Test; - -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/30/15 - 18:21 PM - * - * @author Jeroen Meulemeester - */ -public class WorkerTest { - - /** - * Verify if a worker does the actual job - */ - @Test - public void testRun() { - final Task task = mock(Task.class); - final Worker worker = new Worker(task); - verifyZeroInteractions(task); - - worker.run(); - verify(task).getTimeMs(); - verifyNoMoreInteractions(task); - } - -} \ No newline at end of file diff --git a/throttling/README.md b/throttling/README.md deleted file mode 100644 index 73d982bffba6..000000000000 --- a/throttling/README.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: pattern -title: Throttling -folder: throttling -permalink: /patterns/throttling/ -categories: Behavioral -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Ensure that a given client is not able to access service resources more than the assigned limit. - -## Applicability -The Throttling pattern should be used: - -* when a service access needs to be restricted to not have high impacts on the performance of the service. -* when multiple clients are consuming the same service resources and restriction has to be made according to the usage per client. diff --git a/throttling/etc/throttling-pattern.png b/throttling/etc/throttling-pattern.png deleted file mode 100644 index a31aa54cea121c248b0246f3b3245c7e9cba5551..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60408 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 bmK}$}uk%ekN%DTE{} "-tenant" Tenant -@enduml \ No newline at end of file diff --git a/throttling/pom.xml b/throttling/pom.xml deleted file mode 100644 index 7c2ee8b9aeb0..000000000000 --- a/throttling/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - java-design-patterns - com.iluwatar - 1.18.0-SNAPSHOT - - 4.0.0 - - throttling - - - junit - junit - - - - \ No newline at end of file diff --git a/throttling/src/main/java/com/iluwatar/throttling/App.java b/throttling/src/main/java/com/iluwatar/throttling/App.java deleted file mode 100644 index 2dce68ab9504..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/App.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.throttling; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.iluwatar.throttling.timer.Throttler; -import com.iluwatar.throttling.timer.ThrottleTimerImpl; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * Throttling pattern is a design pattern to throttle or limit the use of resources or even a complete service by - * users or a particular tenant. This can allow systems to continue to function and meet service level agreements, - * even when an increase in demand places load on resources. - *

    - * In this example we have ({@link App}) as the initiating point of the service. - * This is a time based throttling, i.e. only a certain number of calls are allowed per second. - *

    - * ({@link Tenant}) is the Tenant POJO class with which many tenants can be created - * ({@link B2BService}) is the service which is consumed by the tenants and is throttled. - */ -public class App { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - /** - * Application entry point - * @param args main arguments - */ - public static void main(String[] args) { - - Tenant adidas = new Tenant("Adidas", 5); - Tenant nike = new Tenant("Nike", 6); - - ExecutorService executorService = Executors.newFixedThreadPool(2); - - executorService.execute(() -> makeServiceCalls(adidas)); - executorService.execute(() -> makeServiceCalls(nike)); - - executorService.shutdown(); - try { - executorService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Executor Service terminated: {}", e.getMessage()); - } - } - - /** - * Make calls to the B2BService dummy API - * @param service an instance of B2BService - */ - private static void makeServiceCalls(Tenant tenant) { - Throttler timer = new ThrottleTimerImpl(10); - B2BService service = new B2BService(timer); - for (int i = 0; i < 20; i++) { - service.dummyCustomerApi(tenant); -// Sleep is introduced to keep the output in check and easy to view and analyze the results. - try { - Thread.sleep(1); - } catch (InterruptedException e) { - LOGGER.error("Thread interrupted: {}", e.getMessage()); - } - } - } -} diff --git a/throttling/src/main/java/com/iluwatar/throttling/B2BService.java b/throttling/src/main/java/com/iluwatar/throttling/B2BService.java deleted file mode 100644 index 51ed492ebfcb..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/B2BService.java +++ /dev/null @@ -1,62 +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.throttling; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.iluwatar.throttling.timer.Throttler; - -import java.util.concurrent.ThreadLocalRandom; - -/** - * A service which accepts a tenant and throttles the resource based on the time given to the tenant. - */ -class B2BService { - - private static final Logger LOGGER = LoggerFactory.getLogger(B2BService.class); - - public B2BService(Throttler timer) { - timer.start(); - } - - /** - * - * @return customer id which is randomly generated - */ - public int dummyCustomerApi(Tenant tenant) { - String tenantName = tenant.getName(); - long count = CallsCount.getCount(tenantName); - LOGGER.debug("Counter for {} : {} ", tenant.getName(), count); - if (count >= tenant.getAllowedCallsPerSecond()) { - LOGGER.error("API access per second limit reached for: {}", tenantName); - return -1; - } - CallsCount.incrementCount(tenantName); - return getRandomCustomerId(); - } - - private int getRandomCustomerId() { - return ThreadLocalRandom.current().nextInt(1, 10000); - } -} diff --git a/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java b/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java deleted file mode 100644 index 9b274849a238..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java +++ /dev/null @@ -1,77 +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.throttling; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * A class to keep track of the counter of different Tenants - * @author drastogi - * - */ -public final class CallsCount { - - private static final Logger LOGGER = LoggerFactory.getLogger(CallsCount.class); - private static Map tenantCallsCount = new ConcurrentHashMap<>(); - - /** - * Add a new tenant to the map. - * @param tenantName name of the tenant. - */ - public static void addTenant(String tenantName) { - tenantCallsCount.putIfAbsent(tenantName, new AtomicLong(0)); - } - - /** - * Increment the count of the specified tenant. - * @param tenantName name of the tenant. - */ - public static void incrementCount(String tenantName) { - tenantCallsCount.get(tenantName).incrementAndGet(); - } - - /** - * - * @param tenantName name of the tenant. - * @return the count of the tenant. - */ - public static long getCount(String tenantName) { - return tenantCallsCount.get(tenantName).get(); - } - - /** - * Resets the count of all the tenants in the map. - */ - public static void reset() { - LOGGER.debug("Resetting the map."); - for (Entry e : tenantCallsCount.entrySet()) { - tenantCallsCount.put(e.getKey(), new AtomicLong(0)); - } - } -} diff --git a/throttling/src/main/java/com/iluwatar/throttling/Tenant.java b/throttling/src/main/java/com/iluwatar/throttling/Tenant.java deleted file mode 100644 index a720e154b6d3..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/Tenant.java +++ /dev/null @@ -1,57 +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.throttling; - -import java.security.InvalidParameterException; - -/** - * A Pojo class to create a basic Tenant with the allowed calls per second. - */ -public class Tenant { - - private String name; - private int allowedCallsPerSecond; - - /** - * - * @param name Name of the tenant - * @param allowedCallsPerSecond The number of calls allowed for a particular tenant. - * @throws InvalidParameterException If number of calls is less than 0, throws exception. - */ - public Tenant(String name, int allowedCallsPerSecond) { - if (allowedCallsPerSecond < 0) { - throw new InvalidParameterException("Number of calls less than 0 not allowed"); - } - this.name = name; - this.allowedCallsPerSecond = allowedCallsPerSecond; - CallsCount.addTenant(name); - } - - public String getName() { - return name; - } - - public int getAllowedCallsPerSecond() { - return allowedCallsPerSecond; - } -} diff --git a/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java b/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java deleted file mode 100644 index 4ff4ce2469e7..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java +++ /dev/null @@ -1,58 +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.throttling.timer; - -import java.util.Timer; -import java.util.TimerTask; - -import com.iluwatar.throttling.CallsCount; - -/** - * Implementation of throttler interface. This class resets the counter every second. - * @author drastogi - * - */ -public class ThrottleTimerImpl implements Throttler { - - private int throttlePeriod; - - public ThrottleTimerImpl(int throttlePeriod) { - this.throttlePeriod = throttlePeriod; - } - - /** - * A timer is initiated with this method. The timer runs every second and resets the - * counter. - */ - public void start() { - new Timer(true).schedule(new TimerTask() { - @Override - public void run() { - CallsCount.reset(); - } - }, 0, throttlePeriod); - } -} diff --git a/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java b/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java deleted file mode 100644 index 24b73d92fe91..000000000000 --- a/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java +++ /dev/null @@ -1,36 +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.throttling.timer; - -/** - * An interface for defining the structure of different types of throttling ways. - * @author drastogi - * - */ -public interface Throttler { - - void start(); -} diff --git a/throttling/src/test/java/com/iluwatar/throttling/AppTest.java b/throttling/src/test/java/com/iluwatar/throttling/AppTest.java deleted file mode 100644 index 37c8e75ece95..000000000000 --- a/throttling/src/test/java/com/iluwatar/throttling/AppTest.java +++ /dev/null @@ -1,37 +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.throttling; - -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void test() { - final String[] args = {}; - App.main(args); - } -} diff --git a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java deleted file mode 100644 index aaab62b3a611..000000000000 --- a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java +++ /dev/null @@ -1,48 +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.throttling; - -import org.junit.Assert; -import org.junit.Test; - -import com.iluwatar.throttling.timer.ThrottleTimerImpl; -import com.iluwatar.throttling.timer.Throttler; - -/** - * B2BServiceTest class to test the B2BService - */ -public class B2BServiceTest { - - @Test - public void dummyCustomerApiTest() { - Tenant tenant = new Tenant("testTenant", 2); - Throttler timer = new ThrottleTimerImpl(100); - B2BService service = new B2BService(timer); - - for (int i = 0; i < 5; i++) { - service.dummyCustomerApi(tenant); - } - long counter = CallsCount.getCount(tenant.getName()); - Assert.assertTrue("Counter limit must be reached", counter == 2); - } -} diff --git a/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java b/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java deleted file mode 100644 index 2f0b5cf12a89..000000000000 --- a/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java +++ /dev/null @@ -1,40 +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.throttling; - -import org.junit.Test; - -import com.iluwatar.throttling.Tenant; - -import java.security.InvalidParameterException; - -/** - * TenantTest to test the creation of Tenant with valid parameters. - */ -public class TenantTest { - - @Test(expected = InvalidParameterException.class) - public void constructorTest() { - Tenant tenant = new Tenant("FailTenant", -1); - } -} diff --git a/tls/README.md b/tls/README.md deleted file mode 100644 index 3fb5e9a6b128..000000000000 --- a/tls/README.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: pattern -title: Thread Local Storage -folder: tls -permalink: /patterns/tls/ -pumlid: -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -Securing variables global to a thread against being spoiled by other threads. That is needed if you use class variables or static variables in your Callable object or Runnable object that are not read-only. - -![alt text](./etc/tls.png "Thread Local Storage") - -## Applicability -Use the Thread Local Storage in any of the following situations - -* when you use class variables in your Callable / Runnable object that are not read-only and you use the same Callable instance in more than one thread running in parallel. -* when you use static variables in your Callable / Runnable object that are not read-only and more than one instances of the Callable / Runnable may run in parallel threads. diff --git a/tls/etc/tls.png b/tls/etc/tls.png deleted file mode 100644 index 442f39a0c730b6db350e1a2e0bffba1a2a60e8da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34509 zcmbrmbyQT{+c!SI2#mA?Dvi`2At8;VNHc^qN_TfRNOw0VDJde|Qi9UmCEe2fp3(ch zzw!K@wSMb;|8f@R?7gqr*Y&yL7$OfB$GT5+9|QtnNlJ(+fKK+!-qbDcN3zc{t5rVQ44z7_w z8;smY=^&60=8G0!5e6It1A%Z+2AF}D{h+N75U8W|2m_Q|xd^raB*FS;Nhi1O*t;bi zD@CP^HyiV`RL19-OJC`M<0<%lZzFw`E>x{gN{&?>scL=%0**HM>p=-rjR*%VM>6yz z!V&qEp#__9newO7ZU{(7b@AdJXi%LIzF0ewFUBleQ<8*Yg-3!G9$8#bYyE`M)MBZj zl7-CL5sKX{-B0A*5Ry*g>x~~{#LY#7ZBT;7u`~E(fF*B@!D8DM88irS@j?PQBo;ys zmNoQCtdCLgU=&qdDPr?_>P14yT^kt1f$XgCR#uQ!?;x3IY3F5%vhL&AWmn_kgW&OS zSG<l;r!2pM7l~=3hD@3_ zeTd!!jf3Dq^Heee1Ue?j)CPevXtuz^-3{X`{FC&I6j|Zbk+3rIPx(FD;Bc(75ktm0 zxR5jYF%;zE)%IIIYUw`3=N0~6#ZGmX+y+w@h`(uDrIuHnN9Fb`g8gJi;pnWIDL6!% zu*EX=-M9*WPZ(?!e%?c8mtZ_W7plu z)?1?ltU>56Zj9`Z(E-W4{Uez+2*Tp@{wUA}8DVLUe~bTNI>II?P=7OY59R{}fr5R1 z3-fm7{*bBHdTrXY&VVZ+d5;1Aulcyym3(% z_cXKkoEF{7IzFpWjT4W^8Ixj5J{L^lOG)CxNN!B0^}H+}{xg49af$ z!@6m@5Biz)#o*mdC(7Oa1o;d1%k8_)1ht3e9d3P?0hJfMqOb>6WzYkQA2yBnWe&!# z$w&ukUIN$U%cDO!8iHJ(&)zwYa1`vlO}?HxCva`Izq{}b;n1#ir)(xL^*fG>A-+KK zbMDXf z^=(Ml)*98XL#24}CY4qWargNDT*?p7^J7`LyUw7yl>z~`>4b){nyky1tHU_^I|Yf{ zn9wma+q^X`e|JLu%cMl;Fl>*$Fb6#*^`;OjCAUkkjO)O{A9^FL`7sDSWPs5A?z`Wr zlypGm+JE7Ab47l!p&aFP?umm@rEOdP45H(34hnp_$hxXn93ghx|l#n}XjH zH`|>&WAg3u2fALl<(LVORDIhI*Pl$~sb#Op05|jZ(2{2wchx@Y5CLL;CGw_9fD}9E`7n6#*1Ss13kD^21 zIvzW#ngZv}T>ICT*BnuE2i^i(Rwu_F?+847z4a%TcePj3EzpIc%?MA|COt>TE>@o0NPFbdV|p#(%mA|X@h<5$x(|4&R1*X& zp>&{Q%s)g$KyCV3vB=M-cNX%CUwP z#-_;FUW-~2#fu|Mg!zw&NWmzMahPw;%1JJ+G}mvlF3fLLuK5oy2r7)aaO+@S|K$OO z`H%tt!zKIrKcmC{ML_vqm*_boORv0VB111hkE@s~Bpr@~=BwH3r#0Vh7wp zw(B2Vf7}A+x0Q99EPIeVD-nx*H9Vue2`nnasEN!KnKUlrufs3f2(@ueo8&biGIo!- zG3bw|hUK)`G*Xw_%1SuoHJA25z-z)R!8?>i$joodib7Z0eyws!r?c!vvX<7Y0DfE3c^GJ<< z;^MJGX6l%e8$(P>n07N+BfAPV_^gJFI0OC98E>~K>Tbe`Pk0yLekL=?`RFit;|!mN z3kZq*bs2i#6hyaf380bjBjFrZX`-hdNi|Zt;GfmEw>61g$ZqWA*2HO8Oem%}2nECc zc&1!a(x0d|{pdU+?;Udwc*D=JOmlI0&Yifm9!tj5bLq*Y(@1bR$%|lQZG;3&ed0rE zf4`eZHBE6JA#05y=sG6!j>$m$3=qR#ktI(BX5;abIqckv zeW*J12Nw0rqP3pXlm)`6{T00q;ftrMXkIIeSIjrPjcRnW5ElYu;X%PSY7th2oj0h~ zgUJ8(HY1)5`hyI2gj0n=~F18!o_e>8* z^?e!q>$7&sTu^KktD@ zu~DqbeR5GnhBGy3{>4t`8d%F+$7SQ)%OLF+JEnGO9{3D7y7liRx3IL~bf^j}TV*d^DP0?UW5#As3LX6FrujW~%7|b#ElAVYwqhyv6fi!yawlb1z%1R?k+eL@AaKW3!;bYcQ}|3x;b+ zYJhV*7q4;o5CQf63TYvmtk?60rK+2B_xhu;Pj729o+!Ou0P%j{g?O?H8Om(nLgFC>{z`+ zz$y)_-%diY9J&$muebhp$Tjt8=>&z2&^BiKRuBdBliC4Uv%0Zrulp%TDX4bU+~XM3 zVRNyXq}}LJvG)cbE^82iStu%2C`UAyi$v7(>(}RV+sqfPpZCInhvexX5q<(VD7B~T zZNur#RHc4*Wc_o%R6K2v(N6#+novA?_GYrycBM1y5trq(!|nA&eI*KL(Dt9_VPRqJ zr#pBUSEO70*dU?qHVDP&>m_iuuf;~#&kh%uaSINM`JWl_R1nyBkxbnaV_8} z)-C-4*DTovd62z7gRjQ*Xl-#Nl9Z1&PSSG<3A7==?W^+f0OZNWh3;I-PIhSof(@bo zJDbkBu4jlxl0XCiKJ2`_n!Bz6R>;zYpzK&};&J%f7}$eRQK*-!Aek;PDJiI3*I@Pf`UMmN1d2z4XVbdceqtTx za`Ru*Fbc?7ift z_qKW01dhm95B^$={r6g}yx^!D;krr^huxD0?%(5v#t%DAP{!F~atfa`w9sw}y$^R1 z(UKJO%?Dya-;-o9p`eg^AW$y~Y!KWTMT+0GJ#s2&70>)`IxglXO}apX)(C|rk>m(z z;C6@D7Ig|m5M2|5AJ0zUhuwCh@uY`aGh5!CLqXQl) zs1WrpBL`NjFM@HmJ_6cPD+H35f1VIw2*N==W~~U*#j_CBe~$nnM1So90{LY6L+Qkr zTR#693bMXxOBeEmEuGXgez@iEOxJYp(`Op;vecIaFQl%Oi|!WY2mv`%901WBAgQ(F!P0Guz(KSB z!0gQ^gPhlXcU+R!rRU*UOhOR$3;RVTXA9Lnz;(a|DgK?<=bNjlD$fAQv@_<pl58-Yz9*D3=>P+G)-m=6}T3>w-a+vfZ5-YF&Y*pn|2?e zA{VUt#kI$Ay@!)@ciDNBdC~S-?}D7Ugv@o%et9N}zk1+{WjNI4(N9Vn=f3eFlj24% z$3_l1CUV)_j4+$2H<4ryYocfg(|tU$ms}(-rJl7UVH@=OT+j{okMJOEq1^|JjtIjM zKnG(!&}2zfvWBJU6|NW8!#T^yx997EDc-sRp{4_&=^4X%`+jDZ&S@+#jD!zAQ?ia^# z##vJwx8Ki5XA*!^UM;6)zJj9#5>5Q$+r9OEH|MxdV16L|*ig~!*st2Ec-Ui3$inA) zE(Z9>2k!t=25sj?m6J?I^o~YS>xJ`9qNc|_MJrC%E!t?FSq*W@M?3-oRpf2>sR&ta9<9T z)N_dO=2GA zQ#PD1otk(YZ1_4((CMp51&3-788y!07nN=Ho+5XO_@OzZ8~xDNQc45&*Jj3LhcUfz$%>*NJ7 z2eC|LP$`~Gx#bG9k@J~+5y}vfMu_|?P{~0!f2IWXez_(+Ucd3se={_btj5@@PXksb z8boME*z6tA**icw4dgu}e?^&pOcK!TziA0!5`IkoWj-L#p#4{Qo%X;998fk_ux4|Y zIF1nJ9}9Ct05Fs-aQ4T);sOGxwLL_LK6}Yx>esl&wgZxp$hD6@`E!Idnjy+^-|jtu znpOP-QDi~Y7Cep)arW*~qt$Gx%kD~WMN$I(7!*4|s#(>28|1Gjg@s@MEGqL{LApciP)d} zB-Gvp37}`79|@HW(F}d<3m3Z0S^_U~;a!l2)5aJ)U2#tb(QEy&q4!IRU=ac`_~f5= z$zTWVXK$b;b3k5e;m~!raNcjZd{>-*C*d8D29%Uj^X>1#Mm|jnUlv@Z(LH2Q<4Kja zLDuEW&E|>an(%`E1UB{c&WH%oV1b*^ButD^6L{M#e&8 z%1L?@F~T6RCs9P$_t-X?p~-=Z`RKx$+BQB`%$!VHLX@>c&r0&O7hYlg;_>yKcNU_C zdXqlSrVSp4ocr40-tscscw3%7*C1H>=scIFx4)^fXLs(OoF9JmR6;O=Wi3%9P%{NP z7u?5tibcgRXV0qTTdS=mves_TrOg{Q8uzQj?-zNS=9vacx)9`;LO{s!L5-`V!zJ7q zgXAO;J@JI~UcOZB5*kaF$e0joXFiXVktIWujvQaKrRRG52n77}H8)a~!)*2Nl`f&T zWxo`STO^P(%^H7h8aYj=c9f5{>}#BcbJ9NVN#V+LSB!gq9u@`NXhO&9%^o>KGRvy% zlm3wAT>l7-Sl=^;3%$9DAX$n4eWdycWfAMcA}J{X#=K`K9OantLq`r0&&MDoq@EP- zpo57gQvSF+63Qw?o%0oNp$jzkmKWw9>zuN`z=alAt~3)yCFLrF0@Opb9a_&hukIN$y5ET6yEBR%?@v^eV;x&c_3EtDJCnYh1NJjDAop< zP9*@{aIozhRHZ(*d+3^GBdXbrVZv5Pgzx6Hpn zur(h@QuSz9q*fZJX!cABuL7}4{<~6j2IGc*~~Sk+?T+(A_3@mgYVIv=7cy4BgFZhkMu+V*bDcG$Ww=9;a-#F zxsR@kz((-d&BB(i5Q+eFJgN6{IErFWIkg1=gqj=n9Y+7zY8kOr!P^B|#FManhX5dh z-fr>mGF;`@$9;g&KYo%$AVL?1FweO|q?`~~iS=(2opa{hYWnTkYBet~{`C?R@zRJK z=)p!uM&xBNWrmO3AIFDKkGw~#$?{uV#D&^`i+d_nYNB=a?Q*okOkYcI~!5hMI(&lS62+4z*AbSTRxqjUhXU}rZeQnxkf zub`ca>4MXY=8*)o=AFSYy(ZSC*EHONVvmIG6}#Sm>FtnDA?C4XDHD)do{*maU?8FZ zcmX^^1i~}e6cogupWU7Ko{@U2?G4{M1kdEu~_f?{2#-_V13KIWNW zUNFJFYKtuBF~H#~x|}t47d*o&!6?J!&84X6Pj!2SneyiAy-j zVLXwQJ(m>K(qQZ^EOXL-9=6jB-V+f*T=HzOkeNp6+7al< zF9wFBh03FH_`dt0_(H^+ruDn+n!EN9j3m-}-f5X{A^iD$bZ%3LDJ;te`EU? zvFsEcl*rptcj#;|iDei_T8VV<=*wN0?YP{k10`(lS(;)!*KY3Z0(&*r6S*Yh((0A{fWzT`@#ite5QIAxjUYzk9?sk*Sz^s?MHQW@y+PuiE~ ze2IkBn?-DUH^F}K4`JDf-R0YdWg3h8pGCV&0rTsp)&C(k4KcswXV|<+7>{FnT93wL zP@_fTI*L7FcP&ZSJ^lPvTQQ?nOO;9+E8Jc46>w!c&^$7Jciw6KEc_aBv_U z75e>TCF{=Mc1h6rB+0wsY$eK5WTPEto_bg!Ex<6lKUpWnM*Gz>dJgY*%j~Z+TBnE5 z7~!ql)n8=3jLAN3E^tPEY8=P9$CB?D{ou-Ns9NJEb9ZxMTqr%s9HprBj6Sb}8%(Dx zDH!K+#Z2d#NBD%1P%ix$n&rd))TJYk2G@A3_3AUjx53SKaY@WgR|`!mW!?;m54iaL^eZT0n_?jd#ia{< z5ICJ|-W7MAXSwYte&kJ4HhCm?Jr9#(@;H2FO3=p4+u52*j9_n0y^tjJ(eg57Y4ay%xGx9m4RF&)UJhTR;$+N2sG~@8-=dvt z_Im@_EK@TU2J>v;OE>m9R!>DJg$CN{C=l#?c#8>XRmJ)crlNF2(Z?oL!y_ZdBa!7o zSm08?*$FAE<9NtQy9Q)hA1Mr^a{L!u7Kaf&bHSXVsIb@1{?cL!bmw!Hc~2;jqU+43d; z!Fp_Tz?^0qw)wTsgU{V>xXq*T^RIR}@56j>0Uf=&PnJt4zRB6up$JLWW$XUL9Jd3e z)!^{RwJh_~Udp!4i$tR&Rf1G;{8Xoc+80;xMD{jjJy(H6M+?}hvZ_YSG$vr8rxZcq z*)CW>#S7uy{xGul7?zzR^F2fsg;=!9Jvbz=z3w&Y)?<`50jjq*ej;Z&xwXDq%Hc=S z8g_h#MURF#9wnZ|0Zt-QAfGwMfcnSpt#R3u>C%M`r8dFi-WS)sz2@^zs2`?NFR7+k z3*5HdXhR=hY^kEZcM8URk4Ybl!xlN5p#;mOCJs2PVXcn*AU;s^Rls|m$nspUv@TNd z)H>{2oL!n4OlMB65gIIK{X%$Z@^Lv?jVnVNBwK}{6pBmMdef_o-tvGdI5nBl|rLLzaN_7qB2>nJY(lYeFHi&W#vg9#)- zeMAP1$O22MvCzUh4_px*1R^5nK${ZVsiN+`o>`JuaqVUwLg?;CssGR6 zV+%NirBz%P_UHZX9dPV$fjOy?I58^Vd0PL_Ct-oeqU^>yWYN~lFXJZ|UXEpIcUi|qjX=UH09@#wF90hb+&83PG>Vzpr{moOP-3a9 z!tRZoF$s(ypc=aQr(eCgWt&#>0Fi(W^ZMf7fUh}1eBIR+NjE+7qUnsC_mBgY|UFARVRh^$p=8|>wD zM`g85Q9&Vad%!PqZ{HMTJSc0ss|1`~igni@JskJ7FbK_|d z59#xu^3<5Eg8O_Fu^}yygoDgwk#8iol5XUP2fkH(Q0%L+fIM(YUT)z_39G&iA)EeE zSN>@#mKD~U`HG!6BjcQYTIs2g=4$~abtzu+1$uB`!I_`~KJ$N^w~i0bCj1L4=rDg( z6|pG|iTpB;OV>?8xzw_awqcs#<5x8lxtU$;MU`bbk}a8d3Dy@FNiSb2Ssmgzf1hIj z$P5Wc?vWW3T4ONM6ngV+9|t!Vk-snOi#9v z+jU)+Rw9P8Pze)<#oeQ63AmgQ(O47q$?4cP94RDQRKCc{)f6;bAs}J$$CA5gEy4#3&2+X!-#puz9n=-$wfd(9f{m z*WIl!bU;Ke_lb(At~p{dzN2L3hpuI0Eq3g)M2|s4k5ZOB^!tfmKEok^lc^^o&rU?Z zOJ1)6;^iO~y~M9pA05AZPS<9LStqt1 z@1lK)ZiP8RQS^l zVKq6ahm!_`|My{zV-T<`wcoVQVfu?l??=Ogn5UyI#xt?hS(_yJ3V_QfQfLXRK_Sci zjUPkG7B*x08?>M}uLXS@;X+b5@d3P@Rc_WueLRJpQY$SHJ%J=QE8zOuN-^}Oe-;`g zjCw!ap1+)k2nA&82BaTkd~{uq4wZW)fpHW};m6!w{L^Xd>7}!TcoIYc-?lADZpLlo z1)Ij}HTlc;iu>TLv-A1lvJJTOQiudA63sN?D?|yAG%v!%OI6Y`03s<6_dbX$H=K6< z9wILc+H)8c|2z3i_?>);B9hMpAo&D(mw%GapNQo1EgmAd`w1j>2~!Y@$pg2S7#^Sv zy5+?3m3z~+sB^(Mk7XMfh!(-U@2P+cvKV#rcZS-VO@+u%_d^kv=J$g?5mIrZ*FS!! zgO3s*FPre*7os`^pdSO&;DmzZkxAX6*-~8|A+Ql?{fGiNM{*rp=O$?YfJkekB6@98 zfZRmT4IlgmJXR=H_CW-%xnAwU-?chK!1)KyJB*qUY=S-hiD!RbWIsOADvdrXQv8u_ z^TZ4~?F)lsQCim@rq-8f%Fd%*w{ghoQ505<(l}*|xtE z&|#ku-Our_d#JgQ%0*gllJ)6$(?LaVxP5=8p|QK1kH~a@&hJ-LpatAKt(i+@Q;?&= zPziOp@SHIW=@4wV!>e(OR!g?p0e@bxk>D1j9T&^6M|C@TY4%U5+2x4=4CVx;p1!{7 zyjYTQ9k7RbH$A#3Mj3u(m~O;2d1PW0??l)1{Ieyx_@YX81AgwVYgA{Y#x;Lerl{TwgMXKrP80ye^f{ z4&o0#9ji#aB^+pp*6H>>*AMfDHb5un!51M6MM*^%U$280Xi)TdKNh;j(5@;xQ&U>A<|dL=DtJFz1UT_w)gt5@}1ezTkG2&Ef;&tx6P+nV3BRt^wv}7u#LM3 z=ebq0EpT;O51`2qmy}eRPaG`6aj=XQ*fsuse`?V`nAtTH-b&p}V)%N`#1D3wyeWq)G zx~!0wcwS(9?f~S#^D8m+dojZtow}uQIY;u4^D}}iIX>cm_jR+b6kU+Qn}j(9(Iz!P zIYA_MlB`L&)(xsEF6D`_nY<848hZ05d>U@%c!D1$Ge*lcH0sko*MGR2nJ+Ja{(#J5uLDTp>$b zcs6G0GWfVw(CFX`rM?5xOn8`lG2n~8Iu*2>wjK;(1Yx(hOpg5gbWW!t_F6268nUNC zlYO?0CBra+sT~;&H0*u{0bsu0`#jU!fN=QnI!Dy8726M~GC2=2OALH5h@1Au0411MnQI9_y8)JDm3+cxk|$w*1qg|M%2BE5KDLc)BePpl$yS+tZ<*NQ3-rG1GnwLZ zJ0=pOeT8U!Q6P*@(UtN4v}r#kUIu|vr2XM=U*M*W0Y2+;JcAY`;CwK@jve}r;o*9x z6ite&0luZj*K=N9_Vy%%#6VAgaB&~-;1Z@b$Xz@#@$C5_vdhNySsU)v`%JFYaWcTI zmd-wdeu7t#334?y6{CC(2DsAOJ3foFZrXaU`B0nNZA0^_)9?JTq|Q#me)nP5VV^9+ zCd|hO7}oy1{nKsmc%(o!AJS3d+ID{3Sn2a}oS(MQeg1JBJ51Xaho<-)XPjpb+#OC* zakmW~0s*&UVKd9^@@S9lgP!o!xL!e%8;f@=QeH&5=PI>n4LZ<|5<&;UlgI~X@HR{* zW8zJkCcl@~snDg*>Y;m@C#u8C76U=8o>g!mG+6-%>C0=%);&z0G??^Sm<+4WTSw(6Y^@xREcTXE z+n2@_K?bbHuDF@k_c*5h4TaKW z;pFBXO{5*`8=UoCzeISJUEPYpi1651rNG^;%haD1l_O(LA z$apzWQ>an;1XXj?Qhv2lF*f+)v&_%~-bx!}nzoEcjnWrzoh>AvfC|ki-r@>x;tl4E3&&)8 z0|;W7$ZG2IE5@*d?nqMT!ZHwu0-$suGH@XmkTZk#`&)9tPCd+uwuTns&mfr}xeU;PxxId-1eD(xH}Ij#UAj(;kuhLw63PCK$%#^;-mkg&RH zh_|pmRVfa>B<8Xj^}jt@AJ``T`z#N5Yr*eh*lMtOJq zC~OIH^voH6>=gC^-rD*2*cupr<0c7B0D=+ahPI}rbR8Fv^~M8wRCu|ajV~O`jx5D3 zr8b#lSDj(byN5&4^pk7pNWZkB-S9i=%X|3cKj1{^)Hb^pUTom!b zw6bZA9?;4-QRd%)QRrRf<=VpW1~#5gTnZa~?r!Q=)CH8|feKXd!~ z#A>2FefdFpsD+*5bxce+QFbv(6FzSp5~Aw!D}vH(>vD=EMqzH>U<5@9r5JeO!YzooTD`n;DQesvvmXXg zuyhJ zHk8iB8rL&pE8TrDz05lV*}y6tTbmj=N?42FNPqP+nA_Ly9W*%fqFw=K>?iKh*LN6{ z`2f_;4c>R&o862YS@@E@Adx@bzW=6vOPi^2yD#g4YvHDIVdBo9 zzo$?9ST`0v>H4cBXJtKNNJ>l;^{cN;Nj%0GCLQpaJOOpz9^zHVU+p6~Dq_|3H3aR# zy;nRZ=B_*DXEK}Hhjy3Cfe>8OqsZ-BvXa|fV~M?dRogaO%7+8fS7uA;gPgxB^#`W2djr8|*DDWjl@$m!+8;I|#Tt=8l8b)Wy(f&eA)W zZ#{rwBq#Td=L!U!J41-0ysj39*0JZWW`!$kI+q*OKGI6tAwQ3dvnnJH4xHXLJ$-GG z;Ztb`bXd8Xv*Fn)eS6?!UgG!T-yc)HX>>X4=iA3;y#&yyk*h3`|7`>@S7^4j3uc9# ztE>8XggW++4De;t&=d}neOhi(b$eU(beX&z>T=LyIlk(Uj~AjVUFuvv>t?B@#cjGF z@xZ56xBp|zSl_!VfA!pUIL=rm_UegCi+3r5$U~UCkRXyc9HwLHLv;xm%|}iLy*8#A zb=rL5hu&9XF=YqfXc_Ac!1IJ<-%VENQ#L>HZJvB7=jTQBybAb?>muwqO2`xaPJME5 z>;ill4bB*kG1Jx+D$v3roRAfLwa-g$9JTVHg&ygS>dK@; z!!jfQHCPt%rI;aFA0lCVNT>$ZjYYuJfyZQ?w)!mXg?Z5HqRDl4gV}`--eC3kk0Dy8 zZU>XBQ8ekN@A8_9zN6n$+^tL}H;DB^^R1v4QbWcY4@>y^Bv{D%Xsr)?V;bxlEha|z zh&*rCq9yU0j^A)p$3ZZ97Zy9grushHNA_or-@NE{S&zBya8J&y7=~3FSapfbyY0u6 z@!+mfj4aH1`1WebfHLd;Vn^>Lp0}0@4Kw? zEnIBmM2Y!%0S$^U4!tJyOXD5RL2?V6VWpgKVlSqAUEbrv&V=|F&Nljax$om5s-}6- z-i=2m=OS$#6~k5BR34aO&+`Y=tn1N-I90dC2A?&1JdF>}BQbs}xNtwx#405Mh=XFh zz7LA;sd$Rh-=m(#(IgqV8^4=Vd@|?)GWy96%4O0m~?XTru-rv9O-^V?E^ln!;)hzyy8y0;W#=$vUb#q-3 zlJNQHdL_g7{G=-~>;vre^Tj%oqv~5)j_^t{`_D9FL+AOez3MT`D94L#vVHF-GA)y8?=O`6Hz$pQ8GO#odyeH$Z@J7D zb=B1>?b1~*C&_X@iV;Rxljhv6^v5=mxQ@*u*K zJHO1zDdBS&XNgr}jtopcKOwMPeS5pT=H1!W=ZE!j7)_YvtRtCuPP9u5Pu^bn=H54X z?G8HnK4xc`1NnJW)gpieZ#}PM4R|_i$XdAFYf6B)j_yGP$*e|5gxWogNfvmHTzUK!y`RwqtrzFfnR z7(BBLF0m$D=}}?tuiq3@y9L~{a%?Ar<$%{L9Y9rI5~lkrd(t@di26)$8k9KRpVAM3 zVHDrlU%kqlUNT{CA#=;@uzTvRTy?m^Xy-RN%KVF>hH6t;x9LsA1*_avjM|xHOLg^K z%+b*FHSiVduyVF}P%znqi(gMgysiDrW`XHZ^xcQPXPUtjFIqF4=bv7;0$%}0c_ui; zCZAKd#@oJ5dABx9wGx&#eMEh?wJiQi0O)bW9zhB3y)j$JvMX`WXLA)4e(G~*YuSuG z7GC+R_%jtSOryxggM_LjF8i7j7Hzdh0dCVO1RPgq*=ZF1I$GizN@>Ia*RK2|b;yW}n zt!JFJZuju(`qVQTDKa;E>Mf}ai(Uu#0P5SpQ8*6(d%E>mZTP|7T>FB(*3Lbj&Ky0; zP$u2H@yNuB5$k9;GQo;pw7$YW+>@*k4KDF?r9?c-lz=3r!k?b@7OvXax?N~XWMGH9 zncwdu=0hmWfwEFpJAU+z4~fPllqs_BjjE?&ob=2T#OTYV&k?JX~?pV|hu{cc4T=*>HGf-=! zR2JyJJnkn|_7Giz7ADHTDeSkil^nkn{la`+h=Wpeb-J9J;1KVuDpfi{g@4Re^$H`z zQ=T}-0+^*88=ca?LGtFQBM>Kp>6rD!=GVK@yT7&kGOkRY6iORR+VkwCvZLrGZ~D~f zP6_7iy}4iM>L<&<-WLtf`!Q>vD zdGO+~NXj=1)9PP;IB+6VTQ!l%FY4Ix zb$jktan&dzO|zTiQ}&UpB%ayN4vpzcjiWDrrbxV}&5E9al)&UNcI)`tanCiBt?gt@ zL|Tn!B=}I^GyNnVZf?7&>@hIeI8NUf#Kh^loI1Wz`;)YJ0Lu0KP~GsZ{1T zgT+aHwyKI@Wm0&YJa842R<6p7FHtn%1cr+&`ggil2WujdlK)Ps@OiCl{(eh+S>%UTmX*wiDe z#xUw{C|;EU{ar-5pR`c(cHGTj@x*ak=%?vg3ManEyA>|_Jk!hSJvUGA?ic-ATCVNj z??rW`C0hN-ZrCS|`kT4zW*&Y}iJJCgN(p<~s@T5pyS}X~Oix?n=cCvw;9dgY)I7xu zAJby3!4tHnh@ub;-a2^x3U>D^kGc1O`6zp}@3)9P=Ux9I_sw~9pSW5j!tY0C*%-MQgau!-?QFqf#_3inC`&uBA}!g8*KmoSscv| zAr1EMtUlnSbK#_w=Cds1r2CNGTv*c29aQhAnppb7f9mJ-6Sxqy*MHZVmuIO0?kkMr zJ^?1(xqXKXT*Cr#Of-Y4BIO5(3-gl*flr6Bsh87RiSKlFziUU+j2D{fp;2nfLHVTg zQO&p-9)+js>j6EWWWu(%t|9E8H*yOG-(EklFEr1|2D;`4{R}7AD{?A5KU084t{$_3 ztXv>ap6IS5cj9lY@b(a8R7!UbkblxkMhW)M2yAPbg?}3~0_xVWKY(7tqqbQ*!M!Fm zF)#TWgrw7v;;#S!0 z>KDph2cw>DzIWE<*ayr|oeWe>YYBPL#Ym`05m0o~;~W^srlKh-;^~w%8z|g(#fS7V zqEf$rmZs@}jODjb#rz_tfN4gAe|L@6`XANOp=cSmbb8YJRECa$-!zF{xfe}-c)Dt1 zm*6LzYgnow^6<5t>5msh%0MN{7i#iJD(&?PNhTtKrpGWH6H$h+!BVLbARZYuXfXDg z>C<$+!q5>g>#I03tY51Mr>H9;ea{&NbUp#tIYIWA%x!6K=@E{5D#=4~pp>Zo%U;a= zvgf5=F40$!_kKfF3QdR(iJ5yRP&((o z#7`ObPx~&&*R9L~P9d9DU6AaBJieqPdorYgEQ1w`~- zUT1Bf!vBVDe{|`(IVO*!u3{^~lZ#Xr&zHP4ItuvU)sF@UZ+IU>V z_IEy<)i916u%AT)aOJ$}r!Pa`t!m_!CHI+YvxE|Po%xH=9f84KLwR#S5mW&&1w_x4 z7KSSibPr!1tjKAkBcg1gl3u0W4|WpEC0mH3bbm zL%H>fqB!Bar1d>EUKTUKE~da|L#6gLs(_@i5R{j~h3HE@h=6#0vs>!lYlpm-`lF)U zvvKhQ@3lieBtW^m`cA}`XQJEX+ocZkIOJGfsVc_`Vc0IwAAS#v{uSO5C9W&4$Za*z zLhc!x8z=v=W#OzB40dJdswcvTY|rG8&exMIC=IBD<`Gslmo{jT$Gs({d=;ZrZ^pbH z@x6$j9&5(!JZR*;6BSKm%sBV-NjT4!Rfpwg@rp{8730ywZ({E| zQ_WFb70Iy8UR7J&RbHXa0eI9IihD;H(nej}w+*((t}`d2#Z(pr`i=6NMrvouxAD6b zRA2KhKPG2ka{F>Cj79Pye9@wC=1y3>L*iLAZwJm%w|;GIygSY( z9AE8)YN9xr(_$ol=C?{rW)~#*9*2bZFbOehO3c})#e9nVe>!^$s3^NNY5%R&2^B;H=|(yfq#F^C1_|kqZjtV959)c(`<-*v`u?A_ zX1QjZd7l03eaE%;zV2&h5p4S99VIR@V!M5@|F4-cjcmR0x|QCn8J)|`dp%>aql3bX zZoq>2zO1%Zw9VjDH}l*>Svf*)T|kgHiS#ACa`HH4MfMg1sEt2ph*-OerY|%v5QLo9 zW&(m5lHPA+#7ReM!zam_TYmW`mvz@%pek$N2?=V9?^8 zL+-*d;%-BBDs=08FUi9x+uBd;--=c>ujXeanvA^}7}|Gsy~E$EN;SB`o*ork7ak-+;08Ib`~r1D@22~+l^u++C}sYnzkQ4EG=ynNj1k#* zJT6+z{7%^NT0_fak6a#Egn^q{3_p6kZ$Yma;e`-OUsQor%I zn$&oBtwKcGa35Ua?NwS9x1VlqcQxb;7Z#9xj-~xe|*O#AQ^I49`24dmY!+7ti>U4wX@j`Xg zdbb4WW8!hIlKTi=rAzFwG!8G=K+8DA zeo)~}dM&BXH+{-O+-TZ1UD#}b(W?}Lan(p!;VSP*rYzBnNvQviwO%@+R^LeBG~Cws z>@9W~Auri2KDXy3T_n?8Hc5?%+GWe&R<_U$MKKT&%?$0JWg>284w<{6 zF1zBoh|e;GO7dhB_{{j*B?pl+&5w(|Z2;`Wq6x-651)!lOib5_BiR!}CTsgILI-aR znp+Ft#@0Ov@7X+o=-234@3iRXsecPbs5bQufZ2gG5)jn2Ncc30ly>YzKs~~dX;&kN!$U^W}G`xsT zU5mskBag3Ee+GmiMJe!{9iK)1 zor_>SIo1A}H`(;5$i>^y*_NG&H0$aev+ z)8h>JxWU1}4+5d0&L^Q)Q?!bEma8!Or2Pn{)h zQF(be@OR8N4NXm-51Nzwsq0i^t8!dJdY!tDS3vM>0*M}JXaKVUY84L9%`Jb5I{A|4 zJTAkF&aZn%7YN!k2SdA|1E_q{rpjE&T7Jp2 z;^gPS&YU zvO7C?G{s;hK0{(8LKjGEsaMnT*;K#LjuG4wnYQ* zZmr^_T)-%3^r(W>B99iCVnhAnQ;trgv1Q zOtV0YMKL(s=HSO$TqYf#%TjnP>B4Wbsy2^(Gr>QW5!Aw(<$yt*13VGZN>hnPZ0zg< z3AiRiOaH-xk=Hl#r(;+9=Id}1XAj$6ghRnn(O{&4Iw4ML!$eDCDwaF9v!>f>5` z{M)j?aetDe3;`1W`+}S3`r5DaI1wi+ z=z8W)P9tYbPh30Hb`M`HYM2Z{5#E3{0YPPRr84z@%2v+YUlVuzD(F*oHq9w|G+c6U zP;wCW?DNl1XcEFe)9zn=U*~gInL?qP8Te zB1SyDT51zJi1;fW_XJ0=3eEek z{kpolzky7_3Zf#WU>eob6F>!tz3{uZT9MmrZ{5&@oar@YLxfHhxP+r0reqpK0+kLB zjpjS!vMIb%!A1#Qe%E7Z5E?PGKa6-xvK+ttl}h{oR1MP0lTZL ztgH^kIF+b5Aik7LN7qVM@}p)k@h|6kMJoiDV-%P>g`QkN=$%@f|9 zJ?ndiQO%OT>3El5`g^S=Q=PL{Gf3U69j~qrPo~7PeHk?&MtHvlmC~r14k1iNhW`o} z=H}*@hmb7#uR1_^B5X~2jrN(VlUmGpi>_l<*3fA*p?URzN2X_^77x)O_P6PEmSe|Q zA`o$30k7V%-TW>U>nh2JPC(x5K!H(0hpqmnPSAjX5*w{7Y{es&ggr;W9_p#;U2H_z zBP8;?rdetePicg_7m0rz2;F%zekd(<{2h9{*KaCbXazuQ?~&6M+|A1EkXWYdW!?9* zhuP_bl+e4lyJ3ai_6U+C?AKkeeN`;a83sc!Tep;@f=|o%oZ+C0Gr+*``T$tMJ$~)4 zBEU}r?lO=-ut?vEe!RET{mABfbK0b+^LB;bo~V-|n|7f9r<&#sLdhfQyD?gLG4b{G z={(I@6W@c7SkJx!59uMf^IFD+^D}+$cd$wwEkoEwuNpf2pEMeI9-^vrPpFP|0pH@K zHJ@zdjY`9ilq8gOME&(1;7lEuc3tcMVgd>y5AKNVY%c(^S(C4zJXpYJXfrk7454`^ zeP9aw_?rwP!-r6sSuY`KPQ~9NYWGk}YqZ?vhJS7HNAqtSt}scLe&H5tdr_=MxZMEI z{sbCCCRYGmLI}{~z>pXfR##VBjPg~6pA?| z`KZ<@a7kpD0K2680+OxiMd%8;F096FPY*l!DR3M76iv*f>47r|Ij&|2kt>P;GRTvQ zW?7Iw88}9fkkA*zr_KA`7tdik=3?yzw=}f1^T78neZtN=M~I6Ae_T|bv~Vhbi0Yb3 zaUj^9wE>!^!3?->eSZ5oFU3=o7%6%R1C6_MEl$?a)18Fm8b80WZizs^wcW3Q%i0?#{inKSlUaL}&#(v-Wx;E)c z;ov|cOlW$}0(fgBCJJhSvDHW2g)sRUAgupy&fHrA^y4-Dc3A4JscDU_gxI4cPNClF zD&g@SqLNJ38WA~c8`6ltqfG=A-ZNMi0TDZ~*uxw;xBnCLds)z(k3f1o91X^miPcNoet&tOa*XIqX zaC%=Y3MjCn>u&Ah238|>wqjTwVgNydSy7LuiS*Z-V=?al(-q*)?bzaf(+rdJH4&f< z{sDj13szKk6GO{#x7|ebuL*rAPXgku$5w$eV6R~-dWOVA z>-#ZDNeJJkLcn{gtfwUa1YHDlC%acqe*bsHR+o^|+K8$X2ff&*3qWQoM35mFX5R>t zZS+&R?u{XsK{Q_k(KDkhZ!Z8J{sm*BzmkHu(1tOv+!#4VOeR}^7F}l>8~$hvMjr(P z3(qA@ddxtt@L5gB5rjJy+AW|NpZiJw@x)>p=_?lGpGpDTpxe3-0&o&Wr3A8gp_tDU z*M800$oIF)+IwU0$yj;VdM42VklF(JOgcI`1wuC<4*-Ooz|r~n`HAsyMI!^NvMJKH z$D}LimYmUw^W~VMJf;J9%yT;mnzH!EG%?KXXKnAgq)xvnJ^~hC?*~Xi57>LG0ks$q z&p@laecBRG_AHb6jVVa%dV8}E`4vzN53(mmEuY@WnLbTuOa9&wv5s@`_Y|WnzCf zplyg+7%sJ-`WUL(3?Nu@2-OW%8@(QDP|d}^=6U>6D5=tYQrW6<&PEcN{v?=An`JXA zd-_EkHSg+X?1&cjFjod4blr5H^-~X5@s1&A!4DOSpR|v%soNub7Fz?D(^Rn>44a*? zLXLt>dksd7ea=cQrs=!`bITqP%mNL_;8Qb+B5oKM*^aJzsG~zm9N5qTSa6#gS)4+U zY}q-0feU3ghEEo6mI*tyvWMyv9dU1Rzd^B-iNc%Rd&BJV(2vK>&AvMwgk(I}BVl%R z($^444Ka;&I!Blj(Lm=7iqhj5U`GQq7x%P5T3DYZ zyZ^Foy#)g-4CD=|1#M>mtH?fz6U^jH`xsdak`F-9Z=J(TqgSOBbB|SbQgFsyph0X% z=sQm0_?=&bpDes3iX+pECgPeqm0hl3ax~KC77vepg7+pWz`g5OH&=L9stBa6ggch6 z7#Mm179EI=(J3_lRsg&Jmo8=&OH;fEzTZhzdzj+aE&UguUxBjXze;^#1jhAixR4Jy zOAc%<%d&ShW^9pt3%k9~H$NEfBXJ0eh>1Bq!Etv>ru!1nt#M}V5co+1usoAKTOd{2iIog5E8MY3y+J*NTT;9CFH5s4!BkoCz>mPwoSYVsFrq}dVK`-LpB+Q3Km z=XP}T5M#pYcrEA%;n=NjoVZo0zU>_iPTH0OgwGHFw#?EAWmR|Fp(1Z>a5YG3F7%Vb zyESh&ct)86WJ$ccz|spR|J^$0&F`faqhqwtI6jM1>q_Y7+ZZNb**f9(zxaDJosd?G z`WLZypWT{=bM0EQE6%6xExJPoUY2gy6sboi$6_3ukYSL#Fa!S(Ta13Nyy>fu)4D;T z&qWMh6+Fyf0u0A@9qaq#^;72Wx_%UX%}TG~uSbs;8~3lUX~|`Gacft6pT8z8;4_Z_ zdffJ6An#W@ZA{#ddDS2LUT2Ez7>`tp7BV97!~tr#=WWs+u4E9xypl(zXfz^GX$=hl zT58GRUp!H4)e9mU!xeVM<1x#kpKPA52vZYpLV7sbOlY2wnE8NFrD@&)Ra{kdM?RO_ z9|Jm*gK_2&{w3?B^e7$M)|<`{6Y@Xc2p1#vg9U_9lQhQb?0-#`an)|JaK>t7c%8u>*2+SE>jad3M zcM7KnY=JB3SWgIDL6ERw?q7_a+7mr3G2b}o!UM0kJ@@g5$CN~YK1FU-$ii&8o=R8(2}taA~~`Nwa?8)@I)^pL>Q zm^-*l6eQ*TK0;(srZ`@rc1wxlLFAygIGB4iw|iNW>T#-!{ON+?PFQ)#ShG`%sfV0J zb)k0m!zZ+|Ud)+-zr`=N%5UuMSdetveUWED{0ImYv29(K;jEY|yl?5U{boG$d1x4p zl1=$sZOE&T8!}&)+dk*d292>2hhFiCbEIN!wf55=um8LaSByu^Zz*y1=ArAwoa*%M z2$ELRyfy}$0a% z@6eE#&vDqv(2;4JrxsRUL#9)1{?Os=T{c&yG&E#EJRW;Km}fFxdM++R#ey*j0FdMO z-FGDMl0szjiYKh*)jZ6GQ6wpcFvc4dU&P8!nev?QhlN-A!>#F$)hBP_352k|(2HY)dhi0N!i`coQ%iMw2`fyd3f1rc?C z9CC>M6?B=}CGS*DrixowOS1UXwp+W8g*w%|9T^fYy>7F;GdTVVtYjRf(_`BtB)v&M z9d2FZ?6s~Yp&|YfiDh-x{P|E0f0w`z$-7)}?wIEB-kDc63wJuRzBR85d<*!c?WtxP zRSr)}c&+|b0fI_(*@8vfv}>)*ZY$Ev=Lr7J)AJLHNKwD(yuS`CL+FHL^Nk%R73bTm zOAbdOrQc}Uu&d5zTFED?1e>!`2;rmBH_-H&MLHE~Eq0qXx23wdgMWK_r<1t=V<>XB zPKTnP+Q7o}sStk`o6+#y!$QAGCeX`N@hI#ZT)kozh2#Lmu=B9?$g3<>I%q*~HUsE% zUVj&a>AoM9Qdcn_UBH0Q^LG6ShvD6@ytAJ`y6{`Iq%50&);BLIusiYF%@xn%W9t&m zGd%0EpXAGRL_iqr+zh}p<2+J!EQ3nR|NOZ4gM;Gn?80;9H1cv)uFU5y$jeT&k;0M@ z=s+II&bxL@7X*}xBW|r`yK_iw=*Ey{Boo|pyc*1rNgebuQmtAL!U75qSP;2Ie|`Phu9Fcj0ml9O)NI{2yhN$B>nqFrPQ@a0=&t z3Js~B2U;C5AF$I^QHbPh;6>9cw946g`W4`wUxxX5#qY}?H*knWwr)Ow?7FWhAE76g z?y>1QE}9hrWoJqz3(+Jf3tH>1e+FQ|_LV=yn%1Rilt#|}QGFVP^U{q|YJ`ctOZICk30`*yuvkm;tdBI9zs4D9T)B43XF7%mbgh8csS&r&lWw+Z^8g|JB1 z&sMNEg!Vhe6>5IY?s*EkEM-oTd(mmQEY|bjP1v?L4iH8s)F-p?kT^hX2EMG3W5Sgt z;)fgE*+|Kr`+^^Mb-LABR?U5a+&7zCopheQQkTo%xThD(^~O$uLL}>!Mf&=ro39*y z6s2mFjlzeom2~=v`k@>NOZMq+jG2ST19yYvNes=5m*rz<15*0zdiC!~D&{6UuDws= z#Ibv3<*X`yw!MF5>O+1{q%W)7WbkD(@ERo~SQ7&>Q9s=rPY0GfI8PU=!ajPQ)_ER@ z3D;NyZJcx?2}_fLD-QXUhAyQe<1v2;VePpD!696)|0Cp6UA{JIDzFw;tN9 z!n7p0t^DnXC$iFO<=%{^o-$>bQWtM*dh(M{_1(urB#jT*ow?-cf*7g^B&82-N&Al2 z8z(qt>vu~XsWJcf?2P{EJhm>E$Lq=V2l+q5j|XU}HT0x3-Z;LMj?XNBU&o z{X*!4b=%I&pC%<9gpndtQ|hRQY2@7av~E2r{_fTP zcMaP8rTi0|cNfC3cd%9hcP#zAuLmj2;B@sM@#zEpk&F5_q?e3dnQzh+L}`8!xQV5i zMl+)(7>_#kOl8#%P3)H&WB;mH$vN89@4+WkN!PKC^Hq1*H?I09tl+?lvU4GioW(YS z)TTF&JOsqnbo(KgHV}{!6SeKE?UVUzdfMlIX46#j%~GsLd9g4`LCj@0=Fv=@`()uG zpk`iZBIb-<{t~{M#o7qYWpPfF^n8<0AF$FQEv0;qKZi_2CJ}lsYfXfxx#dKW&9=o% z3lP%_j~+yZzXDzbG>Mol6IVT@bj(d!GT~i#U$*VrN!_1O*I#P)fUdu{ZFv8Q^{?py zfdk{#khnH40F7^X77O6}L;6RhbmK0K`|$TV$8QDt7QFUBS&ruZcY;0^UtJydowOMR zZ8!JR!8)NVQT-Z3^due1l`l2{wcW4+C+nQT8FWc(B%F;?fLvv;3v&dkrv|J?3hN%D z#>1>~?&o-nxK2wKxGm6JKI{1|@8xhf73z5!J{94$yA1Tk4mdYlfie)E(JK8U;hjUF zrJdXd6(wn1Tb-;8Vaui=Xw<~JxL<(0pGhk(ql-J3jXY=6Pcq8B*Wmp6mUUW}JZF6F zZ&dzl<2)TczTsu_ji1L% z8dUc!)GC}3H-+W@b?R}x---z-kPS5zA7CDq=Q}l+l<4imnu8MVzRqum#G3h>JLr<2 zU129BIO7}gO2$!uMhT^5Dx!E%K5&tulOli~?h?&LxT9|hmzBcfMrDbdV*>%KU)N-D zg2E;bKQ^QBj$gP7(U5isv*@7_$;6}Y*Z#6BKdhd>PMJRk4xosQwpH4O*ox<334uknkBBn- zn8l>+YT-epxR>c_>K`TQe3pMamU%gkZf}7FHVBSkI6P)_Wxo?0gEQ)_IQkEa0d|J! z_BP)?a_e>yb?$bWs9spfz)>Qty&QGa;HsEv6*SUl0c77BjrQ){^ww6VM_5O~0W)KG z+5XIuyN&Jr!Ri1bk2--@Ok~#6d&j%nqzdIvH@~J;;OLB=&rmA8UJ|{JcIv*=EJz$6O z{zlnW`$IRPRz0`hXwg>9M#^vwpG1Q~VUoy_(RHONxMJDc1n;f4%IV2>X4@d5%n9Cn z{h^lZ08km957C-ER6KlSD&(oDfza;A3VQM_+*D&iOYXtra<;c8txZ7mJxOmf5!jt`n?Ulp9)>gw$KEAs!ldjm`pV&l>q^y6!RaDaMlF z5j0=G58JKrbZw;l^rj{91;CSx!?5FdBHfdo2ICu-SqBWjX%S}Li9hH+Y{P%h@iwN| zd)>=-&3N=84e!M&%ZLJf7cJP$*^$FobFv4zUf45W!a{-8SyD&s{`O!W5-an{qyr6F zwQ;-VeaKphfi%rU;hz>A8cf`hGDbL<&~VogN>xBdW$5Y{-AsJ%h~7H)3VCW-y0RU@ zf5sDck{291p%mpf7kP8P>T3(}EeDB*-)yNYn})!0`+4u?+e2;gjr|s@O%PL3%U!xw z>6cd&j>%o@A#bis#(pg12;^8R#W{DfE=12$sRek?Rh}e>#M-av)?`&l0TRneqI>fb zR~FF^vkP5AEr?(~JXzH(E4Fs?1F9qp?yf`ED-~X2u>_0IzZ|6JlT&WW-Td??_1$$poU`EsG3UOeil zs&@sml|er}bHt^um*Po%-c9=*i{syzq$FO>R5!nVO$gr={T`GOd5~dZ+0^)pbM#Dv zS*L#S?=t{KAa;B|4=#Ssm#|5Hjye(f1cP#qFj%M@C4cV)AU^mEgV{9(~QE ze>nK8Jrpa%gl0BGsFatMJR~_6 z1w>RjR!s6xrYoB~xkpjN7U}R4oNAajHRAEUS?-m(dpwEJ83NCP9rHT)de{-KjmfUY zqsn-}d2SI3kxr}8W?c1gaL)`L_jp4wp^o6sq4@O8ty6YrWB_!Zw54YWG>tk|bbTr-opIV2vF# zX&01{4|hIR_uAjgO*)$$=%zc`p-ZPJZdulVAUzVA8qhh`Hu?#p!tGZc3g_~*6I$eL z5iEyBb=#LQ&X@u0M?Tae?aPtqNra5L~r~HfOSQsnotxlHx)7Obw?rk^kQ} zS~=eEw4O`;TE=-iF(KpiY^+29_2%fA&S=25VYB}eg)#a;^uC3#I4mYb*^ymNuS^NW6JNXn)!a`2La7`7P z1;{n;(|B)zw&If5B#ut4!V9~0tOhSIHZTl}KRkFCQK9uV=Ke{=dJO3Yo;R6K){>`g ziFZ;_@w~jda)3{jfO0WH&?l-i`fJiynRRcZPd1dA7S!_hD%kEWRVdlwcL z1Y6Ljc}j=@X=V2X)nvrq_nJar^U>gOq9m`)0nWU#lBf@H(H4v?hT$hHdG7MB9_+CF z;&-DVBPH%PLTT!vYkRPge{$0USIKCJe(_Fptqwq%cKS^$n1pjN=5&?vdXx`e<5mt3r9-P&Zx3|EOZ(jL#-wHQL^e!J!&*lINp#9wskLngk zeFU(IpPfI702Z(JzDS^nku~&e_c(v!^jrS%PVeNTyAu*ATk|Efz|n4S!8ZJ?BF*n7 z`OH(KieTG^L)`;wr^C9Rw5}g?TGpF-q`B8*AC(vD_(TtrrWpP+fDFQfPjkhN_XoPY zel9PBo*ah$6#f3D-c^k>6pKk$pdHF9hroX?Fz`kNM_os2k_Wb++Sp>J%J5+L#Pkc!I z<HQ9g&klPc6jbU6??m2w0NW$6pr2=Y|!(IQ$qd0v@@5JmhILQJ`z*1cM!1)%ECsFRiJB~O(6wAKoe@7?3 zkRr+mt4=sq+8U_u?$M;KK-YhCejo}fx5w{*qY#>7f{+W3H{tq+U2xNUQ|M8+i8$Er>tt6ATg#z!bs*>q|Eu% zxZ_bRvSplGTyljjkCUa&T!Ohhg!V}56#fL82h3YA`rlUa(#A@J6fC*qKNcM~FOg^s zrsN}@24O*i7V-L43zx)wrhf#OHJ$_y_3l?Z7xI?Pt*bQxJ*^% z+BJ79Hi#hK+Uoav781&WUR%-0b0N)H)Lp^(aG&peX%Y&C|`rl?;98#-}xS^B3K~b#2#T(_V|k z$O<8DI6yju0}6>V|K2=Rb+ zz`doCEs>dM4}Dw+ns8a+^qQ9|1dY#{kXS?$-KVh9d)Ak-Jkn>v>=t@veZ*wbb6;{W zVGxbt9AnDtOgp4~nO_j#iA#Ge>On2BJQ@{`s2>skK;L5z*fL7JoiO2^3-$eXZSxR4 zBiHtzrfc-Zuf)-U(+}H6`}Ef6nML_N7+=?VdHnEpz##Fm%2QN$m`(wAX^R~V6phjq zGFf|gnPeJ=o-&pgoKM4o6!MvvBQ}r`VOi^VoMa6pA(F=f#{z@HgXW?H(54Un{-!k) zAs%R0P}pyda{vwq9tb#Gh4;U`>-diI>hxqP#%ugIw8ir%>1@mE%x$&d zrY8O04IB~j*_b>T?#Djf)16f1d?iwThX9;`a!0ZcoHZ%il!rzMZST+AFJ}7tCib?_ zz_{F9+c5KR9le%3gNm%i&6t5r@zO?y)NmYUVx7q0{tDHRu8uNizt&p0d(s8O2Y%Z?!t5V4Qyu#~f}d|e zMi$eKH_sZJON4WnbiH2AtN-h^7n9)S_IsUnWgMPA21e6&2ee9hhvcbgR0t>4AGmS5 zE?B!~xI4dZS|5O)c*B33Sfx~6_ z_-b5`>o!D#(}$+2%n7RD@FKfkjfMANrZ z8YyPt2XXe?vz{MbRImB#K^R&78B0L6!Q()&~2zUtqRUg-&LBK)KA7+2BHw7D$Y@tW)`(x>#{!Bbg9<0s=pQ(S!|VI*di~B2z62~)ZAibo7ACPAzAeE3%}f~%8|Nk z>+5p-?N3jI@nX}%d{2W|mLZSIs9_xb-L}+ae-DZ%;z!TGz}nHMknZZ0*ww5uv$VoE zZnAWHT|t zJ)lZosG=F;PSmefm#!*A8>T%7E9+oFkmP+LPu}xneg&X)`-NZOTojSK-M@ceJTYAE z>E(139yI_4X*lyqB8nz|*~a4WlAJ|ym%%$R{P%i#y3?mzkHoZtKUQ_aP4YfPTCF8_ zMfsNaJzh#acL0VdoCuxrtwZ~(4|XIbGIfMZEDVGjO9S!@o~*RJ5O9~hRP}OPt;pN? zeXxCre$%I>V{IRQkGyXEz|-0ize<(q2OCj(I^a~U-zfxN$VY>hGhF#bf4l<30kCcU zI2x$Fm1$yo7i&wHX8E`K+ONW+(U%?uVX=fDlnD1zBc-JSXy*jBZ!a056bFkKTBS-I5fQaJnrs~ln zk^`e#KXv}qYjJ5lg;_&f_w;jE4*Dh7n&R>h`l0R(_a^=oEJ+=qQDQZ_KL-00svX2@ z7OxN_K1TG!*Owb3UP~QUOj;L-s>|%`UoF1h8vJ(`3HTUW)jFT^~2jNcS z`jY)@s}Y4aT3^wkBb1MtX|#bZVBV#zZR)mIPEbnzM9OE8aWBD(Erl@1K$Bvo>uT#53x2b@DJfC)R?MU+yw!R<^dB6vC zY|UkqMy?dAOiubWGO_XNLOItGIPGOj42^6Y*B-vO7ZT#b^~h~qM}+2*gEzH_=iQ5k zH*&H#v*YF~Zr#tgX=-T znVz2~24Oh4CjUZ|8bVY}@3pdIxv>8g-9TD(o(-|<9bhUSk?RE#>w`%dw`=dE zrgv|gX(XVyul)j;{dyucNzw&+1Ja7QUOzt=|2QDA%X>A4({V|x3TP3e)>8i5a{kyc z_3e71!-3{$rNu|_Byc|b9|!$#I?Zal*S+CcTH@;v&c1N;@$%{lSEXb30!=*un(o-2DQLV=$i4e`|0fwpa1hFaH8mQuQ#V8ta9fC6?4>|7wMr=#E%ER5fL%UV;8c z24cFLmKuXT|IW;=k#a{n=is`?rvRlMERN??J^>(=@f@TQ96h`}l2Qi(42SA7UW%nT zN_{usZ+{KtU-ugC{M+N7CDgOM$$UY~y7c_WCRZ@2Uc#*OJ=MSRLT@W92wVM?^420w ztQ{fe3#9w_zlQI{D-UR(;m_=OfAfGIccf2|7Jd74$q)^+SC{`^2Ax{hD~=D8rT+vZ z%);E?2=|}w1RR#BzP?F>c%;S-+mzWqQ~|U<%pU@CnmqWczl%Af9{gEfK0xf!3^5*@ Su=8Tx-<3k&DUf*V`+op$;IV=L diff --git a/tls/etc/tls.ucls b/tls/etc/tls.ucls deleted file mode 100644 index bd238346d0be..000000000000 --- a/tls/etc/tls.ucls +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tls/etc/tls.urm.puml b/tls/etc/tls.urm.puml deleted file mode 100644 index d2eedb371c1a..000000000000 --- a/tls/etc/tls.urm.puml +++ /dev/null @@ -1,23 +0,0 @@ -@startuml -package com.iluwatar.tls { - class App { - + App() - + main(args : String[]) {static} - - printAndCountDates(res : Result) : int {static} - - printAndCountExceptions(res : Result) : int {static} - } - class DateFormatCallable { - - dateValue : String - - df : ThreadLocal - + DateFormatCallable(inDateFormat : String, inDateValue : String) - + call() : Result - } - class Result { - - dateList : List - - exceptionList : List - + Result() - + getDateList() : List - + getExceptionList() : List - } -} -@enduml \ No newline at end of file diff --git a/tls/pom.xml b/tls/pom.xml deleted file mode 100644 index 40d6b2b214ff..000000000000 --- a/tls/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - tls - - - junit - junit - test - - - diff --git a/tls/src/main/java/com/iluwatar/tls/App.java b/tls/src/main/java/com/iluwatar/tls/App.java deleted file mode 100644 index 634d36d26b90..000000000000 --- a/tls/src/main/java/com/iluwatar/tls/App.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import java.util.Calendar; -import java.util.Date; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -/** - * ThreadLocal pattern - *

    - * This App shows how to create an isolated space per each thread. In this - * example the usage of SimpleDateFormat is made to be thread-safe. This is an - * example of the ThreadLocal pattern. - *

    - * By applying the ThreadLocal pattern you can keep track of application - * instances or locale settings throughout the handling of a request. The - * ThreadLocal class works like a static variable, with the exception that it is - * only bound to the current thread! This allows us to use static variables in a - * thread-safe way. - *

    - * In Java, thread-local variables are implemented by the ThreadLocal class - * object. ThreadLocal holds a variable of type T, which is accessible via get/set - * methods. - *

    - * SimpleDateFormat is one of the basic Java classes and is not thread-safe. If - * you do not isolate the instance of SimpleDateFormat per each thread then - * problems arise. - *

    - * App converts the String date value 15/12/2015 to the Date format using the - * Java class SimpleDateFormat. It does this 20 times using 4 threads, each doing - * it 5 times. With the usage of as ThreadLocal in DateFormatCallable everything - * runs well. But if you comment out the ThreadLocal variant (marked with "//TLTL") - * and comment in the non ThreadLocal variant (marked with "//NTLNTL") you can - * see what will happen without the ThreadLocal. Most likely you will get incorrect - * date values and / or exceptions. - *

    - * This example clearly show what will happen when using non thread-safe classes - * in a thread. In real life this may happen one in of 1.000 or 10.000 conversions - * and those are really hard to find errors. - * - * @author Thomas Bauer, 2017 - */ -public class App { - /** - * Program entry point - * - * @param args - * command line args - */ - public static void main(String[] args) { - int counterDateValues = 0; - int counterExceptions = 0; - - // Create a callable - DateFormatCallable callableDf = new DateFormatCallable("dd/MM/yyyy", "15/12/2015"); - // start 4 threads, each using the same Callable instance - ExecutorService executor = Executors.newCachedThreadPool(); - - Future futureResult1 = executor.submit(callableDf); - Future futureResult2 = executor.submit(callableDf); - Future futureResult3 = executor.submit(callableDf); - Future futureResult4 = executor.submit(callableDf); - try { - Result[] result = new Result[4]; - result[0] = futureResult1.get(); - result[1] = futureResult2.get(); - result[2] = futureResult3.get(); - result[3] = futureResult4.get(); - - // Print results of thread executions (converted dates and raised exceptions) - // and count them - for (int i = 0; i < result.length; i++) { - counterDateValues = counterDateValues + printAndCountDates(result[i]); - counterExceptions = counterExceptions + printAndCountExceptions(result[i]); - } - - // a correct run should deliver 20 times 15.12.2015 - // and a correct run shouldn't deliver any exception - System.out.println("The List dateList contains " + counterDateValues + " date values"); - System.out.println("The List exceptionList contains " + counterExceptions + " exceptions"); - - } catch (Exception e) { - System.out.println("Abnormal end of program. Program throws exception: " + e); - } - executor.shutdown(); - } - - /** - * Print result (date values) of a thread execution and count dates - * - * @param res contains results of a thread execution - */ - private static int printAndCountDates(Result res) { - // a correct run should deliver 5 times 15.12.2015 per each thread - int counter = 0; - for (Date dt : res.getDateList()) { - counter++; - Calendar cal = Calendar.getInstance(); - cal.setTime(dt); - // Formatted output of the date value: DD.MM.YYYY - System.out.println( - cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + +cal.get(Calendar.YEAR)); - } - return counter; - } - - /** - * Print result (exceptions) of a thread execution and count exceptions - * - * @param res contains results of a thread execution - * @return number of dates - */ - private static int printAndCountExceptions(Result res) { - // a correct run shouldn't deliver any exception - int counter = 0; - for (String ex : res.getExceptionList()) { - counter++; - System.out.println(ex); - } - return counter; - } -} diff --git a/tls/src/main/java/com/iluwatar/tls/DateFormatCallable.java b/tls/src/main/java/com/iluwatar/tls/DateFormatCallable.java deleted file mode 100644 index a28e24d4e762..000000000000 --- a/tls/src/main/java/com/iluwatar/tls/DateFormatCallable.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.concurrent.Callable; - -/** - * DateFormatCallable converts string dates to a date format using - * SimpleDateFormat. The date format and the date value will be passed to the - * Callable by the constructor. The constructor creates a instance of - * SimpleDateFormat and stores it in a ThreadLocal class variable. For the - * complete description of the example see {@link App} - * - * You can comment out the code marked with //TLTL and comment in the - * code marked //NTLNTL. Then you can see what will happen if you do not - * use the ThreadLocal. For details see the description of {@link App} - * - * @author Thomas Bauer, 2017 - */ -public class DateFormatCallable implements Callable { - // class variables (members) - private ThreadLocal df; //TLTL - // private DateFormat df; //NTLNTL - - private String dateValue; // for dateValue Thread Local not needed - - - /** - * The date format and the date value are passed to the constructor - * - * @param inDateFormat - * string date format string, e.g. "dd/MM/yyyy" - * @param inDateValue - * string date value, e.g. "21/06/2016" - */ - public DateFormatCallable(String inDateFormat, String inDateValue) { - final String idf = inDateFormat; //TLTL - this.df = new ThreadLocal() { //TLTL - @Override //TLTL - protected DateFormat initialValue() { //TLTL - return new SimpleDateFormat(idf); //TLTL - } //TLTL - }; //TLTL - // this.df = new SimpleDateFormat(inDateFormat); //NTLNTL - this.dateValue = inDateValue; - } - - /** - * @see java.util.concurrent.Callable#call() - */ - @Override - public Result call() { - System.out.println(Thread.currentThread() + " started executing..."); - Result result = new Result(); - - // Convert date value to date 5 times - for (int i = 1; i <= 5; i++) { - try { - // this is the statement where it is important to have the - // instance of SimpleDateFormat locally - // Create the date value and store it in dateList - result.getDateList().add(this.df.get().parse(this.dateValue)); //TLTL -// result.getDateList().add(this.df.parse(this.dateValue)); //NTLNTL - } catch (Exception e) { - // write the Exception to a list and continue work - result.getExceptionList().add(e.getClass() + ": " + e.getMessage()); - } - - } - - System.out.println(Thread.currentThread() + " finished processing part of the thread"); - - return result; - } -} diff --git a/tls/src/main/java/com/iluwatar/tls/Result.java b/tls/src/main/java/com/iluwatar/tls/Result.java deleted file mode 100644 index 69ec5c5020f6..000000000000 --- a/tls/src/main/java/com/iluwatar/tls/Result.java +++ /dev/null @@ -1,62 +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. - */ -/* - * Fiducia IT AG, All rights reserved. Use is subject to license terms. - */ - -package com.iluwatar.tls; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Result object that will be returned by the Callable {@link DateFormatCallable} - * used in {@link App} - * - * @author Thomas Bauer, 2017 - */ -public class Result { - // A list to collect the date values created in one thread - private List dateList = new ArrayList(); - - // A list to collect Exceptions thrown in one threads (should be none in - // this example) - private List exceptionList = new ArrayList(); - - /** - * - * @return List of date values collected within an thread execution - */ - public List getDateList() { - return dateList; - } - - /** - * - * @return List of exceptions thrown within an thread execution - */ - public List getExceptionList() { - return exceptionList; - } -} diff --git a/tls/src/test/java/com/iluwatar/tls/AppTest.java b/tls/src/test/java/com/iluwatar/tls/AppTest.java deleted file mode 100644 index 073c0988a850..000000000000 --- a/tls/src/test/java/com/iluwatar/tls/AppTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import org.junit.Test; - -/** - * Tests that thread local storage example runs without errors. - * - * @author Thomas Bauer, January 2017 - * - */ -public class AppTest { - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTest.java b/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTest.java deleted file mode 100644 index b4f24be9bc7d..000000000000 --- a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.BeforeClass; -import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * - * Test of the Callable - * - * In this test {@link DateFormatCallable} is tested with only one thread (i.e. without concurrency situation) - *

    - * After a successful run 5 date values should be in the result object. All dates should have - * the same value (15.11.2015). To avoid problems with time zone not the date instances themselves - * are compared by the test. For the test the dates are converted into string format DD.MM.YYY - *

    - * Additionally the number of list entries are tested for both the list with the date values - * and the list with the exceptions - * - * @author Thomas Bauer, January 2017 - * - */ -public class DateFormatCallableTest { - - // Class variables used in setup() have to be static because setup() has to be static - /** - * Result object given back by DateFormatCallable - * -- Array with converted date values - * -- Array with thrown exceptions - */ - static Result result; - - /** - * The date values created by the run of of DateFormatRunnalbe. List will be filled in the setup() method - */ - static List createdDateValues = new ArrayList(); - - /** - * Expected number of date values in the date value list created by the run of DateFormatRunnalbe - */ - int expectedCounterDateValues = 5; - - /** - * Expected number of exceptions in the exception list created by the run of DateFormatRunnalbe. - */ - int expectedCounterExceptions = 0; - - /** - * Expected content of the list containing the date values created by the run of DateFormatRunnalbe - */ - List expectedDateValues = Arrays.asList("15.11.2015", "15.11.2015", "15.11.2015", "15.11.2015", "15.11.2015"); - - /** - * Run Callable and prepare results for usage in the test methods - */ - @BeforeClass - public static void setup() { - // Create a callable - DateFormatCallable callableDf = new DateFormatCallable("dd/MM/yyyy", "15/12/2015"); - // start thread using the Callable instance - ExecutorService executor = Executors.newCachedThreadPool(); - Future futureResult = executor.submit(callableDf); - try { - result = futureResult.get(); - createdDateValues = convertDatesToString(result); - } catch (Exception e) { - fail("Setup failed: " + e); - } - executor.shutdown(); - } - - private static List convertDatesToString(Result res) { - // Format date value as DD.MM.YYYY - if (res == null || res.getDateList() == null || res.getDateList().size() == 0) { - return null; - } - List returnList = new ArrayList(); - - for (Date dt : res.getDateList()) { - Calendar cal = Calendar.getInstance(); - cal.setTime(dt); - returnList.add(cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + cal.get(Calendar.YEAR)); - } - return returnList; - } - - /** - * Test date values after the run of DateFormatRunnalbe. A correct run should deliver 5 times 15.12.2015 - */ - @Test - public void testDateValues() { - assertEquals(expectedDateValues, createdDateValues); - } - - /** - * Test number of dates in the list after the run of DateFormatRunnalbe. A correct run should deliver 5 date values - */ - @Test - public void testCounterDateValues() { - assertEquals(expectedCounterDateValues, result.getDateList().size()); - } - - /** - * Test number of Exceptions in the list after the run of DateFormatRunnalbe. A correct run should deliver - * no exceptions - */ - @Test - public void testCounterExceptions() { - assertEquals(expectedCounterExceptions, result.getExceptionList().size()); - } -} diff --git a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestIncorrectDateFormat.java b/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestIncorrectDateFormat.java deleted file mode 100644 index e0a1507e91fb..000000000000 --- a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestIncorrectDateFormat.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.BeforeClass; -import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * - * Test of the Callable - * - * In this test {@link DateFormatCallable} is tested with only one thread (i.e. without concurrency situation) - *

    - * An incorrect formatted date is passed to the Callable - * After a successful run 0 date values and 5 exceptions should be in the result object. - * - * @author Thomas Bauer, January 2017 - * - */ -public class DateFormatCallableTestIncorrectDateFormat { - - // Class variables used in setup() have to be static because setup() has to be static - /** - * Result object given back by DateFormatCallable - * -- Array with converted date values - * -- Array with thrown exceptions - */ - static Result result; - - /** - * The date values created by the run of DateFormatRunnalbe. List will be filled in the setup() method - */ - static List createdExceptions = new ArrayList(); - - /** - * Expected number of date values in the date value list created by the run of DateFormatRunnalbe - */ - int expectedCounterDateValues = 0; - - /** - * Expected number of exceptions in the exception list created by the run of DateFormatRunnalbe. - */ - int expectedCounterExceptions = 5; - - /** - * Expected content of the list containing the exceptions created by the run of DateFormatRunnalbe - */ - List expectedExceptions = Arrays.asList("class java.text.ParseException: Unparseable date: \"15.12.2015\"", - "class java.text.ParseException: Unparseable date: \"15.12.2015\"", - "class java.text.ParseException: Unparseable date: \"15.12.2015\"", - "class java.text.ParseException: Unparseable date: \"15.12.2015\"", - "class java.text.ParseException: Unparseable date: \"15.12.2015\""); - - /** - * Run Callable and prepare results for usage in the test methods - */ - @BeforeClass - public static void setup() { - // Create a callable. Pass a string date value not matching the format string - DateFormatCallable callableDf = new DateFormatCallable("dd/MM/yyyy", "15.12.2015"); - // start thread using the Callable instance - ExecutorService executor = Executors.newCachedThreadPool(); - Future futureResult = executor.submit(callableDf); - try { - result = futureResult.get(); - } catch (Exception e) { - fail("Setup failed: " + e); - } - executor.shutdown(); - } - - /** - * Test Exceptions after the run of DateFormatRunnalbe. A correct run should deliver 5 times the - * same exception - */ - @Test - public void testExecptions() { - assertEquals(expectedExceptions, result.getExceptionList()); - } - - /** - * Test number of dates in the list after the run of DateFormatRunnalbe. A correct run should deliver no date values - */ - @Test - public void testCounterDateValues() { - assertEquals(expectedCounterDateValues, result.getDateList().size()); - } - - /** - * Test number of Exceptions in the list after the run of DateFormatRunnalbe. A correct run should - * deliver 5 exceptions - */ - @Test - public void testCounterExceptions() { - assertEquals(expectedCounterExceptions, result.getExceptionList().size()); - } -} diff --git a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestMultiThread.java b/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestMultiThread.java deleted file mode 100644 index 635d6f25ad93..000000000000 --- a/tls/src/test/java/com/iluwatar/tls/DateFormatCallableTestMultiThread.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2016 Thomas Bauer - * - * 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.tls; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.BeforeClass; -import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * - * Test of the Callable - * - * In this test {@link DateFormatCallable} is used by 4 threads in parallel - *

    - * After a successful run 5 date values should be in the result object of each thread. All dates - * should have the same value (15.11.2015). To avoid problems with time zone not the date instances - * themselves are compared by the test. For the test the dates are converted into string format DD.MM.YYY - *

    - * Additionally the number of list entries are tested for both the list with the date values - * and the list with the exceptions - * - * @author Thomas Bauer, January 2017 - * - */ -public class DateFormatCallableTestMultiThread { - - // Class variables used in setup() have to be static because setup() has to be static - /** - * Result object given back by DateFormatCallable, one for each thread - * -- Array with converted date values - * -- Array with thrown exceptions - */ - static Result[] result = new Result[4]; - - /** - * The date values created by the run of of DateFormatRunnalbe. List will be filled in the setup() method - */ - @SuppressWarnings("serial") - static class StringArrayList extends ArrayList { - /* nothing needed here */ - } - static List[] createdDateValues = new StringArrayList[4]; - - /** - * Expected number of date values in the date value list created by each thread - */ - int expectedCounterDateValues = 5; - - /** - * Expected number of exceptions in the exception list created by each thread - */ - int expectedCounterExceptions = 0; - - /** - * Expected content of the list containing the date values created by each thread - */ - List expectedDateValues = Arrays.asList("15.11.2015", "15.11.2015", "15.11.2015", "15.11.2015", "15.11.2015"); - - /** - * Run Callable and prepare results for usage in the test methods - */ - @BeforeClass - public static void setup() { - // Create a callable - DateFormatCallable callableDf = new DateFormatCallable("dd/MM/yyyy", "15/12/2015"); - // start thread using the Callable instance - ExecutorService executor = Executors.newCachedThreadPool(); - Future futureResult1 = executor.submit(callableDf); - Future futureResult2 = executor.submit(callableDf); - Future futureResult3 = executor.submit(callableDf); - Future futureResult4 = executor.submit(callableDf); - try { - result[0] = futureResult1.get(); - result[1] = futureResult2.get(); - result[2] = futureResult3.get(); - result[3] = futureResult4.get(); - for (int i = 0; i < result.length; i++) { - createdDateValues[i] = convertDatesToString(result[i]); - } - } catch (Exception e) { - fail("Setup failed: " + e); - } - executor.shutdown(); - } - - private static List convertDatesToString(Result res) { - // Format date value as DD.MM.YYYY - if (res == null || res.getDateList() == null || res.getDateList().size() == 0) { - return null; - } - List returnList = new StringArrayList(); - - for (Date dt : res.getDateList()) { - Calendar cal = Calendar.getInstance(); - cal.setTime(dt); - returnList.add(cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + cal.get(Calendar.YEAR)); - } - return returnList; - } - - /** - * Test date values after the run of DateFormatRunnalbe. A correct run should deliver 5 times 15.12.2015 - * by each thread - */ - @Test - public void testDateValues() { - for (int i = 0; i < createdDateValues.length; i++) { - assertEquals(expectedDateValues, createdDateValues[i]); - } - } - - /** - * Test number of dates in the list after the run of DateFormatRunnalbe. A correct run should - * deliver 5 date values by each thread - */ - @Test - public void testCounterDateValues() { - for (int i = 0; i < result.length; i++) { - assertEquals(expectedCounterDateValues, result[i].getDateList().size()); - } - } - - /** - * Test number of Exceptions in the list after the run of DateFormatRunnalbe. A correct run should - * deliver no exceptions - */ - @Test - public void testCounterExceptions() { - for (int i = 0; i < result.length; i++) { - assertEquals(expectedCounterExceptions, result[i].getExceptionList().size()); - } - } -} diff --git a/tolerant-reader/README.md b/tolerant-reader/README.md deleted file mode 100644 index 5d1cf80fd22a..000000000000 --- a/tolerant-reader/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: pattern -title: Tolerant Reader -folder: tolerant-reader -permalink: /patterns/tolerant-reader/ -pumlid: NSZ14SCm20NHLf829ExfXaYChGn26lZ4xSVdtFRjSrZJx9AkZnFOyI9olkenSEOxGxmjWnXgMvE6viLWfmz_kNI9SLZP38XRqEIuWx1Kd0t5XVjjGVj_DNtMdLD_ -categories: Integration -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Tolerant Reader is an integration pattern that helps creating -robust communication systems. The idea is to be as tolerant as possible when -reading data from another service. This way, when the communication schema -changes, the readers must not break. - -![alt text](./etc/tolerant-reader.png "Tolerant Reader") - -## Applicability -Use the Tolerant Reader pattern when - -* the communication schema can evolve and change and yet the receiving side should not break - -## Credits - -* [Martin Fowler - Tolerant Reader](http://martinfowler.com/bliki/TolerantReader.html) diff --git a/tolerant-reader/etc/tolerant-reader.png b/tolerant-reader/etc/tolerant-reader.png deleted file mode 100644 index 45f0302a2c7bd80c975f20ed67eb700d0224e368..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20514 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%0APyX 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 diff --git a/tolerant-reader/etc/tolerant-reader.ucls b/tolerant-reader/etc/tolerant-reader.ucls deleted file mode 100644 index 92e069f8e6e1..000000000000 --- a/tolerant-reader/etc/tolerant-reader.ucls +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tolerant-reader/etc/tolerant-reader.urm.puml b/tolerant-reader/etc/tolerant-reader.urm.puml deleted file mode 100644 index a73394a4ed7d..000000000000 --- a/tolerant-reader/etc/tolerant-reader.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.tolerantreader { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class RainbowFish { - - age : int - - lengthMeters : int - - name : String - - serialVersionUID : long {static} - - weightTons : int - + RainbowFish(name : String, age : int, lengthMeters : int, weightTons : int) - + getAge() : int - + getLengthMeters() : int - + getName() : String - + getWeightTons() : int - } - class RainbowFishSerializer { - - RainbowFishSerializer() - + readV1(filename : String) : RainbowFish {static} - + writeV1(rainbowFish : RainbowFish, filename : String) {static} - + writeV2(rainbowFish : RainbowFishV2, filename : String) {static} - } - class RainbowFishV2 { - - angry : boolean - - hungry : boolean - - serialVersionUID : long {static} - - sleeping : boolean - + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int) - + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int, sleeping : boolean, hungry : boolean, angry : boolean) - + getAngry() : boolean - + getHungry() : boolean - + getSleeping() : boolean - } -} -RainbowFishV2 --|> RainbowFish -@enduml \ No newline at end of file diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml deleted file mode 100644 index 7e3561f80b6d..000000000000 --- a/tolerant-reader/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - tolerant-reader - - - junit - junit - test - - - diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java deleted file mode 100644 index c2493338455b..000000000000 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -/** - * - * Tolerant Reader is an integration pattern that helps creating robust communication systems. The - * idea is to be as tolerant as possible when reading data from another service. This way, when the - * communication schema changes, the readers must not break. - *

    {=^~r1=1stT~bBS&d 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/twin/etc/twin.urm.puml b/twin/etc/twin.urm.puml deleted file mode 100644 index e48298f18262..000000000000 --- a/twin/etc/twin.urm.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -package com.iluwatar.twin { - class App { - + App() - + main(args : String[]) {static} - - waiting() {static} - } - class BallItem { - - LOGGER : Logger {static} - - isSuspended : boolean - - twin : BallThread - + BallItem() - + click() - + doDraw() - + move() - + setTwin(twin : BallThread) - } - abstract class GameItem { - - LOGGER : Logger {static} - + GameItem() - + click() {abstract} - + doDraw() {abstract} - + draw() - } -} -BallItem --|> GameItem -@enduml \ No newline at end of file diff --git a/twin/pom.xml b/twin/pom.xml deleted file mode 100644 index 62d138fd9ef8..000000000000 --- a/twin/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - twin - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/twin/src/main/java/com/iluwatar/twin/App.java b/twin/src/main/java/com/iluwatar/twin/App.java deleted file mode 100644 index f31ca43266f3..000000000000 --- a/twin/src/main/java/com/iluwatar/twin/App.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.twin; - -/** - * Twin pattern is a design pattern which provides a standard solution to simulate multiple - * inheritance in java. - *

    - * In this example, the essence of the Twin pattern is the {@link BallItem} class and - * {@link BallThread} class represent the twin objects to coordinate with each other(via the twin - * reference) like a single class inheriting from {@link GameItem} and {@link Thread}. - */ - -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) throws Exception { - - BallItem ballItem = new BallItem(); - BallThread ballThread = new BallThread(); - - ballItem.setTwin(ballThread); - ballThread.setTwin(ballItem); - - ballThread.start(); - - waiting(); - - ballItem.click(); - - waiting(); - - ballItem.click(); - - waiting(); - - // exit - ballThread.stopMe(); - } - - private static void waiting() throws Exception { - Thread.sleep(750); - } -} diff --git a/twin/src/main/java/com/iluwatar/twin/BallItem.java b/twin/src/main/java/com/iluwatar/twin/BallItem.java deleted file mode 100644 index 54b8cac3a0d5..000000000000 --- a/twin/src/main/java/com/iluwatar/twin/BallItem.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -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 - * resume task. - */ -public class BallItem extends GameItem { - - private static final Logger LOGGER = LoggerFactory.getLogger(BallItem.class); - - private boolean isSuspended; - - private BallThread twin; - - public void setTwin(BallThread twin) { - this.twin = twin; - } - - @Override - public void doDraw() { - - LOGGER.info("doDraw"); - } - - public void move() { - LOGGER.info("move"); - } - - @Override - public void click() { - - isSuspended = !isSuspended; - - if (isSuspended) { - twin.suspendMe(); - } else { - twin.resumeMe(); - } - } -} - diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java deleted file mode 100644 index f2b64e467bb9..000000000000 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -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. - * - */ - -public class BallThread extends Thread { - - private static final Logger LOGGER = LoggerFactory.getLogger(BallThread.class); - - private BallItem twin; - - private volatile boolean isSuspended; - - private volatile boolean isRunning = true; - - public void setTwin(BallItem twin) { - this.twin = twin; - } - - /** - * Run the thread - */ - public void run() { - - while (isRunning) { - if (!isSuspended) { - twin.draw(); - twin.move(); - } - try { - Thread.sleep(250); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - - public void suspendMe() { - isSuspended = true; - LOGGER.info("Begin to suspend BallThread"); - } - - public void resumeMe() { - isSuspended = false; - LOGGER.info("Begin to resume BallThread"); - } - - public void stopMe() { - this.isRunning = false; - this.isSuspended = true; - } -} - diff --git a/twin/src/main/java/com/iluwatar/twin/GameItem.java b/twin/src/main/java/com/iluwatar/twin/GameItem.java deleted file mode 100644 index 46e19283f4ca..000000000000 --- a/twin/src/main/java/com/iluwatar/twin/GameItem.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -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() { - LOGGER.info("draw"); - doDraw(); - } - - public abstract void doDraw(); - - - public abstract void click(); -} diff --git a/twin/src/test/java/com/iluwatar/twin/AppTest.java b/twin/src/test/java/com/iluwatar/twin/AppTest.java deleted file mode 100644 index 60e02e4c412d..000000000000 --- a/twin/src/test/java/com/iluwatar/twin/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.twin; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} diff --git a/twin/src/test/java/com/iluwatar/twin/BallItemTest.java b/twin/src/test/java/com/iluwatar/twin/BallItemTest.java deleted file mode 100644 index 5dad024814c3..000000000000 --- a/twin/src/test/java/com/iluwatar/twin/BallItemTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.twin; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import java.util.LinkedList; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InOrder; -import org.slf4j.LoggerFactory; - -/** - * Date: 12/30/15 - 18:44 PM - * - * @author Jeroen Meulemeester - */ -public class BallItemTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - @Test - public void testClick() { - final BallThread ballThread = mock(BallThread.class); - final BallItem ballItem = new BallItem(); - ballItem.setTwin(ballThread); - - final InOrder inOrder = inOrder(ballThread); - - for (int i = 0; i < 10; i++) { - ballItem.click(); - inOrder.verify(ballThread).suspendMe(); - - ballItem.click(); - inOrder.verify(ballThread).resumeMe(); - } - - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testDoDraw() { - final BallItem ballItem = new BallItem(); - final BallThread ballThread = mock(BallThread.class); - ballItem.setTwin(ballThread); - - ballItem.draw(); - assertTrue(appender.logContains("draw")); - assertTrue(appender.logContains("doDraw")); - - verifyNoMoreInteractions(ballThread); - assertEquals(2, appender.getLogSize()); - } - - @Test - public void testMove() { - final BallItem ballItem = new BallItem(); - final BallThread ballThread = mock(BallThread.class); - ballItem.setTwin(ballThread); - - ballItem.move(); - assertTrue(appender.logContains("move")); - - verifyNoMoreInteractions(ballThread); - assertEquals(1, appender.getLogSize()); - } - - /** - * Logging Appender Implementation - */ - public class InMemoryAppender extends AppenderBase { - private List log = new LinkedList<>(); - - public InMemoryAppender() { - ((Logger) LoggerFactory.getLogger("root")).addAppender(this); - start(); - } - - @Override - protected void append(ILoggingEvent eventObject) { - log.add(eventObject); - } - - public boolean logContains(String message) { - return log.stream().anyMatch(event -> event.getMessage().equals(message)); - } - - public int getLogSize() { - return log.size(); - } - } - -} diff --git a/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java b/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java deleted file mode 100644 index f531a24931d5..000000000000 --- a/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.twin; - -import org.junit.Test; - -import static java.lang.Thread.UncaughtExceptionHandler; -import static java.lang.Thread.sleep; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; - -/** - * Date: 12/30/15 - 18:55 PM - * - * @author Jeroen Meulemeester - */ -public class BallThreadTest { - - /** - * Verify if the {@link BallThread} can be resumed - */ - @Test(timeout = 5000) - public void testSuspend() throws Exception { - final BallThread ballThread = new BallThread(); - - final BallItem ballItem = mock(BallItem.class); - ballThread.setTwin(ballItem); - - ballThread.start(); - - verify(ballItem, timeout(2000).atLeastOnce()).draw(); - verify(ballItem, timeout(2000).atLeastOnce()).move(); - ballThread.suspendMe(); - - sleep(1000); - - ballThread.stopMe(); - ballThread.join(); - - verifyNoMoreInteractions(ballItem); - } - - /** - * Verify if the {@link BallThread} can be resumed - */ - @Test(timeout = 5000) - public void testResume() throws Exception { - final BallThread ballThread = new BallThread(); - - final BallItem ballItem = mock(BallItem.class); - ballThread.setTwin(ballItem); - - ballThread.suspendMe(); - ballThread.start(); - - sleep(1000); - - verifyZeroInteractions(ballItem); - - ballThread.resumeMe(); - verify(ballItem, timeout(2000).atLeastOnce()).draw(); - verify(ballItem, timeout(2000).atLeastOnce()).move(); - - ballThread.stopMe(); - ballThread.join(); - - verifyNoMoreInteractions(ballItem); - } - - /** - * Verify if the {@link BallThread} is interruptible - */ - @Test(timeout = 5000) - public void testInterrupt() throws Exception { - final BallThread ballThread = new BallThread(); - final UncaughtExceptionHandler exceptionHandler = mock(UncaughtExceptionHandler.class); - ballThread.setUncaughtExceptionHandler(exceptionHandler); - ballThread.setTwin(mock(BallItem.class)); - ballThread.start(); - ballThread.interrupt(); - ballThread.join(); - - verify(exceptionHandler).uncaughtException(eq(ballThread), any(RuntimeException.class)); - verifyNoMoreInteractions(exceptionHandler); - } -} \ No newline at end of file diff --git a/update-ghpages.sh b/update-ghpages.sh deleted file mode 100644 index d240453b0755..000000000000 --- a/update-ghpages.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# -# The MIT License -# Copyright (c) 2014-2016 Ilkka Seppälä -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - - -# Clone gh-pages -git clone -b gh-pages "https://${gh_ref}/" ghpagesclone -cd ghpagesclone - -# Init and update submodule to latest -git submodule update --init --recursive -git submodule update --remote - -# Setup Git -git config user.name "Travis-CI" -git config user.email "travis@no.reply" - -# If there is a new version of the master branch -if git status | grep patterns > /dev/null 2>&1 -then - # it should be committed - git add . - git commit -m ":sparkles: :up: Automagic Update via Travis-CI" - git push --quiet "https://$%7BGH_TOKEN%7D:x-oauth-basic@${gh_ref}/" gh-pages > /dev/null 2>&1 -fi diff --git a/value-object/README.md b/value-object/README.md deleted file mode 100644 index a8e707b055d3..000000000000 --- a/value-object/README.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: pattern -title: Value Object -folder: value-object -permalink: /patterns/value-object/ -pumlid: LSZ13SCm20NGLTe1RExTXX2KECBOmfza_VRQszDxDnVBNJFiTG9pVOY2dteqdBdbqf3XK4ULqQbPFWmEklZcikjgXvV9W8Olwhn-e9ijjOpjKW4fv2zgHgypktq1 -categories: Creational -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Provide 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 have the same value, not necessarily being the same object. - -![alt text](./etc/value-object.png "Value Object") - -## Applicability -Use the Value Object when - -* you need to measure the objects' equality based on the objects' value - -## Real world examples - -* [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) -* [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html) -* [joda-time, money, beans](http://www.joda.org/) - -## Credits - -* [Patterns of Enterprise Application Architecture](http://www.martinfowler.com/books/eaa.html) -* [VALJOs - Value Java Objects : Stephen Colebourne's blog](http://blog.joda.org/2014/03/valjos-value-java-objects.html) -* [Value Object : Wikipedia](https://en.wikipedia.org/wiki/Value_object) diff --git a/value-object/etc/value-object.png b/value-object/etc/value-object.png deleted file mode 100644 index 69a244c80691b8ac63ed5b732b8b0828c592a1f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5025 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 diff --git a/value-object/etc/value-object.ucls b/value-object/etc/value-object.ucls deleted file mode 100644 index 7bbf5e47cfbd..000000000000 --- a/value-object/etc/value-object.ucls +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/value-object/etc/value-object.urm.puml b/value-object/etc/value-object.urm.puml deleted file mode 100644 index 6149ead9ba36..000000000000 --- a/value-object/etc/value-object.urm.puml +++ /dev/null @@ -1,22 +0,0 @@ -@startuml -package com.iluwatar.value.object { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class HeroStat { - - intelligence : int - - luck : int - - strength : int - - HeroStat(strength : int, intelligence : int, luck : int) - + equals(obj : Object) : boolean - + getIntelligence() : int - + getLuck() : int - + getStrength() : int - + hashCode() : int - + toString() : String - + valueOf(strength : int, intelligence : int, luck : int) : HeroStat {static} - } -} -@enduml \ No newline at end of file diff --git a/value-object/pom.xml b/value-object/pom.xml deleted file mode 100644 index fa4c06697fce..000000000000 --- a/value-object/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - value-object - - - com.google.guava - guava-testlib - 19.0 - test - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index 82963ec8fea5..000000000000 --- a/value-object/src/main/java/com/iluwatar/value/object/App.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -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 - * have the same value, not necessarily being the same object.. - * - * Value Objects must override equals(), hashCode() to check the equality with values. - * Value Objects should be immutable so declare members final. - * Obtain instances by static factory methods. - * The elements of the state must be other values, including primitive types. - * Provide methods, typically simple getters, to get the elements of the state. - * A Value Object must check equality with equals() not == - * - * For more specific and strict rules to implement value objects check the rules from Stephen - * 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. - */ - public static void main(String[] args) { - HeroStat statA = HeroStat.valueOf(10, 5, 0); - HeroStat statB = HeroStat.valueOf(10, 5, 0); - HeroStat statC = HeroStat.valueOf(5, 1, 8); - - LOGGER.info(statA.toString()); - - LOGGER.info("Is statA and statB equal : {}", statA.equals(statB)); - LOGGER.info("Is statA and statC equal : {}", statA.equals(statC)); - } -} diff --git a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java b/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java deleted file mode 100644 index ff85e0e934dc..000000000000 --- a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.value.object; - -/** - * HeroStat is a value object - * - * {@link http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html} - */ -public class HeroStat { - - // Stats for a hero - - private final int strength; - private final int intelligence; - private final int luck; - - // All constructors must be private. - private HeroStat(int strength, int intelligence, int luck) { - super(); - this.strength = strength; - this.intelligence = intelligence; - this.luck = luck; - } - - // Static factory method to create new instances. - public static HeroStat valueOf(int strength, int intelligence, int luck) { - return new HeroStat(strength, intelligence, luck); - } - - public int getStrength() { - return strength; - } - - public int getIntelligence() { - return intelligence; - } - - public int getLuck() { - return luck; - } - - /* - * Recommended to provide a static factory method capable of creating an instance from the formal - * string representation declared like this. public static HeroStat parse(String string) {} - */ - - // toString, hashCode, equals - - @Override - public String toString() { - return "HeroStat [strength=" + strength + ", intelligence=" + intelligence - + ", luck=" + luck + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + intelligence; - result = prime * result + luck; - result = prime * result + strength; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - HeroStat other = (HeroStat) obj; - if (intelligence != other.intelligence) { - return false; - } - if (luck != other.luck) { - return false; - } - if (strength != other.strength) { - return false; - } - return true; - } - - // The clone() method should not be public. Just don't override it. - -} diff --git a/value-object/src/test/java/com/iluwatar/value/object/AppTest.java b/value-object/src/test/java/com/iluwatar/value/object/AppTest.java deleted file mode 100644 index cd0b1354f38a..000000000000 --- a/value-object/src/test/java/com/iluwatar/value/object/AppTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.value.object; - -import org.junit.Test; - -/** - * Application test - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java b/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java deleted file mode 100644 index b7b65b6c6991..000000000000 --- a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.value.object; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; - -import static org.junit.Assert.assertThat; - -import com.google.common.testing.EqualsTester; - -import org.junit.Test; - -/** - * Unit test for HeroStat. - */ -public class HeroStatTest { - - /** - * Tester for equals() and hashCode() methods of a class. Using guava's EqualsTester. - * - * @see http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/ - * EqualsTester.html - */ - @Test - public void testEquals() { - HeroStat heroStatA = HeroStat.valueOf(3, 9, 2); - HeroStat heroStatB = HeroStat.valueOf(3, 9, 2); - new EqualsTester().addEqualityGroup(heroStatA, heroStatB).testEquals(); - } - - /** - * The toString() for two equal values must be the same. For two non-equal values it must be - * different. - */ - @Test - public void testToString() { - HeroStat heroStatA = HeroStat.valueOf(3, 9, 2); - HeroStat heroStatB = HeroStat.valueOf(3, 9, 2); - HeroStat heroStatC = HeroStat.valueOf(3, 9, 8); - - assertThat(heroStatA.toString(), is(heroStatB.toString())); - assertThat(heroStatA.toString(), is(not(heroStatC.toString()))); - } - -} diff --git a/visitor/README.md b/visitor/README.md deleted file mode 100644 index 23ffc3af7caf..000000000000 --- a/visitor/README.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -layout: pattern -title: Visitor -folder: visitor -permalink: /patterns/visitor/ -pumlid: DSR14OGm20NGLhG0mtsxmSWeJa8oyD7sTo_xJczLgoqFIM_B1Spu43c_vLHSkMU8rs4GGwcZaxPy6UnqyyFR8Q6dRPC1SGlg7B_Gew4OJeBwVqdlPMPlNm00 -categories: Behavioral -tags: - - Java - - Difficulty-Intermediate - - Gang Of Four ---- - -## Intent -Represent an operation to be performed on the elements of an object -structure. Visitor lets you define a new operation without changing the classes -of the elements on which it operates. - -![alt text](./etc/visitor_1.png "Visitor") - -## Applicability -Use the Visitor pattern when - -* an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes -* many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them -* the classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes - -## Real world examples - -* [Apache Wicket](https://github.com/apache/wicket) component tree, see [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java) -* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) and [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html) -* [javax.lang.model.element.Element](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html) and [Element Visitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html) -* [java.nio.file.FileVisitor](http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html) - -## Credits - -* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) diff --git a/visitor/etc/visitor.png b/visitor/etc/visitor.png deleted file mode 100644 index 5bbee60eeabf0d474e4cad4c09249c5947abe593..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22790 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 diff --git a/visitor/etc/visitor.ucls b/visitor/etc/visitor.ucls deleted file mode 100644 index 17fe353265cf..000000000000 --- a/visitor/etc/visitor.ucls +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/visitor/etc/visitor.urm.puml b/visitor/etc/visitor.urm.puml deleted file mode 100644 index 36a67b41514b..000000000000 --- a/visitor/etc/visitor.urm.puml +++ /dev/null @@ -1,60 +0,0 @@ -@startuml -package com.iluwatar.visitor { - class App { - + App() - + main(args : String[]) {static} - } - class Commander { - + Commander(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class CommanderVisitor { - - LOGGER : Logger {static} - + CommanderVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - class Sergeant { - + Sergeant(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class SergeantVisitor { - - LOGGER : Logger {static} - + SergeantVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - class Soldier { - + Soldier(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class SoldierVisitor { - - LOGGER : Logger {static} - + SoldierVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - abstract class Unit { - - children : Unit[] - + Unit(children : Unit[]) - + accept(visitor : UnitVisitor) - } - interface UnitVisitor { - + visitCommander(Commander) {abstract} - + visitSergeant(Sergeant) {abstract} - + visitSoldier(Soldier) {abstract} - } -} -Commander --|> Unit -CommanderVisitor ..|> UnitVisitor -Sergeant --|> Unit -SergeantVisitor ..|> UnitVisitor -Soldier --|> Unit -SoldierVisitor ..|> UnitVisitor -@enduml \ No newline at end of file diff --git a/visitor/etc/visitor_1.png b/visitor/etc/visitor_1.png deleted file mode 100644 index de5285d7fdc36722b8ffac4190f25ba7427feb02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47078 zcma%jbwE{V*DoQVNC^^3x1=B;ARv-Tr*P=*luikyyGu$+y1N^sySt>j;Xde$&b;4y zzkB}}=ZKuWpZ&yI>lbVLNQw&~KX~#03JMDOtuVhd6co%F_%8+#2K*#k>=8W_RC(@O zeqLF-_^pKdcF6CS+H#S3TS7-e5uZE~aQ~KqD5pf5<(xH1{VjZa?9qK{DgN9-<~P*d zz7$khoqN%vz?#u%Ea7meu*{Xu(kZa7s`3M>YR95*%$LduQ$HZwwJv= z#!*+C+b4y}H-)O}NqFBNT+-b~UnY^SSa<(V$>9SZ1|@H<&Z)W4hk~0p5uxF5k^J!^>huhaT>cJB5Z=Vn{t~RWgt)3y z^+`4skE#)4)~6KNpZA$~So+F7^x$~xL;WrHw3T+5jL7W`cdim!h5ZYHh2dc`!o;?l z8?Lmiq)0*+1&^jBG^T(O=r9P?J97E^zJtNYlHD`aKFP_c-{d}QOix^1o#SAH4Dw`= zlW4|zc^MUI3j7$&rSH&P@9&Lc?RoS}OKa`o{M?X2W~WNM5oRoZH&iQ6d7|)xUgnX6 zA!9Ew9i9Dr0}8naR<`U$#QeNQEF%@`gWc6tf7r%Ae)-rCR&{A4fvgs4Ua2QVhKA52 z{@~$OqD0(S#S;Tr(Vr=$W97gI;;|QDY4pF{97Qf*edT26g<|FtK2u#^Yq>(!qg`~m zr3k6CwC^eE98QU8ZVPx3$9i04L3$IV#u`qg;kx==cL^s1mGyS7+1BFaODeorAK`4) z-xH?DQffSVWzgsjheh|~a7+zBOsFd|Yh`DqC5$qateI-EzhBDzx#`^O_Po05uBxV? zVQ8w>ejM8pOIRnop`AmOL8MqZRu5j8aSZIVkKg6iKxJA_@Y+V|=bDtFQl9 z)tp$!JU-_to57-7+Pm{szjkiBU~LjqVY9LVc`C<#ja|Kk9JWM zJ^tDc$j*47aOX!%0)o73d9g^$QwZ}1MAXE|BAx5{8xHRdR+HI#sW|OP<5V?UQmLc6T>_&=B1h=jP8 z(ZS?AydHGb{7$CfsfPN)+pgy*h+zA+&y_XChC(kOpoVU3Z=?A%cP8?v#W10ye~?L+S~X7l z^HliKcTe@i`C?}|+Q(6RS3ZJuLH25R{8>JNb@(myoA)YNgERtulRb$%OsqCL@$7_; zse;c>qfU2QT(4M+ zU`%nupCD`{Oy?{g@C0XnA(oFu;J)px-rAbustM;lOVe%b^=70R{K>?98ay2J!jMVe3zk8BR}c1cVJ^5Y-AAnxN3uNq5?v9^JnYh z!$WIJ%ZI3m4l7-Of%tLZw2E7~<*(|mPd?<}^W1QS#Ob2!1@QMO2H?%dXyBuMGEwszN>DYHTsb@?r zss%Qkp%$SF;-W+8s)H|L?YB$2PEKs{>vtG!j0thYmYKiBw?ZVPJmB*eykl9i4`*z% z1-|aPDP5I=C6E>TnOru4ArP;V&7vGNyDkXk?pEms*d{N;Anzx~3soBCyN_W*1jSM3 z(Qc9DvZP&_JnJaMot`Z=qFHas3tc@m8*ZS!r`tzBjjNg$WIm8$vzRCPrfKmrvJpw! z#Kiq)t#iyok1*Jw@C}DEjrHDFh(xWBH6If(omRmyN1asPjt~$10(VbBWcq7$H7!amDqneS!go#Mj?r z_*w=!4g5cR;jo6nLc*qBUs&*kD!RV8H1B~eKQj|EOwRQGnTiI9OKS**3ww`7lO4az z8nK)26s(oVm-5&n2+kij*dXhkGb5cia~0Ia6C_xS<>R0Z?WW-B_#ygTxk zy!ncI{RSGt_1ap}YPNr8#&2gvmdWhkyTpznh>70#D! z)Fcx%=Q1s}o1=^Mx7Qbq9$z~;KFVaI$Qj78tJPj0H>u~Vxz6~uO7L7G`q4p#!?Fap z%^AB>#sAbF9A6_xldorEmpB=9QG8FQwnb)%RbqSWu~ltf>K+c5)XE3xV@!(J=L?)I zwpNgfw3Ql;ytewTRQ4TROK8@qcr}`_R)g^jwv&HNrAV8xaN*+EjVZl>2-co46_2c0 z1?}s-#c&2S_>jjm9G%0`ISS|@5$b`B9-Ic!Nd4`-dC%uz`4=~*Ftb^W5v9@ZckoRY zxEYS-Ji=M0?1M`{FKubLN4m9i$OffSSA*}@aStbh!(1iicclalDPd0BIPKYtOSadH zvmGkA=vm**!qaqGVJC;pmEPv+-F$*kor#Y@Z1BD8AF)kL91OtBH z;=Ow4W;mk!k*TQf%k?{}*~K02=^oqd$v3olN~b)Aom5`g@9XW4M|{DK(;r$DOL_#= z)ViV*1Bs8v6OdPPm}jon1?g1p3X4Z^=u#^RRrs{ zyXMmLg;l3JY#_ehJ-%@IZFRl(b|88zwbxSy#XL?Z_wve)?~F4W#k@TL_168*Xv3jW zC{T!=wKdZX_qe$OR_awmW&A)Ophdx-WM{Yk4sf;d3b+HXLjH&b)(^rHJPHv7=SpMZ8?{C_9Ck z&$-bB{U0fM_9aXW=BcD!eQvBc%aQL9aCvaCx4=-~eFj4R(aBW4T2+Zy@u8qo9IF`& z5u_xO629|fcUOzV3)FX@mY|kiCf`DVhUU`iHD(o~E7oX>)|`vTc`v1H`MDhRlw{Me0#yCvo*McPdKP4C=~pWCJGid zmR`wZpmZ>MIf4LFSg8Bt96*lk4^EFk9nWeg<;rE5nvObM^{4Slmhu>^A{^N4V$A6##NvU?{z(8?(kShZd)9Yh> zt4OCc@un03Em{}aDyDywOhwBeEq+a>s3j_mf4Q%dAudMuuipR_*ZF3?2cMUX=|mBC z(n3c_DJXyl8B?l*B$mK*labT$xmQ&5T^tz%l$ILGsnj{a$g>zMTF<|Zj&CkAIn?dB zkd*X`mWMFa%=b=J)5GLKSSqYHm9|=EY6m;Rq`VDgsv39ech?6}b=m{Pehg<(sLJ>; zz2xM~RpGoo*`E0(2jU0zr!3VOozoowtlKKfq2CW3o{>rZ%IQZEFFx8!YibT!7zO6=MHlx{V^th`+_lAT&vn|)1Ky*5vb1pTw;Vxbtld#ZX4bjULL?ydddlJE+#|`1R#w3<_ zi+Eu$n$xT1if=q#K;g8jO7eXDuun(?K0Ql1?G+5AgrJ)&+H+MnL+B%gE59!1-#bt8 zOA3~`Phz536n)QBiTz=J@(3#7&Qs=0*rb;3ZsZzpyod+CMuIG0VNFMQ9R@L-_C7tb z+8oX@sCU_JAruW=un`A!02-9j*#&oPa*?a6!cto)!bAPrMg)8}iXcM53P(0{H^pLZ zW>o=jaNl{~oe{9U0xwxu-j<$`V35vLh6NkMQc6h67W0t`eqS)Ip*H(di5?J@_H!`* zV`u*_bizNuK=Rf3p;UP5r^Eh1Ik%LfpCDh7d)6q~dfusK?2Xhd<{e}4zn`^#q7Vya z`ZNUa$6uJetKE^V1SLM`6hieQ@&8G5C?;cd8f8mFJUh-7chx%W@xa<$(^vX)USlNa zdg?dm?8uMm(GeAD5>rh&|C|LmLn-5ndO6!2GH{+1Yu37*c^pb^M{~_uGg^_fMt;YX zWbChzo}R6yroAiOQO{)B7LLcbKxQdX?_+bmNCM%2*KC{jT^tXKTSm^zjivb2%W> zS!j}y`xagR)eEGa4Ol9Sz0+oG)5CFcRPd|GoBejtRlwP$U41>J7g&3k91p{}`7tM(C%nN0Ey3SdPf3~jn zX**1fumsO=_WSIH*E~|u21D=~d~f&J`hPP>1didxYs>b1WyG`xT_XpnhU&zm%_bJT^TL4 zQG*eLH5*}ETRcCBfgrUC$hPOv4b9DRR_9f5*7pg<Z1+^cRl$i?h5SAyAdqrWX3yQ#Y^)Zh!o5rPpCghwY@2PS_g>*5mci`h~dAMJpy>=zUz)-HS8+gjL=mzJ_ zW2v31{V{a1RIL@F6NRe(+P$TPeEl+xEuZpko_}#=zBp*2YrV6JZ9WvG4K_BPTyLGd z5Mix?VJ&aA%M~^fhaVAem+Ew1bl};;dW(Q{Y9q>*1Kv%Qr!{9VQ~T`w2AZYl3Czks0#O-rZfM5XS&0p%W> zX^T-hk1IC?u|^@H*(5X4O#MbK+TrqBU-pE=^XWZMHv{fKOb-UDa~*B|coX*W#Du0v zN{ZJq+6CqJLIw-0I=So-bxuqewD~s@6E|neK4TytE91z>AOxo~@C@PGTa0`p>_u8t zvdur|OVJZD4?<;*3a9h_V&MTH$LRV}J84+hd*%8%8o;B9?{=2~CgLw`ATk9jR{l>J z@E^j#KQle?|58f}qYhiHiN7&4ls4Vj2LyGwsk2cCOs0((((k8{JdyT0ATOqn7fa+` z2l4_U85yn3hY$2>b)tZd13Zz%mV&k*J0)d48U{B_Ehunisz$_i-w$cE9o=kXAo^j> zFEl&jbJRpcM#ihC4y8b3@TYHBKGD_I-oT5!;d-u{$LL}j|q5|CP-UZX!(<+RdY1N@zjx$%}V zi1JWw(cjtW=y0_qi?j>hMX26KA)vrj;LQPQ1)L3}wyOIRk_9*vsCbAN?CN2lK3JsS zmmVwvsN4;+u1+jp*`9+q<bTPN_CO8iDO<1cSvKVngj{>gn zfl)-i`Ob7CUh}9`D{Igv^6uXE!=VJArbh2uF;iZ8N z;@3RtQO@ZOd3rhpI|o+1{R`C{`EoF!m6qoKLJ@FHqS81jpA(XVbS^Zj0ig%h2MM#I zUfqpHb8iAjJN3a{O~RXI+Sex$5P~{qcxy>ZYu*^Kg<)~$226Y zl~x8%FC15-mMx(@!Rf3v9MQ&@`>Kl@?#M{*As6?X9AZj|bbm1kPY&NR`C`*-H{p{2 z|F_Wd3)YzeVnqMNr6Gk0d!GN)Pwr9=;?;gT0Xq#*;IDjleeLM0gxU1bKUHX~v;R5B z3pL^|(l;w3fC)P|1VJ4XyfBk#P1K_qo`;-RQ}+r!l1 zI6(XFkzqyIbHNJ)J;CQ}oZmldAt90L>>mJGyGSB&baNDrigR~(_$y#=00_6;idF;D zSWw{8HtbGN<>HL0W2$hE<9j^&R}eKxR{tcQ&z}YS+B&p2NApo-d0|=2M!vblFMy0c zID`uQMAb33$h*><7=?(u3G3NMbHEWpJT|WCkY)%B;;V~0B6Vw`Sk`}B&N(brC-^i)@t^S~1}9+3^0=Kl z`zn$W9$_2tHI!d$r^B(~NSeq8^vLRwl9FZdgxIR8$PYF)hGTi?4w~epB_>k^lF9Dt zp##--?2Cr^!$*Ez!3)1rPHH*#2i@YMJ|R0S1_GsYf7pw&FI;nsE-GE2FD&dPureZNi{WX?R77Tzs)(daqTk8@2!Jh(X zDg4=jxU-XnwrCR|3IU;PFNA?VXIk_;11L=r!Hn&<*F^U&!rP@r~Ss zar2*B)efgP*=PI64P~G@T%AF|+`sQPGacU@#UPXJ-@KXc2r5Q{#y}bR2<_;Zy^KVX zBgG~!)KlyAJ$VSk(&qX#U^*19wyXYmL3i$Ba5&Q6cNSBUqyyBpNPYq21X|^n-`+(W zME+n|ktTLJ&>jZF34hG7VpC>j5)gbRj$uQ9B<}SS(Z-}l?sH=MvR#m>*Vz1}doPTS zSGu^=t?#xfw}3Kb{Y)g1Rvze2jg8Is9(c>mRFyV}TeP}@xd!nA7NLnBWtMK48WU6wK71^w!E_YS|mH(-=0wz{S?tVsqYa8z;cw`4IwB7wYl{7d0Ub<4?;D%Hi1e6PQX*HDr`{uA5r|2|L+@a;INmu9#w2p z)**^0dP8B!-EV5nuvy=WM6}(#Iq8ZBTjn8RHI1Jr$r=lIx?g`)l+1ts@`WC2cQz2U z0uoX%#3Xo_Kdc77`ShU7bY>pVFSi$)@*yLjpe%f=t=+KFJq2hH9$ith&gak?Kz4_L z;T|tDnVl$Bi=b0tqM*Qu0qmm`2zLHu9L^k1n9Tv3q*PufAQXuI_VY$KNEtj@ZR%h7 z_2vMOlgkPYsz`(0EcR3|{++WlZQJTw&kq?|SonSb&MzSM16mK5)CQM0#eKeX& zOhon(^Y=sF73BXTm8}a6Fw9m*d5gFTwJ(CAzdL~>Z)rfT{V!NGp+7*+_BW*aJOm)!qcB#F`;w52iJl-JxlxH&Zw#_pt#vgI zE8Q1x0`lJb+*sqq^4C&N+4AT{HEqXFevFtct3iJPBv+t<-*qV1qGmt0=zqg(TL{DT76iU7SOu|{nt^<8Pl=u-JEF!#Xm*^BFtWv%s`?O6WWYx zrDd9qS`7{Yg}H715t~%N4vWR&C5h8wOO*S4=JI!7c}*sXwy^!gV(ol(2t|p4gs&I8 zSV)vAWkCqJC*duOA1T=qggf+fuE1xm38)Me38W7(frgN9MdSZ;4B-=IwzRbT-TC@G zc=|(!hrR?X95(KaOZz@|DLOe07%6lTxpT*IktC&&^3E(O6C)#QwA!7HCMt^9(y@;6 zk2f8uJ~WebKt-C#Hbl{z@QtBR*a2DdKzyYU7Zf>nqxJQUmIvfNuuU-F3Oah@HQZxT z#d*;Pia{c}Lit2;%>7!&a!8?OsL!0{>UUz3DOSvEP^W$YS}v#Uqh&RXffPo|`(yd2 zWI$b?{izLhc|+jazn`FN65*W)JNV z83jGG2D6!}#NDm|nt<((VN6CUL4ff_zEx_s+_TI=qxyx^$eZg~FKCnJGj{8g0vf(> ziL^GTj+nWLf=bB}#I`WXXKrpTfW4NxdEFi)1k)>?;0q5AiXige55>gzq$)Uub5@_fwR-UpkMUT9rTNS zO&?KiJM;Cc4vBOkdCS=5x&mIbyD%lC(0)tUkMfUvZ$3{=O;uLZJk)0YnS)PDX;oj9 ziQ*!B6z}`88~l4K#kd?y@Yv+p9pJjHt^1neyPle+tWpmwJ;(syF9`ZK_%n69aRTDA zCi-lN0Txm7k-WG40a^q#tkH1oD2*S^4%L_@`gv~%eL-4fMhLDFK1`r&HRl!LY=86(R5$<4i<)dy0M7IcpAc8ODzgMU z!16KAex@b^L)`ig$#$tcFl|PF#;Y+HqD2o3NZ4Fk^ZTOooyXUR7lu&r5g+268_Dgh$sRH5x! z+SvF^`X-A%CJ4xx2_;5j9Y6`XzI1e>NZGU9rI;MFaH|4Hk>=)y;dBLSLGzjI*em*T z>^}W5P_{4;|Np09xc@B;Yl(;|lTh%np8U>(mJ4r`^Hp>Dbe;s@o;1y(tiNU z-8_5c1BSfHyB!mQb*Dt!!H)l+PIaE_AzXX|P{V?KXIRxZx76a;6jtP`qPg(D| zNjW(^p&3~23=4lIbHT~Z9!aZc+~U0hg{@_He!h0R9yBzB+F40_wd-oe-*A^Vcd+5n z@VKf_5(tmh^ksBC@RrQNU_kjrq$|_)22ST(k>?_s*yJ}&Z@7Vx! zJHenGauOM7c^~?dFbVh+()O|THshiiSdfF9w{s$?74ni0zh_?eq^_B^$5eD^1fA_R8n z%}7pn{ICK-gtT(h2&t;Z!3skF9UgT!m}b%dr%iL<#-QvCo9I(OhadGDy#6{rW7BsO zo2cJUT@AhTVPMQQ{wU8&?&o&z)jRTD->Zp2ef^bs0vtpdd8;>3Kpad7g@Dqw%vh1| zqq`~^S7azeowK^B{`SVIVRbNVNm->EpA+j@UK7_Vw^tk>i8piUU$K;jbyLwY;4>WN)yFiSPZI1Ag%Sx;;Yu!83XQbJ;L$C zNoYqiiWb)^5Z7ydWyNN1{$1zu8@`EZN5?U-cMuAO$?p~m8GwUD5#=54?38lBd3RoI zL=bg={nxVmlsmOAI`wYHD;GQU?un9hcT|+sfy4MAVjWJ$?|odR|II-ga=_UdtEJ;z zE)I9SiJ{#gp+Y`*F7@RX1)J?#;gyRST_BJjQocGHX8g>{QTeYF5v!C zsr-=ElGCzb1U5u~5mR6#N%woS#s-NbrVb}bsU&8EM_2ppODf+k?n2&VDr$sQM>Yk_;cND4e|ilrnT5P)S_ zeUTsBeHUoL;JbI?G`M^h2bhO{4{;^wW!}$`J;l8H?wxoHz6*#paQSd+KnwhPh+VuE z%0EZOO7-ujy1V=)uzK7*-k%|Yxk==yPxE^%6~6uJT0e$>W$mz!hfd{zZ;CPh-H88o z-GkdFCnuK!^26#GmGf{goX+$aUrR1MK%T=wt7)%q1q=yrbVkNnoBrw`hK$U|h z&Sa>+Iyl-G`o}-AXYR~Yn@yH<4yGkhbqW5OgU3&wI&O_KibT1mP(4Mz8@O>~LV`-& z!=phF2E{5XuyloYOQ%y@WwTucSf-`3@$vCU0OeimGuPyAu5kA$1y;V86LhVS{rvXm zXs%Kmo0%ydkJWm={o(4$-S1&>JbZf*m`-QZY=5>DAI_(3_zqQ?iA5(35Fr*DgJ}%P z6-mDNvRQ**)S4kAQhgatU$Gzvy%}%mUU3?5DcIXck7g6|efIS9q|&-M&UdY>s)A&` z9RA>Y4RhzQ(Z7xz)_giyZkCvlk-?-pTVv1Xg;FXD?u>Ey>7V@vn;@G_Njf-G`T2GC z@!Zn3ml#hlv9gZ33#5GEv(Ht#bGP6zaTn7xgEAKyny{k!J#ekV5wI7vFSR3}CC1mJ z*lfS2bEz5ClosiY6}={*C>{5w5Q}BDSmZ~qbG>yb)NI`|m>`i-jOaN+0%VNS_3<>2 zq}lLewucAn>m`8C|IR=ToDqMOh|f4PSG)*EllESEijtZ%e2vVYkl6$_nYe+@Fv^64 zgrT7!a_&Rp(jqsP1z_9+Y+m$PewAOkh!I#`EP(XfzMX;e#EK*2&mwyidb;zH$ zP|A*tO%D&zhOB51xY?&(mIi0#PJYEw3eCt^t8>02`#F#wF3{c|v)iN8=;0<`I&)0& ze>JXDYoJzd0U!?@J|W4ZeR6Lv3#cXJ(l)v z&fdXhHM_y=IRLJxn~Tk)4dDsP`j3Lg%bir6z)(D?Fz|V?!WARLog^u)^X!~9hm5rfi5hG97MQQ_L$Ddz9#hLc zr=w&4r2xC(0~^n!QNA3O611Yjk^V%6#HRHo3|aH`haT-FkdKs0GG}hCH7p-OHXc0g zN>K{AgzLczhDt#3h2DB?i-yHI@REXD=kbFeKFQU5Tmx7zq>zr`vX0?!WGY(P9Dbii zPOB5|bhfYE2SKfkVXltnlU`?k=y1Bbt5WOmuGEm;Tdkm>UM3?wGi)hFbMxOw_c6H1p9L%Sm-fxS) z7=$;D8zvD=FSFSUhP<4BOG8l9F7k6?9bnKlWUkZ~8Th;ek@6P;tRnvLkIFkU{s0hU z_4gMARyJorw ze+>Bhn&Pj(7HZUcGRF7*+ff%FKVCpMoiB(O+Xd1In3iXN&j7f`#un8=@_^&{Fy}2@ ziHn$_y@e8xi7|!`fMusJA8^PqVL_m+Mr?}h+m*kdEG?<28Q!^b%=z1Zm0!+09`9DTfK=_FG$?oQAcWP1vMc-Tcr!yxD@BqMz zRawbSO4Bp5Jyl*~u`~%BO6TjT^e`U&FG@P!J{P8oxd7hZU9TY1di~d_5_89j+P411b(+96GqNb zBJ$9w!GXn>Aj{Ibpw^F9(A-PigJ&)ng5Q_*uac#@*EnFG4*Sp7DM$G zFC&y(Or6>5#Dv7%nDXtGF~r-`ll%`hJ#CYyqhgpow`W?YkXGQ1CJVwts5b@P(^#QG zM1TGM`BKoX#$qJDR=q3V?I=~62D0HN=71+7FbFhHZJ0rGj)Twhs*F4prEqGw6bMTc zC;)=iNkgVkv3g#fv)*7v2vT5ZPaj6N0WpMgZybIiQ(ihf^x6U9XK` z^Fl$khHWAhv_b`v`U}3eU+b;(SKG{kUg(Yg+BP#+sD)v%p#+)&L07_;m-}fohCha( zz3-|%FE1LHk5KkF6`_y@Xa&D-`@mM%@=B-e7Hy#>SE-yso*3E2vtet3kG$DW5WUTS zc4r@WHw2yezYnHKFv3ZGk{i#*c~8G)b84yyBKyGgLKjA+=MgY2No^N8o|aoM2FYbw zE%xl<;s;vb(%z89mZ{$Do;xN8h#zNffo?*g3G@SKv(KNz!o6e+-jLIG^an#*0oRau z=t6sQ-+dIgfJmD64xmG>M-&z;IX_^URPEDB{JOgV28N4U8g3~AtjSD;g)T_@<|k0< zE3WyXMC^>OhKgk{pwP4LL$D{z?4kw-d_U2E-bI@w`UbMBT=^e1x*7 zp`{XDK3^2hxfjWmd`SMRxEduXV0%37?5EW#6!3GdBW4Jj2qRP?>AI5s+_acr)>XTU6eby}~M zN&?ltQVvUH@c=*4$-r>Y94Ni}gaakVZ|D?Zw3StSp3>p2M4|)V(`CfRu5WTQ^Rj65 zB=o&#ZLNe@ON-nuD3N<%OTH-ZlLm_8hv+kt!@eR0txsIN!Z}S@J_3~)eTbbt3#;)7 z93gVd(~8!C;)Wq1yK{3iFe%%tdKf)3z_1FO#7X{)Jbb`(L{6F-XJ-_++Y-%AwP#k& zVDDvRz`CYlH?t7kBUFA2;YtzHXIQDlS^)8?p&EGC(XLM;={{&`x}&3|R**HbP+|>~ z_=>!%qyuU*+CG#+h;gg$+t^`}o$&f|-5x*!H!sSw*-$@GP=3)t&a1=U=Z?%vRzc7< ziTu=Ew$kkt{~FA~0S@-~L3iql6f6ucEoJxwC5GWp^4GI<*U!pRL`J`N-IML&ClPG$ z)?oaw=0Z!^oWX8juDP%^U132%0*$=5lXBz_Now}0Zy+gqV+Txzp>N43KgWHr`N1zg zU_QiZCM_a(qdwE3+qiq8#I?243}m4u*Avva=Q_NLLtp-H4L}@{cTFZQze}Y$q}U53 z0We8IkV}}iqUw+ptPi_V#!RC5B=mT5Oq>i>Ltk3NeD8V7`|MSi=b-_0g3JXem%#xv zs{GchwPBQ5;+REJb8`HkZ8 z9tahlVt9eNxJSmdk|L2%igj#B@iNE-8@qFd<#U>1uhWPg?YSwC-x9q2JC2Eot++VJ(VSTqA=q3sii?|zybE%vK@Ol(D2dPtU2@I*ZK&3R;zyY z5UJaqzUzP{iiodiYFW^a4l`k;;;2td3n-llmlQn$g zW9JxQU?`QQSb4CK@aT1@Hcp>+K`5las4zDaau*J#34VA_Jb9S<=k+S4GA6r zUP;IYG)DB$lpj-o)v(RoGTpHZ_P^VcYIU!HUr_&CuCMVvaMS|9Im4kg zqmY+a7ezg)J-NOjUu{n3V*BxUg5f*a7pOvgqv)l=iqP7fdpwB2X`uF9_n)&%Z3D*f zWj+5F?p<3cSXaw`cUV1vCKJ2@?53EcpY|gVFJr!dcxlZtoqny=)w2ffr-IgQGUACj~OEU~3}Kn&~M14X>0V_z#3alMx# zdTIB5-T%4?kraOaTX-7=Z!|j#zhLLV{50kS=(JDJ%jGmoHkkMtiO1C6l0TIW_u?d1 z&4O9?`mKg1x`*B43h#QgRy3+JV6)V`_d4CNQy<>v)k`*kGEn6IhBO%5m%C44o!LA^ zC#o%u8CR08FVEy!oLEg5Mo9wVZz{9MQ*p`u-0~Mz5fQhuH}5J5vhBr-g7R{`@pzf% zalhUd=cT^r)sOyWO9zZ$O@{}5{<^_u+vVdmtp9mW0?y|rsk3V5^@OCffiyRpLz)(6 zj%tm>g$>2Q z_8Mx=`kEv6ar@)y1+pe@Hw4>>0@I0G0@61UL8$enkyhZ$VBGtcbNlhdObCu>a8FqFeS}q%aOt*Kr%W2+ZyEXn* zJi%}=O_9o@xOfOC#?Tkv_kTn#|;+Z=^c-!C2e(yL;4QR<7^Lqr^(v6|jt z69%!I1a?#e*BNE^+V}?Ztv~A_FDz1ovqe*E`qg)9gkSR?S?d{i}1**4L42vzcx(kXOYRc&|je z9+YP41_vLE|2$_R;*Qf5+)!5b=z7P%(?jC#yEk|1f^3NUBApEj10(7oPCo%O+DY{; zYZx1_v#FQAygx8@v^`}r_|-+t`PcxoXr{bzdjnoq0`0!rzmR)6YqYewO8YFc)$Z{i zsq4Rn8Sh4MJ?YBsVm^J=SlEZ>h4Z*b7(OSF+Zm0D7fldU)$M`Xq&p_j5_I2i$vh8x z{~jP<5*c}R^6O1o@1vGQKTporwp-5q)x@@r&Hpe{zzTsP6Hbhy0mAfslO)kIDG~Ty z=aSp~Bx-y>jrrn*h=1Ga zXVF*7xr9shy#)EYSjaXwP$d=*+`d&?83YPm0!ERA$BF(i<$~dR$S^9_xd?OZ=1=Lg~b#w>mD%?I`yOLADr#G0joSZ zRP57yl2T#&NJz(U6%gXmSwPUo?+)ti^kZ;u0>(e>*wxN3%#kA-Z}ef)U!85~qxrwd z9x=o7DQ!c1KQGwky}iHdFTzDpnVIVfD{^<|$BKw&4$`qZ1< z+wSVEKQl=pR&216^{ug!-U?jzZ`#LCr{}-^z)u!A5HIP7D6lQ!ZI& zt_W;4;(t!H(SL1?`>ubuy!;p_liz%&>v?iaXMTh(lyZUo@n{*q z+t+Yk8hbLW0wZ6!=}ZGZO4ncR%#Sf%ul`4?+||QE4L#J-%wF+{RsWjQPd-1|Mu|)J z_Br06GOg`bwFeQlx3pM+B11TYWWw@b&CxAe(drh6p~AqffcsgNLHXsoSJin2L&NSl zcl`q5jPkj$v^=>KSHF7cM3;&3FM#{?rK+SiJ12)d(>s?+k^@v^e4YKaq0b2nl$qq9 z%^lbdKoo__-RlV9`c65jT;Oz~XP8o@lfY1(3D?8%#Flwqe_bqtx!$nfs&|5aL|8&% z4hSQOiE5xv6jGvJ=y3dF>zh!z#0@ZhVxbtXRa!y8gbs8-ml%T{f|Ut^{uXl3jEAi9 ztAn7C`DX{g1Tkm~{dWVwHY-{(C~jLJ#+yK21@A^!Hov~0Zvi&e37~TTPP!l3jmH+fA;6XMb_3C*N=uKZPc1=<3wRk2r|oCoTB2LPK_B>X zt;KTHJSij_&o+FqS5F+6PxX%mj`YF@ z7uCS7lMhG)T>IeHxAgS%U%q_#u-01(-mS6twdadrsFXd2VBj_(m+7SsLz6TX$wz@! z8`q4OUwsDyEc27QV`}BT9fxaLphIH&%Flt5sLhk(o;o;5uT$;(2R4(#J=a9&@oX!+#YI z$VeU)(Kc*h2 zrbmj#IP`rf7~Gy>i)2!_NvQ&FAQ>jv1g4b(9V203M2^p*+3;d(u@(fg zwT|zniD*@-N^sc_f6hSqynh+54{!0w_lqe zPXq5#?W3}EK=Q8W_~`}B`pKK7Tr+@ooZK;|{UwXil9h9Sx}T>;uaVB3oV%Ur{`);w zRx}j{c#J8W7noXx1GLGO3{<(V_&z-!BvtZDBrE%oBjv{~8W4!5kW^VoQ3AsR-YWFR z0`$_lpz8=iR2Dsd1B`IN6)y+Sch?n^$wb~kcibjlTb3(a1u@v|>Wjj&{U!4rVT72nbS!0LeN}YTqip-hJcj8GUG8B zIWOX;TYY}q$CHnsM>TgIuvdRuiw-TO52x+Dp+w%?^UxlC4EVkmzdx_VVkdn>iAz=e zvo~{`p8)l;8P(_>x)Bqnl*$@bz$y}JsV-Z4y4A(e#(fM5J3BjVSr&Z`wgd@_{MMTP z!`@rQRoQj#qDv5z5+x-BMYR!gufY ze}3nD+aLCq2cNapJ?|M~jydAG#{8;2l^QI2{gtV#q2=OU$34V-WYj6_58kH-cVKK$ zx&802h_P1uA=B;uKwLxD@Ix5s`G%qq5iip8W3ZMrKN5$&9C6)JX2n+oX+Ub|9s8#P z&&9?`2=VZ|Wj>WLRisLNqZa70X=)36%;^vErF2^39jY6W-eQu_w}2RZbA9=s4QObCia&?r*|u}EWT+RAqR0yT|d z)d_wVIeS6%2$O(YEm5>v1{5zdx)phyf&!Pm5d z)Vy}ex@}wxUJrhR+$}asM11oWr3b*>-ys6XP(XGnj51O^=m-!t1sA{v&Gh0E2F1kG zwKoB*f3$3!yM5n6qtuA-6I>9$5H5*U+rmEpbnypVVYsV=gAOp1uP>mg0b0sXgIhp% z?~wK9^6%KoV4O?4IviByard9gfv_yd8CIN0807ckSH!lA{s4fb*F+y;?q_CvIr#A! z`^MQ!Xgf&0=N-cJi*=B|Oaw%?wuXl?e+|$|5XyA^!f&++k1JHG3>r%a8yjg0$vKRL zV*d0M37)3TY8n2wjZK@`4+CbH+DHkp%$R*e0akrXT)uVA6^Aj4Ee=SwWU~M(3oAtw z-r^wp!eW#pu4D8^YruZf1yqFb4y;O=Kc-YGfiUO_N-X5z?*9rhl7WVm$Lf&eZO_!m z(XH`*)IYcJ>tAM9U}L>!XspLpa#gZDSPiuTaQEsjR>Q5^-+W&L;dc2Y8AHQ*O`z)a zr6R^7gBOIN)&NBi8=)966|hz7XssxvO4Lz&#UZ?Io1nx-#P3<}xIJE|Q#U;|Wvs?l za`tw696&e8DT=CZp|%$T_qg1C@r(+Y)&*?E_p?Du3Z0kNuCMI#0?6&kAc@ODBQ>gQ zM@|PLthpi#F2>!fWCn9o_w(E<@8q0YD$Do&IG7q;WCn?K|)BtJuxuA zA*Cb?xaKjJhXYjE3B{dv-%xtneGF<3v4H0eZUTHV%F}etG=Era!QUZ+>Dn9-i_#!3 zQdkkZv=%LrSx_R2MoqSRc=X}sravw7O`=^bQV^DaVy`We*L5eT48wd)&erpEU!)9G z)#{%v)1>3rlh;AKQcWA28JGYDW2oe;FX5*~Jid@oc+cSgo*YNmCFXYtQG4yjUVwWg zzt>ics=CV~MMoGYdpn@OoVLU+`d9y=9+PFa;xcoe{nZ628E*>nKHId5e_u|Jit|8Z zV3aVh(EJzh4C5v%`D{nG-9thXsohws+Ev^6Vl%@NX%?gf((9q%QZZ2j#W=Jzgp?f;EL zR{0>;S9pjMi}zISIx!uGxq_2iiC`u$M}*m}H0bY?co`Sldy%yiC0P#rFgVKf>eqI5 zSPdU;`(wutkLjvjbSw&{qd#o}hx5EI6Ni~Cj_Y(lHi@#1yl$|ZQ%P97hVQTCXujg4 z*Udm3H`Y-=@lRiuzw@3GYp%7+1_!`8x<+w0xgAM(QO~=LX@C%X;Oy`%aTEb9CkrDy zT$6Xer0`k;FpT~*xcd>gG9W3SK$L;AIpu(fGsU)EJy>3t1IA*X1NlZ6XuY&DkO*dm zQyHSqToC}mjNP!5a$jvanEG{j2dSj1I3<)gE`Q{w(pl`bAh-@(F!XWk3i03L;5ui? zhK*xd(KK8379`i85Y(Es0s5lVe_*B!`- z0o)Sf9zq6&szB@{U^%9beSWqjKkO>wlD$=V9d+r8mPLra6C*MnZTo#dAqOSOXnWryIfr&gm+8Bzr`vwRRg z5^A_@k5_GUwnaXA>hpK`iJ>U~T2oialQwNBeuG4okU$SmG=FVhuxs8$=ooS7wSpoL zt1*P0KiibQ-i_CS(bFQ09?KHob4l`yp_2=k|6Ttfoi>WIOkch7J;{7~R!?WyXnOwJ zd9c*U02euUQGu-xgg{Z(>CpHAAk$?M&l>NifV|=>xW0nlK%D!RZ3ZAJm40~-v-7zk zC>s{isY?H6i^X@Ki}FX>lxcnFA``e38-eP+U86OYU|XTcI)!bzKbp+tdGQ<+V1f}; zK!FiZxbNz4V4JMP3_T1!R-hflketz!9kmD0fo3Kh@Yn@lg3C=-zMHneDMDwo1#6k5 zLN=qNi=H`&0gmVWT{Ahs$9)MCn9`{=W8mmY;$n+JEn?W3ovPEU$VM16f~!#u#{)yI ze;?i_6O$$k`sd&gJy;1g4i?xi_Sx?%`$oCK_-==NUp}mpkS;PngM6?99IziNOF=5U z%oH8Lp6AV{$VZr+nasDn8$8MC86>E9O<4=XIr_!zey!k>GMkYuz}$2yMZr82NtO6U zMg8psF$6EGN(lA!EQ~1<_m5y~1OnxwQ#mh5xn%W*vQ`7^$mq^d_BqysXd*v%<1ut1 zQox&8?7c&yma9mVZE&)7vs9+P;(%mjQ;T}L?WMr}OpD;R2R?nzI3R!3qk(xb3K@m- z0g?Wsk1XGgnx2OzO<5(VjcV1)E=Q*kzXP`j3f_PS>FdL_5wBCgya(v9%gfX9vjI|WsZkQSFnz<0 zC~i!Pe>8>GlZurMBi!`?8!Gi;Z#&AdC>rh+ripe;whvTK`7Uy#HisW{Zh?w+AQB7k zgsoDKWQwACla++JU*UX^Hm&-U-3jV94Ml&XaV8%Jm6(3Vrz+{8U7KC>7??31vR6Y2 zI2GV)R{+Gv_dV(jC|u>ZrEG6!CoQh-ezd`L)CbCnaWsryagwo`zU_2yLZR(eG6IJW zAVo-ZM+LBn{~hKk_@HU0UyAYx?Siqd!9sS_yMJh%zY2zOvJx2$M~Tq6x;k_{>M)3x)_)IN z+Ym)WOtw@OP}u>83Dg_L2PH-y6{_S@b7_uP^ra{X+24*=UN%f$s)H;M1=C^@0(J(M ze|nGSUfKo#^H`Y5=`$bOgAc1}BXW(mZ+^;-lzunDy-%yd)jw7-TVg2ZAGAb0 z3s6B^vv@u1Uz?GP|=lbGbVyfbHn7Q#*aK zh6ig-`?hOVXP{@pEk?NE`sA|9tXUM$HxCl{v)`}LJ|s7(`c$6PSsZfvumkL1rnjZM zU|BzqcPPsNVYe)tw#u;%ZW$>G;YQ1520jr#z9b-*fA8NT)Be@84cM^@_8EU!0pGm2 zCJdn-Bo~&(u@3gi?cp5r0_#_ty$hu)?5GEdWxz5Y3=RiYEbrD909Hon|M)eAe>yOV zzSi(#@xrtVnCY3V<)oX1d6#Ap+xi<~k$3OjP~^_77V9rA48^@8+lVBy@6BaLg?Ub}CWUzTd8t82DXs^%*L z#z%QL>WgSq>DvZvap$Nq1(t)O(=v7=+!adc?~x$yggwpPtaH4D4y7!r9vLJA#Ht;| zycJa1HXvV8q7x9ap077IG>k|}qH_=y2>ZGZCyk0Y_N`7(33nz{bH%@@$!o6GaZ_c( z&zr<&0U`D=Y90c)t`9T}Z)$1^!0#A9+0KR~yP%ck-%r9}7712#1_xkLcpi_b9j^7E z+`r$viqrM>&u1~gv$Id=IBe!yVP9zty?rd-i2Ve#OwaNb8ukeD(B%k}aWL*N!;H~_ zK)4QWyq=}zzJ2`A$d%$d{GJdfMuH0}#N>j8A>RGpap54%C_6$ZWP7tUW$x#8QPL0y zC89hX1fqK%1;y=PB|wsVRlf1*?j1-cBnJlqX#&uQ=UiNx8>$e<3Pc$N;;qNb!ZK5C z{@j5E0a1;If`gh`@{gyT_GVoGX8ylC9S|DIZ@(7&M>j#K6mY`o z2vxyBp59B^XJpA7ry}p!~Op<=k+d!x(%*mf6Tdwi3x*VBi0{_I8|nfGItl^ zE&U(Mg;EIC{0QMzN~EO+2f+WpyJ7+%`mTur5zzY&$v~I@Q*Z%yD?imm2#{2U!2}>M z|9%WsV)(asRgc3#2617FntiPRQr>tgIw*S{aQ4gUQY0(pw|`)dnW z@9x0F9CvmC*69ryu+H!P`4}{6e!B~BwQqZOE5F|xVVxGRfj#y6WAprI3^Hl&(KH4H zGk$O%#Z$D5Uq1Q=C*6k(j1mb**Ldh!?7Tsxrjh# z+XO7g%#id)!VHDU%{1KqQyI z>qZdSBPV*n^YSCUT=tK7X{uVbhuCLW z+Q=L-rM3b?L-_46`|@(yxpMO-S(aB<^;K3V#$?XBn%}p#GfQF*v=ZW@>+MY$Vj_|n zC^$KV+6u-jI{W&-wGP=86~@O~#D2aZW3j@0S?%21Ga~_m1SNT_CXz!1Z*!U}aO6=L zDd{S^+~lcuiBWau;z{8G7P_OX#H|v!af`^5<_gSlyFM6pu*=7fBGr)Zh6Kcom6>X( z+BJKJ0^7N;>BuB|e*xQgvEz2)$*#`+ybPd{OV!xn0HaWCK>v7fQO|wI zU)EnXP*z4Nt9%w8^3;)$a!ef_F?0C(>-Vt&kRTG%t#Cij0M!6229%vG4gyB9IcN@U zib-+x>Ce7@<)fhq>IfYXR|T+|Xwu4dgT%1W*S5Cfzu)`m6JyGXtm5!DTn6S&*0tB7 z6hhg;6xhW4YHnHYXYoHE!xj$WqlhZW#_cz6!Aj~L^pn>Or^;eo^RwR^xS=71S85_W zcWKsSq>cpWF&i%hgYp4SAy~>jD~;Qa<-L1?{~#IhzFR?oyyu2SpUMaeP7o9sz-R zQzK^A1Ci^oZ-{7#lM197h!1vHjXtcmhX@8<<$K`=F}WR6mr3It1_z7N`zL;Zj!9x+ zCu&)Id5bLHE6*bC^oc`ER90z#)6VD#Te7TRjb})lqJss}TLb}PNV4SDd*qKJ4dnBN zn2vNmKUpBMykB{B=0lHK^-gYQ4U@+t1vUBV7Tl z%-|6Zx1egD%2QDye3GB|;!$>I4A$`$XQ38{@Dz}XhnOt+O4)0qIaFm*F`?q0bJpd{ za(`0WWHTuRTGKs4-E3h@?(Ou5r9j2Re;g@E&zkYXl4SE|mtiM%CxXOQ=}fNm{Ot0Y z>O@;xoV)d&b`v=MUzg5xWZN$^KGD#WV(QP5x%{G90994RIpQ*GXLQ;Ga~;C==`uX> zS&gBMjTG8*-;CtvXa4Q^T2lAJ&KRX}S?q|{kWeL=D93glyA}<7`jFS*_2X4acSdQQ zvl22(-xtQV$(?GFu^(6Gf>8u*WA?4DMCX@-y8ZRrSe~EiCqI-hdnHd@Irzz`IH0va zzcx1P^sIfkMIC~Lg{0t%h?v>Nl7pl2a&^3TDGq#PaHvlU(L}v{Yl$!77ucRhp4CJ& zS>bK`>i!tT` z+kVSg%M7<#ImLXRd&{3VnQXh*946(z!NzVew=-9kl@;H~J(OwB;9k7O#pP8Vj%<;+zBu$YhC zqZEt<+g@6Lf&W+>Cr#<%HYJsv@v=_op20isCml2_U~U(fkIesRZA4qkBU^d8#9 zd-l26Ej}+#`PZRT!Gaa{QE(t_aH#^%mlWtk@H=#?i(BRzs3g4DKUxiEu%n^RU*eES z#wvd?%Sxn z3$if@=FfVLD_g$>e`N!dY+k-@NN47Cs|1x_t>?_z0=v2uY`4edeqFdsPDXwv4s|(f zG@3Xe=9v_$P(W*J)UB*s-8>au0UPb*Fq`2W`Lp6lAiP-Sgi^Yi4Hy1cVnMialNA)VYd+m!6CK>@fl<*U^-Kjt;%Y3v3FnIC5j$*8x>r}2wiY+$`?nEJ2^{NHd)U70 zeQdJKA$Mi4tX}$6;dw49jr&?Jj#FA@>awH&&Kd zYV>eZi)O#NuSA;mZ1>f2OM%1-j`MLAgBvYkUWcDKQm@wA7u?rU9L zA5^Z?DzI4dlrqs;2?g+-Z(l0gQt7W43DsZue5kV-qHGks_g{ynaed2yG zbYfj8tEaqaC3&r_jMF_?nv@6FtXAPzPyG!8-`62|J8)PL@l^W_4-K(U$?WOIG6!A- ze73a}6!v>FJ*AS-3mvn>-d7IFG&Xml4e*!-B^Nj{IjoSg%0uN$D}!F5<6^TuNIeoG zW=mu>XN+rTptI6#N^T{2Ti&ERt10v$!@_UVKyIP)^+Fedgvyd;!XeKD&w{A@+$hv zALpM3(mPIcc$e}EzJ6g`|ImF?3P@X*m*};wjuT*A%=QPT1Lug^I)huN~tsZ2_ZGjd@hdG%)!nixc{p; zH+phXKoXr`JY;veli6fvdFBh0OcAk>;(QfCp9 zE&hah;F+DXjbvXe)3RQXjO@o$8I0+PLNcBD*k)xG%=%snK<+4bbBZ1oNTP3HWv)g? zZ9HD+u|2Z$mHu?E;aJUhOvtA1qlzjW9$r}FnkxL^;o(~PyDoQnA#ulFCo|5<*g@~P z9F?>EKa3ZUy%(=FiKRDL;p@dDK?)%WG4whobDgdB1ouWQKFHRMmo-{y75uNmh|s!6 zLFahhK4RaM`lv+DGXjgtd7s2J^C&fEh;IGOknZZYqdM7SF*@`4dLpXFCmbuWOdgZE zq`|iDa5<94@FI@nf_to@w zAM@nDcF)cRLjhe^PG){?ribKhzYz8B`QJ7Plw{FbO$qr<_ozL1*55^lG)*DHcIPd; zP4-nJjj5mqc~6>kw4IQUdj+Ziwxr$5o*c!r6S45OVzDGhXy*3_ykG|++hE!LmID05 zN214U@w!wpoYdjIQzeE3;-%o?p?BJOB0(3xL0(*Y%g9zl)iXS*jB(duT-x~j zLXi&Go_u^sQZd)w^YIwUu?GVw3xy&TpML!mvjnsrDt|a{or1;sn~kAk>5)%ZmuJf+ zH&@UJd%;`!_kc}Z-b?iH~2qn(OHatgGBt_^`C7YmVXj?GNw}cr<*%qEf=GsKc zKlg-!x>s>3vnX5|CHviM(6O!_VYV^eYAO{oEKfqWp9Vs}@|_ZKb|pjl*7uIy>|y@d zJ|PL+XUSCqKjOc(bGn^{`p;fqF65rQ7VPn%MwX|Oias031$?%M9{p4F;U5Z@1ipTr z`Ulqd6jPfc37QxjOX`HX-)o0>Qufr9F z7=wcQ5%&ty8=Zhi;yt2tonS={Tvhbje;V4TlcGg#^J1t{&Nu0q^K08_L8p=LU+}W| ztYFd;jmE>PwKt2mx3#66De22;-(JkjiV8CEy7{VTxxpzZRTULv2@k_!ACsT?Lx|ZK z!|$WTI)UCISku9?91!VY@M#Yoq?S(^2@<Ex38~HGMe`5briqjmfPL~2d9em(Q>0Yr$P$3cBJcP&HiY?q(bmn z;C3tJw^}{T!Sx+6@6mA`UF0iSeX~ua==}?l+M*{7q~w(gE$w$TF{~+J~~iY1g5xu0#HHk5$0b?M}oO;lQ?X+Lm#%IOw3PLWdneYnboLTP%a z1evD2uD!9{gZbo zQeiOBlQ?^=Kx_|+%*$~xC@xyscYLf;lgU%gZC2F>x98;gqT$U#|Dl?JwNK&1V9rsim$Th(siCoT3s==BgDr$;6MEpx`JF?Ce@` zSe~7H_3@yt1EGsMY+15T{J||VDA%?>cgHb=c=*1|1s=r)>D0{^wpoVX#0CMc9_Www zXi{{w`Z|ReEd-0}t17uhG^C%IM>X~~`@@cojwW^S>;;D5H}%?;g@4IH1_r(_6RPC# z=5H6PqrlL>qy(X&KRF~cII+@f=*)Kcg6e?5yRK$TWo03yGnu;4SW4UnQ8w_3LUr&{ zWWJzAuzkNwp6~HKpj2kVvoMoLRLHL$(X;XZXyN4U%sSPCNXP?iQ*DES?!c#_xvHpdN8s zp!4YuJHZl%&6mI??VhSr6aJOXe5W-Cdf7ASSr z#tb3=_54~M7hP%B`k|_f?j!L6OwaB;49Npke;k0#r0n-#m&@a#7~D_kxOt$UKB=zw zY--BQ4{dwA%ydSMe|KrevPfQ$ZmTYb$GJ^c8Rizgaj#}n%~%x#p{YV}b!E@DBvzgV z2P%cD{7Zu0njPLpQNh=*+((ATIw_HGai9MKMhwG#B9F^`^PpTM|KYU=ic2fY?$tGu zaIG>zMY`UEiX5B+arX1WP=13Ni_HvAE(bFq-Zwz)bP@5(KF2G!)bJ+J8z~lxh>)eo z6hb=ISs5pF{dYo9X)6CZRQ`CiOl|ALM83_!#}#`GjUm!>iG+xWT5uQ((;T!_i;md= z-^3Emw^VDPAz^80N&10gVOKd%P@?BA9!kOf-PPl9XNiO=^O4whD~AJaVXQ9a2ZNu* z%p>ok{SxxPRStUbC=|UV(CXF(Odf1bRaS->=9r;cEInNkYEz@DoCD~@S&db_AP%RT zd?L*WJPGJ5nJi3ETJoU+?f$<_78)3aODH-qP}s2VCWYXAh7Dkzw}HKdIumTWpB1Ct z1|%Nh-@4e}$C(*{l38p4f509VFzamoLsdqg1FtGoYy}Hn6y~mii&5b+9(V)@U50&% z?aZ-g2M%axClzb(_}P7!vGAAI|K_*XFM{xQP}8UHB`YuAmq`La=hHTAsX``76=8pQ9lOz`$zj9&M6QfERL-yKL+FlxgNqKBS(ji-)8ewpQ z8w@xo01*hXD(oas%-S^?d>toijP7XTfvOZOi%my`to{RUo|vDd;eJ3<#~3- zfif}#;>^mFfm$@$&Q3*4WiEX-T03>l>Ob}|+VP03>0TftDc?CYLB64Dc3{HHw4n2? zyTPv~e(#5hnkN$VtT(xEqV_4bH3D*n

    dT_9 zmtRwr5y6Qmsh|=xoOUy%73+rBX2YOsG~0AjRt{C|)TyXHotKu-DZUp!^rk0m9QF(o zc<7?tze4`{6a{#8TiAh!n!Nk@~mEmeP zyYlYg`aQQ3%Y=jkD(os8!U*T>3aq_(>BS_ptRVBBi*S2Qi2Gt4dr5d9;wo8fKdmsH z@E#a}t*}Aa?vK8|w>fn%-+(1@jXJP5H&d)q`O-i{kuF=##ze{tOQqtIbdBw@n8>xE z*@gfHWrpTtx~@@~X{ZUXx#tNn9x*8ZGyR34HUX}xB~37T1jWv5O+@{-*;#ElU2=N| zWxCv4n#82t-5qMxFJ@z3GYpK_SQ+9~6QH2wX$MrK}>~Ko;P&zjQ3)rw6uD4*IQ~9PlECi};S`&CO}B&-1V4 zi93(Yx3Y99UN6^vi**nS#Xtu7CIP2v51Yf~%~d3^TtO&LX(UE@uEXpM+->B3c&7sx zjG7u6phzAE@Db0?98QibCE`fgBqJG-(21ST5BkYvpfl6a6m(u!XQGM_AeLqeZhP81 zn^7P!0F%(7B3w27u5hx>CtVu9uIk;6%!K1eoz0Aj?M+`$p@vh@T3Rp2(yR58(9?gA z{P=jtr^ZHAl{L38HFdywU-xB#vNxfQTe+FLnCvn?Fa#fv28i~lhT<@zqjLlrNmN(7 z_lAc3R@C%9id(3_maV=QzP@In=-*qYm=h`7swMizSoz~;}%E>iGtI9Jy#T^C3KAO|z;GryA zgxe7Pu3MK+7ZvuoS82GS$s?h2pk-IzrGe;M&Qa7IF145ybKg6UzE^mX@|#=;eBx| zS;|yO_$2gNI08Nr(YdxSyK`|ud_)WVBTqNNC_t`TA?;}ud(s>mDIKYU*G7}m(@1tI zrJCLpFKd#dw0cd>%$w7ug2*4I#H}^=@y?kzAJ*Wz{h-x&^__BWs*JR^%eG=aGoC6U zu~ae&d3U;oxkkYMwU^N~aNtSDu+Pz<&q4;6LkTrHzO5zLh=vQK8FJQn@&@D?`xoad z6UmD$weaj(FNB(kmh`uumnaZ-;^S@fMrf=Qv+Ux4 zXWA3Vq=r-Q^QS!^WJChXgQUS?LX|dRg%K@-h)WxepmuKLRqndq~>Iey;NZm76GYGj;1O)UI@XL0=gPFkh$1d zXbPNxg`e1RQ=Mtu%K`D9lNwq}3ZhH`6`jqu-bRcd)v*aMNdcrTG~+eozs%# zlYG#@O6!8{vJM>5g?dg5!X2q@;hzgBSLt~;7-tP`O&;Iqa?xyToE5PH;aFR{B5X7G zDQi0|8tSLZil03*Ha521nM9QAXhTr&4l||6$6+Q&umhe<*%1hX0D#s@MZYDd<@Tr3 zZLM)mV?v^DJr38B-=$}QnpaI%7<5P=0xD1U+g=$omX8N1vJ0A3!fDdo^#2ew1tFL@ zH8Q;H9C)2~$+f^{uK&#K9i?Cbevk|ZOoJGgIOgDXFkVZip}Oarvln2m-1F}y*0X1gk*T`8OiaP9b0BlW`dtCUPjIoLD1tLOOamx2`*wJ+8Amde_42RJOSo@q`CKZkcZSE%8^<@efiN<>-V7uM(OSgszTi^TFH6Oa7tQFl|1f$lq}x@f{j(Sn z%q&M!o8au}>DdBF06_S2C<;_YK|?W%Ewx)U0=f-{4s6Qd)VHD01TLX^%46vcIrEKh zU)FLz-x{U5h?%5MB5eYUvpinrfsGWW{g*xmj%sNV4<5k5&TZE?GZ_E6&@cjfXY&|D zhOkZ|*K(&o2xdE7(?QQGBC{l(!d?Bnc!^ug9#ATz0q5unB6_%5MEJ#eYWNq;{~Qn2?VYY3QPkD9a&nVQOVxF>v3I%r}vDruWX$};V` zPE`-)qqmt&RScz=nMrCgJNrq`)-8z( z>qTI1Z*O}DLHiw0Ex3j@>&eYVz%@Z6xzk%&~1S% z@3$ygX)<4PuafmIP)j7`AW;Wxh;qj@J`^}Gt04p&Sn_mBEU1#4EJmmF zyTrliz4&ADPubavb$P|MK5s5(dBz!ozHggveUuUj{rD8C;BboT!*pr{gB0-UU&A%q=!j*WYVDeYC zUmc0fyZ_y^+_E`C(aF@5jsG00YL?Q*cmdll+M$8qgG7~!yPXW+sD?oa_UkMr;Pmtu zPRw&gTN;u`ZkS9!T+PAZ3&z9m@MGy8b%AMqa*==x1QVU65}lamO))4m=;Y+2=Xt&g z$_`6ZjDFEL%r9yzEhzzaCrmAP-N+crrtr;WO5wJ7sYnS434Im~A$;-#9u6)R3a-~^ z1q`n`$8FJCpcu0^H#Y%8a(sMzetzD0Z#E4sTQ&)w-E#6h5+*gc!+C4V^biSD%%0zFJzR%XY8K&v@XjScXV|sB+#v~PY^jRx6+)=vs3s3{%fx|I* z$-+-uK>`T`jE?$3fZgHPN9vlx1a9R8omA7Knyp-_NuwVVnVhFIO`2Wd%GJt)T-svH7tpD@iuvKa2)UM$HPQL zm4~>$zrRp9S5aEJ7w9gxlO4QAj|B64^N`WdGIdfsPBZ`s9xML(8E71o*Te=BBq8)Z z14)TaLqj7gD@#yNu+DiO)WvkFv0DYMwe@T@lR@hTi3oBKQ&|B)XS(Md9KI`&{lG8Qr(!WRV3tH{=|Wo08>@P#fie0AT6lsR(l= z2H(At@J>)cAup23%@x6T*ybh(7Y{aTtRmvSE^hcr^G*8lb~tslB@Rd_DC#mYd`A(P zL%Hwl)N{9HBpQFm*X87BS^B?(WE<}vnHiiA5 z3SzIv(wm{lTv|Wf-^^56h2XOpYy$k)6MoOc_aalJ#v1+Czb>bA9mg>6@TSs)@2Lit zKgiakrK8gz#|8x+#y-2l>aG{*@`^M6~dK=N1FgK{?^Y&nq-jCb~GosyKU6I@!W*84gN{n)bX~&N*HNM4fBe0Mwm;y zUiUETi>JHNu9;4|Ug(RGjV|^^YrTuCv`=~YJg*=a^jlG9m*`8@(WKAUp9_jw_sumn zOMCQFQ|-}d35h=*`tgpPZM>ynE|N-E+^0+jT%ZY5u^50$W_`w<_ZJH#vWiA013N`D z1V6Jr<~;%?Wh(#zCMM-d0i~BE9f$GoVRPUUPP_L?bhErn3+{(#RI${O+D)E1H3tAz zB=ZXqzXS{r&POriW7;V`S^#~SC_oN%u>hu31j!BbvD@?+$WcvKI_e{USW;B%N)Bs9w17ww zuq|V+65OR4!a>{`u+0OXh)*}YM8ZV2iOMddVeQi(>tcTWD*Kr*4~I2sx=hINYnv+f zbJ9J{r7W4R@^o7;TMK!=MXgZ#{CNtD#sdMea z1a_+>Whoy-G<6e2MaA|0q#6!T718V9;2@GFrW`=0Mmz7p5JZE<8bRsKUKG5k#=b!HrT)-H}xGYrS}qp~U=r zl$1H2@>T)s7pOhcfn?x_)WpQZ)Iz(ux=Kn*)A1>v;NpsjHF*BgWY0tJQG8AuDS3HM z7)b3=&+cywOk%T#;A=xwH_=$o3lT~vaLt%hQS8)Z3<`obWlG5ej*`LBxM zy6(HVXt6wa{m(h1wEqBX0`}3;oeY1`34!9NekK z=M15ZOZl!0J&P!@(Y*CfBa8?w!H43CU#TlLJv_~yNrh7Y?=GtWgNtFcOuppXfX0~a zK)zZWEg~zvvXp`cgq(e(%^!qxi22;rgW>fWT#wIw8qy)?HhIcO=2Y)u5dDeu$?i}) z5f91gIL}06Y3bGQg+96pqOaG#BOh{`$b1|LWilj+l;oal9a&zeDRTy*GTpOb;hFoj zzmw5kHKe`+HxwP$NF5T%@@3yrycGsp!U33Q0#_K>oKu%X##&qwLp`MloTLXMa^!)8UN$=`20Au5b8DrfnQfwpnCSj z))-AVEvYsDN7q2d@)8pX1$CtJQr!UH`*-q6u)^$09T>S-xDbzD7Zsr7@??qO)EeMp zUmk5Lf$9y-&CNhwkyZ>85$5V(5iV@_YPJvqbLn=aRZEkslk>QGb^(A8PycE76)qJ+ z2Lj5$cK|)ES!#q7W4|}c$ zvQpA+P|}UCRS+bIX%1dV!?XU|=rCv$C<H`K<1|6;vQM9^uABUNBl!9yz#j)epOz~6ikO1qq53CI>E~LSBx&0ji%Eob%9xEl> zYx70I?+TZ@4O0`4dp=<52Y($@Ff zIE$Ho1cLT30MEsSKAC^N1Y!n4yuRp+lx?ZXWxo&go-Yc!hZIw5;8Nc%kqy)23<$Oo zpQOvX%u+M?l#?2RHlw}%j^k}prlC}x(8##%E9pjpr$j6V^V&Rl2q@k-GiUO2urRO7 zp^5FBvF^M6mlo_aS{?J68JQ7cU6*KQY+F$xO+F4kWS5@mZXplGQj);ceXg;cv8U^7wvQ}Q(gtc*(7oub~f5wq7HZz zeW!0_lN536pVx**MDT-azoP9ohsi7~EJA$s8r?Vd_V|GA2egE(p{WcI?f+lj$?aq* z+~UWU1IfJ$f`mJsHhVcT3GYxgRRXWtC?*MIfpIQNOEd6%>;-?sJ`k={&AT_quedZ9 zRiu=aN3&BryX`<>Y0)?a-TFcGYpoD^?Xy^@WDLDbkr2mA77+OdXPtW!%Hbin@ap31teEhm@RD!mqc*SLKx4F8pqu3GCF)6#s{G73a&V@W7Z)Gl z;Eb0Tilq@KKK1%_tX2UX1L21L1uaH?ub)c@R2ieA%95xA?3SQVgXKP;R!nL?qra0e z++Zl5*9O#mSfEx*InWsOpaZobA$`CfqEXIy4Q>iaOHg_WY@A%3I;U5!p2{8DdlC^7 z>s4B6U`UXzCG)s^W9Gm5(ZcI?LP-Jn*QbUxrBVFqZBY>eS$i-ZCJ_<6gMGQ}djAs+ z4i0{Pem)#0rISMt`ksA%sr!es4cIs#;7Wn7KKG~uiz0DqIrkSq^?o8EBEX99IzPzt zwD3#8#s169X0%X7#4;JD{6y(>eV*;(Bdn{NOyZT!kVz%BA=+?nnC92TF(_z)d3qY6 z%lH;bMFLiNn1gSY=vE@j_h|D6qGovI9t~vmfIv#`G@yQ@b zjw<;`91v{eo2uhC+l6x3JMDL>?_kWA%iIQNg>|X zz}wDjN6?%+pmR-0YoT#F-K!`r9y~|C#t=%m_nWVi>V<)c$;-pTx|i-gZSnmC5PM)m z2Z5WT?TMn)d*}*$yKJxBAdmwX`y$l~$Z5gqJ_gVBV~9KtjOI}9J>ioo^LUdThDh^iP8 z&$klO(yw`uAlHJicb@XVqN;$$f(rSD3Rwh{G+;kLUO^t3K<`O|+yj#6j~-!y;w?W;oM52{sjNU~z~8AVhmkDD*wUYehx3(m zkx{c17C`63v>SBWSOGjUfTe27I-Ml1tlY;QOV<^)wq66(z6uKH^3`q_X)V9B6GGY9 z=BK8TW#7+#P|0M%1ii+)?e!ZKI?_kv(vQ_^O3`vd?AMnnjPmkvrbU>SCQHyF$sLzA zr@~L#TYI;r%IIh~e}_pX)Pu`@U8-?%PMKR0WNWhif1{C*gB=`>sE_FV<42xmrA>+{ zRMYPKK%z*Gcsx0`P!l8_xIJ9UNN(t-0jEYs=NWhnX{mWP6H!c+m0QSlH@^sG%>zrc-O546O zz|WxpfX{gJ{=?w@4OQc@^b$V~n~xx?GCN*bUs16Nus`BifF8jF} zK-im;N;CPi^V+U7C^#`I*?y&y3v}n5-7kC=pm#srxz7T5-|>khC6sufv-Pbjxp~;f zCv(Ysybqu7mN{A7>xQM+0CXzw%HkQoLeWM9cLNlhRQK}FWmdYj7g`n2z|V$Jm=sH~ z898bLwsW<3$RKl$Z}9=Ji*l6?0R>3O1Y}vmL=^_oOq7;Y=4EdufEfatfDc9u(STY7 zt{>FN3a)|SF9QZ}uC&BMuDU6EQvM3@c6Zevimd;rn@5rr?{{=%4chkIZp;Hl;uLB% z#2LCL)UVruf}3vUvph~phw%UD$Nh9o@%ZY#J&bzpAO4s#EcApg>^2`Zw3`$pG`LkB zjy|CNw))NY3CP2MgbN$UMn_EhKftptx%xH($Ojjf=-qvNtXEpX|LC_xm7XC?je_;# zxUd&iH#HvAAria^%oY>9CeIqGn*zn}Di>Yr$1$({S4IIs3>CEr;NlRk<*R{t?!<)6 zv*DXD=6}f+Y_Ap;x_V9+raiXqN$R=0cDbIfDL*|78Bt#ZZbuBI{s91FpX}?kfykyt zy~kxe0f%SCQGpi!@%FmDp;Dofl|PLAFyQ3*RQ<^UbBIME%8n9Kpy4CT1YIMnuS}qESaO{oX8!mlkaK&1K_1QfS zTN&6tk`VxiX7}q=iPyz9e$dh41TIHdWWUUP_@PX~c-j?6D~!-f_9ks-cj_gi3>$aH zmgO@8Py?`F#W{g+Di44AmN=XtUOxI`OT`3aK-bnxfMk=#37v!Df9Y31fymcta|TI9 zeKA)9VIi{!@oTpK=F)rDlw?rm4kqO;C?-l^-4DDQ(GH?Z34oWKpi+4K8KUq?(9%2ngH%v zBDAEOwl8nG(Syk9BhefIILZufH}PXYNNlv#^e^UXN$=ouy^h8Ibm81yO~(?G(a>;o z@SiM#AAsc(N-$wFmPa+a2r>+r>~e`OC}}Ne$)FQXPpMj_d{MY#q55iKofw!cW@UQ( z=#>EUa-&9vF!mbYOYI&X@Ndd@-mB|AeE@>2uFHEAi9A1wF5jwASXgN$S^t*x-4& z%Z-5}T``)w+zY2?NrN*Y4r%o?2qf}5-G8HO7 zvGV}-sT+CNo<+aajh(J^UnQh;8h;*XGn>8KiCG}^?Vqdrpi9L|33ce<)Gd#p0ZCPp z2=a=l8)lCSho^Kx<}55DK;?@IE9bm2wzg&m%#@<0>&QCO=-g=6W5OCqP$}fuWlRTP z_4999?SE`XK`Y_6yLx0a5)#d0{SE!xpe zo$F|G#pipXAz5mYN*_y&^qqdA%cWKpf~AT80^oI7YABJ8Ttegx&?0=-)l&elF`lDI z*#t<5-7yT?i;Fl@9#~?V9_0yF91)&R-wKq@BmIobS}3>Die|<~gxb+C6q2pb@tR zD}4c)?{ElEa$KG}du|708~`)HzsK)yz+R)Bkzdm*~0?#C-tkM#CwRXPZ&^cgIxBJU9h|Rlv?wg`QKVkW$h8}VSaPRW(kn@)hvbB)uyl}8?FDsLC zTE=nu2j|qq8)Hx^$bKZn_4UbfJ219*Hb?68 zm2C);6d{pTiSAPpjf?&}qVxdTLaA#=576A4PVdnD4-L)w0T%T-J|_n^6BYT>!h z2IEu(nimn&T}V9K=ZEw33>U&_s3-t2&-ACLWoz8bQ0;ttQx7o+yo8)zqpjqho)0K1 zwIpN7W?a5UyMofrePd#o_5$vQ@M5DeylT80Y`1DW8log`B5?)O#HwG?ZvkoK;n#?_ zY&*5z{01jOX0Vr%e2y49pdIS(bL3uO6ReT?-1}#98<^Y5Y)5ve@dUBcCN<^fhp?WX zQyu1G>I9y6YLg}gOq~Dbwa)SOM^o=kX2HW-Sy>xMQ`g)l2$))wL=S%1oB{f&kX@E~ z*Q>9&yCO$-=eEtai@D$n%#e&{!xIN+kKE6%d6Ob-K3f;GCM-N+YbS^)$Ock)lFpmH zBiCi+3>s}+59YQ@(-+8Mn>#GCcNx%dnjvYPlR7)pd3wpsI3e$*#9kz>BUf$kz z@D#x{M78S%YQy@?$aI>dQ(x+aZX?ps3dnTlNP=hPB=G|INHgKbTtQ8G49PMRgC!c5JQoc4FvH2 zn!us3m6Y;-Ez><%VBIpjhpex#dSUz-HSC2bNB=L`-=68(kgbJB7&favC7TS{Wm9C2 z!WZ(d{acxd@PEGwMXxyR1DWE*onc)iqePyC_u|}3DngIJe7sqqqDpY%OYH_pS}d8> zYEoaKafi&{aX3T{AL9FZ9qbO!r9W|@ntEwyZHgEVc~Ny6Jg)0Qe(&V`+Qujml@Ec-JB_mRrf5zQ((E8(7#tiDyM=4UsiM8Ozw;d6Qf+i#rLr zJ#G|f9h!=u!X2q0z`GsP&4TWj0Y6#X=sViDtiFC(LZPFynH-H#Y}eGs3tbx;zte-D z3k{)Ex}_ySCVi!mx|tEOy1K6+b4MV{wKg*oS=bG+i)Q)G;@^gsCX3 zfwQyC1?m?HbWGM!aRTi8igs}!jrni{dJYs^C zn2dwC0Iz+Ti6xUT^il+hd*C#Q5dA9VX^`VXffQ*6612DBwa?fzR8PH(@4I{)KtHEC zNcmKNiw)l4d6!Lb6?H9&jLEv$C>ZxV|dV|M<9@TA~6~Gh~-69co0Yc~>^< z-Ijdw=$tu7+67^_m0VJiUS5t(IDRefinvx1kGze|Vk3f8rfXj?Gd4YcvZhL)sZohf zPif$=s6!?bwXZuT9KzUY5DKclzoZ+NPT6RzR^Pp%K09UMl&D;kV~=$)_|g6QtKgnbyG1JnXcdewi4)vB17T-stDZ@R?PoojgYt?x7@GL2 zaw19Erx**2JzXJ)qaGc2OeBh9{M{*cgclWcH9d3YfJ$w8VahmE)Kn?@ZN`z-BNC3e zu4IyNTCO!yyRe%^jVGZ6|BX%ChO`Zm-wJY#r9E9cbzn_%@m8rtTcy+jCDvWIqrv|b zaCqla)RN|oz_RHFP44VEMYdjGHdfp612ydLtW2TL1=p?yFh*}XJH7YQOvnXT{lpgA zfp1Olf>}DBd;!8UXhYB1)L}7cd_3(kyC-v-ghobqIBMJvZZ^$ZT}-9F*aMrQ;lNs1 znZnR2T2kUzp&k-x48BJi!RR#y9s|K>RBYlQ6vc?RUN{NwvNZkvfX@iu6$K>HwDk}k z1ipHWKQIDvl)zusuY|eYeW1}w51ScUysUORzMDonOEwXY)NJJ7zi&9a1-6a@+Yq>O z=N=}xrv`AKmow0Od}-2;*tN2z+en;hJRsj-P}Rzem>e9e)ldYV81UTG9O@dsq=FL5 zV+^h%;p z(+^b(5h&qJZY4MTx-}a*>lC}Z)`MSP+JyHY*w0zOJqahdX9p^TEW1w;^3s+@p15>n z6+2ykT$X{s%)&wuxZWf*cnIO%rdjCQT3R+NPQQm5ESe(^tiL!z*fOM%heuHi( zvjiY>qu#&$VzR-=!~`rQJsKoFxvyQ<5@vM4sH^ye>u1Cx=-vcIMBL0YhPD;zczwFw zS``?|4|BzCe|=dMv3WT<7PK_uR|aaK&Kf&_bjTojJy+SI8mXCf(P@c4#J=^!+1#p@ z7Uv#<>OyI;J`f(>x zTBaU2?Z6u~R}aSK>HdvyybH9XIlnTHGC*C}P2avRMoBmmd_2OEqwH4fZNKApB37%X zjb!!^lq5YFagC5~LhT7Io;}WQWdYy=_4vAci`?8t+* zGM@T^04bW?3nq_tZ1**qaN{cazGf(;0&Z=NU6gRe7dx>r@UdU|>0-cIPR`}!#wjZ+ zZl`i-mPjhEs`8OAahmx+4Kf(h;wDK+u=u{h2tTeC=LGM+wHTIw6o6rYTA2H9j`_@Nj%P)b~J17FODQT+VsKug=!1oL;uJa0M!~Kh$`F;f&n=Aais) zq`P24;y%|mSe6nl_y}wzL;~R`8oz~_VP0W%ZAVU;OryL;z%ka2%D!MhPH9cl$IUkS zeeB}2H6Io7mWom84=E{^vcF?=ThDSJnUc!6)EdLqa_r203VY=yV%B&FVwO<)ZW(Z0 zFTw=4dY`|y-J0)8x~^!Vr4GZz0k~G!)6;N56j%mv2dlb{Swv{J1Po;7<{nc%E2@>b zYJk%gIB_B}XeUI{fV%^`nIm&tH#n{A=EnLGqQh{5GWYB|Du2V|9(dtmiKPyFY$76d zEm1WWV3Th^`x~xsK{KV!%#3$#a1JiT-LI>9lmafNkL6th6_N3ANn9WOjsHBI-R{pE z1uR5sQms=VQK$3{ox{BbGBUS$7U5xh{2yHh^(OF8m^noIkHVnGOpAMc*+LO|u*l(< zgDM-=nrXE#E1%sqf{bAHGcddITSP%wg^AJh`lO*iX)9a zlg^0`f+Hm7_}S5&LSbuvBxPzp70Fs`;A;&&7GAU7;RKBkNT4Ac8M!_pf0aQehU7CN zC61_w)q!&x)IiD&X#wW<`t+cd)22V&=}dU=V3Ilxi90d+R{v=8heLzq;5VZF>z3@i zJQw(g$p~B?cn#`fnM}2`%8tnO1>KL5}hdOs=RX{J(N?9h!f1sF&Wk9Eb`g6!5f+o(%vG z)pQS$RZEG)I6{oiOS{zSb-y|0Tr_0$#||Jhq1;NN8DdCiG*dXB@lfLxVq6s%?|iDf z*bxZJ6%3OMG$>z^oKc(wIr?jWf^;=;)eG5Z>C;%J6Dr?<6^}_mp)Vv$tKzJcz$+3GM4XR z4Kqt|hlS~PCsmxo;p-3(jHk554YqJd;(7Z&$H8jB@?&IChl(1pl>V4c{=ek^<(AYD z@a=<)MRB^$una-j(Uo?L%yazcRr#il^jOQ0?l>mLkpAK9BZ08dh$%Rt-m!Fj&k>N# z4j?yR2|IO%qWV`l67P+}Iv$Gk3gFJpK|Kj2s0D27909*Se92m`u^LOYK1|--cgdN- zx6kbfBIJtk+5j0m`SIx$tJ0 zk9H5!O9|0r$Ow9aTx@OI0PU-0Jp4LIc?fDNAmD&9`Y~+M)=3EEdX`w3fd=xYA?YpR)~In(aw0wE`-U z%Tb;W8yl0MJsr{`Z5amJ{cLA%TOz>Nk3#^3%5LxNzFyIXvMq3>F3MRTrH3^eB1Esg zu(zxcuCld3y zU6$wIZ~0R0SP{l)s0WlOc!h+>%6ss!$#WcMe;C4}GYZAXbaJKlLztr`r$UP{K|{>` z=8()iALSxwdWOg%E6dc4Hr6$v2oO38nAguVKYqlj_d=`wE&Y$h>^$7YDtnOTWJhR?m-nC7eU8tgXeJ z7sg;&8!Ql;f`c&fam3`-*y~|P41%pXo9DX=j#G&Ie)0lUf3KfF=q@&+9R+v=1t)-* zn3+jk>^+pU)#w)-65xe%GynB?{+A}+-=Zn9o7rD%j*VtYZp$ks=wAF-&HDS#iVX@= WkM_vCm+q&L|HsH)kja!XaQ_$hI!I&y diff --git a/visitor/pom.xml b/visitor/pom.xml deleted file mode 100644 index 5445a94ccaa0..000000000000 --- a/visitor/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - visitor - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/visitor/src/main/java/com/iluwatar/visitor/App.java b/visitor/src/main/java/com/iluwatar/visitor/App.java deleted file mode 100644 index 4de8452e5b88..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/App.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations can - * be added without altering the node interface. - *

    - * In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is - * traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s, - * {@link SergeantVisitor} on {@link Sergeant}s and so on. - * - */ -public class App { - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - - Commander commander = - new Commander(new Sergeant(new Soldier(), new Soldier(), new Soldier()), new Sergeant( - new Soldier(), new Soldier(), new Soldier())); - commander.accept(new SoldierVisitor()); - commander.accept(new SergeantVisitor()); - commander.accept(new CommanderVisitor()); - - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/Commander.java b/visitor/src/main/java/com/iluwatar/visitor/Commander.java deleted file mode 100644 index a11f04d69c9d..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/Commander.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Commander - * - */ -public class Commander extends Unit { - - public Commander(Unit... children) { - super(children); - } - - @Override - public void accept(UnitVisitor visitor) { - visitor.visitCommander(this); - super.accept(visitor); - } - - @Override - public String toString() { - return "commander"; - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java deleted file mode 100644 index ce7cf4d44da9..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * CommanderVisitor - * - */ -public class CommanderVisitor implements UnitVisitor { - - private static final Logger LOGGER = LoggerFactory.getLogger(CommanderVisitor.class); - - @Override - public void visitSoldier(Soldier soldier) { - // Do nothing - } - - @Override - public void visitSergeant(Sergeant sergeant) { - // Do nothing - } - - @Override - public void visitCommander(Commander commander) { - LOGGER.info("Good to see you {}", commander); - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/Sergeant.java b/visitor/src/main/java/com/iluwatar/visitor/Sergeant.java deleted file mode 100644 index 266350bf26f4..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/Sergeant.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Sergeant - * - */ -public class Sergeant extends Unit { - - public Sergeant(Unit... children) { - super(children); - } - - @Override - public void accept(UnitVisitor visitor) { - visitor.visitSergeant(this); - super.accept(visitor); - } - - @Override - public String toString() { - return "sergeant"; - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java deleted file mode 100644 index 48b4e9dba949..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * SergeantVisitor - * - */ -public class SergeantVisitor implements UnitVisitor { - - private static final Logger LOGGER = LoggerFactory.getLogger(SergeantVisitor.class); - - @Override - public void visitSoldier(Soldier soldier) { - // Do nothing - } - - @Override - public void visitSergeant(Sergeant sergeant) { - LOGGER.info("Hello {}", sergeant); - } - - @Override - public void visitCommander(Commander commander) { - // Do nothing - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/Soldier.java b/visitor/src/main/java/com/iluwatar/visitor/Soldier.java deleted file mode 100644 index 681b8961de9b..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/Soldier.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Soldier - * - */ -public class Soldier extends Unit { - - public Soldier(Unit... children) { - super(children); - } - - @Override - public void accept(UnitVisitor visitor) { - visitor.visitSoldier(this); - super.accept(visitor); - } - - @Override - public String toString() { - return "soldier"; - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java deleted file mode 100644 index 10fe49b7e1ac..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * SoldierVisitor - * - */ -public class SoldierVisitor implements UnitVisitor { - - private static final Logger LOGGER = LoggerFactory.getLogger(SoldierVisitor.class); - - @Override - public void visitSoldier(Soldier soldier) { - LOGGER.info("Greetings {}", soldier); - } - - @Override - public void visitSergeant(Sergeant sergeant) { - // Do nothing - } - - @Override - public void visitCommander(Commander commander) { - // Do nothing - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/Unit.java b/visitor/src/main/java/com/iluwatar/visitor/Unit.java deleted file mode 100644 index b904bf3586de..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/Unit.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Interface for the nodes in hierarchy. - * - */ -public abstract class Unit { - - private Unit[] children; - - public Unit(Unit... children) { - this.children = children; - } - - /** - * Accept visitor - */ - public void accept(UnitVisitor visitor) { - for (Unit child : children) { - child.accept(visitor); - } - } -} diff --git a/visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java deleted file mode 100644 index ecf8bf2a5bce..000000000000 --- a/visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -/** - * - * Visitor interface. - * - */ -public interface UnitVisitor { - - void visitSoldier(Soldier soldier); - - void visitSergeant(Sergeant sergeant); - - void visitCommander(Commander commander); - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/AppTest.java b/visitor/src/test/java/com/iluwatar/visitor/AppTest.java deleted file mode 100644 index 23c9bb48f637..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/AppTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import org.junit.Test; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java b/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java deleted file mode 100644 index b0b83cf7366f..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; - -/** - * Date: 12/30/15 - 19:45 PM - * - * @author Jeroen Meulemeester - */ -public class CommanderTest extends UnitTest { - - /** - * Create a new test instance for the given {@link Commander} - */ - public CommanderTest() { - super(Commander::new); - } - - @Override - void verifyVisit(Commander unit, UnitVisitor mockedVisitor) { - verify(mockedVisitor).visitCommander(eq(unit)); - } - -} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java deleted file mode 100644 index 9cf1f2985435..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import java.util.Optional; - -/** - * Date: 12/30/15 - 18:43 PM - * - * @author Jeroen Meulemeester - */ -public class CommanderVisitorTest extends VisitorTest { - - /** - * Create a new test instance for the given visitor - */ - public CommanderVisitorTest() { - super( - new CommanderVisitor(), - Optional.of("Good to see you commander"), - Optional.empty(), - Optional.empty() - ); - } - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java b/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java deleted file mode 100644 index 9266837b4dc2..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; - -/** - * Date: 12/30/15 - 19:45 PM - * - * @author Jeroen Meulemeester - */ -public class SergeantTest extends UnitTest { - - /** - * Create a new test instance for the given {@link Sergeant} - */ - public SergeantTest() { - super(Sergeant::new); - } - - @Override - void verifyVisit(Sergeant unit, UnitVisitor mockedVisitor) { - verify(mockedVisitor).visitSergeant(eq(unit)); - } - -} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java deleted file mode 100644 index 717684300c28..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import java.util.Optional; - -/** - * Date: 12/30/15 - 18:36 PM - * - * @author Jeroen Meulemeester - */ -public class SergeantVisitorTest extends VisitorTest { - - /** - * Create a new test instance for the given visitor - */ - public SergeantVisitorTest() { - super( - new SergeantVisitor(), - Optional.empty(), - Optional.of("Hello sergeant"), - Optional.empty() - ); - } - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java b/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java deleted file mode 100644 index 31dfa0bdee76..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; - -/** - * Date: 12/30/15 - 19:45 PM - * - * @author Jeroen Meulemeester - */ -public class SoldierTest extends UnitTest { - - /** - * Create a new test instance for the given {@link Soldier} - */ - public SoldierTest() { - super(Soldier::new); - } - - @Override - void verifyVisit(Soldier unit, UnitVisitor mockedVisitor) { - verify(mockedVisitor).visitSoldier(eq(unit)); - } - -} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java deleted file mode 100644 index cc15cff8541b..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import java.util.Optional; - -/** - * Date: 12/30/15 - 18:59 PM - * - * @author Jeroen Meulemeester - */ -public class SoldierVisitorTest extends VisitorTest { - - /** - * Create a new test instance for the given visitor - */ - public SoldierVisitorTest() { - super( - new SoldierVisitor(), - Optional.empty(), - Optional.empty(), - Optional.of("Greetings soldier") - ); - } - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java b/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java deleted file mode 100644 index ab84705122d9..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -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 java.util.Arrays; -import java.util.function.Function; -import org.junit.Test; - -/** - * Date: 12/30/15 - 18:59 PM - * Test related to Units - * @param Type of Unit - * @author Jeroen Meulemeester - */ -public abstract class UnitTest { - - /** - * Factory to create new instances of the tested unit - */ - private final Function factory; - - /** - * Create a new test instance for the given unit type {@link U} - * - * @param factory Factory to create new instances of the tested unit - */ - public UnitTest(final Function factory) { - this.factory = factory; - } - - @Test - public void testAccept() throws Exception { - final Unit[] children = new Unit[5]; - Arrays.setAll(children, (i) -> mock(Unit.class)); - - final U unit = this.factory.apply(children); - final UnitVisitor visitor = mock(UnitVisitor.class); - unit.accept(visitor); - verifyVisit(unit, visitor); - - for (final Unit child : children) { - verify(child).accept(eq(visitor)); - } - - verifyNoMoreInteractions(children); - verifyNoMoreInteractions(visitor); - } - - /** - * Verify if the correct visit method is called on the mock, depending on the tested instance - * - * @param unit The tested unit instance - * @param mockedVisitor The mocked {@link UnitVisitor} who should have gotten a visit by the unit - */ - abstract void verifyVisit(final U unit, final UnitVisitor mockedVisitor); - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java deleted file mode 100644 index ba6705b2307e..000000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.visitor; - -import static org.junit.Assert.assertEquals; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -/** - * Date: 12/30/15 - 18:59 PM - * Test case for Visitor Pattern - * @param Type of UnitVisitor - * @author Jeroen Meulemeester - */ -public abstract class VisitorTest { - - private InMemoryAppender appender; - - @Before - public void setUp() { - appender = new InMemoryAppender(); - } - - @After - public void tearDown() { - appender.stop(); - } - - /** - * The tested visitor instance - */ - private final V visitor; - - /** - * The optional expected response when being visited by a commander - */ - private final Optional commanderResponse; - - /** - * The optional expected response when being visited by a sergeant - */ - private final Optional sergeantResponse; - - /** - * The optional expected response when being visited by a soldier - */ - private final Optional soldierResponse; - - /** - * Create a new test instance for the given visitor - * - * @param commanderResponse The optional expected response when being visited by a commander - * @param sergeantResponse The optional expected response when being visited by a sergeant - * @param soldierResponse The optional expected response when being visited by a soldier - */ - public VisitorTest(final V visitor, final Optional commanderResponse, - final Optional sergeantResponse, final Optional soldierResponse) { - - this.visitor = visitor; - this.commanderResponse = commanderResponse; - this.sergeantResponse = sergeantResponse; - this.soldierResponse = soldierResponse; - } - - @Test - public void testVisitCommander() { - this.visitor.visitCommander(new Commander()); - if (this.commanderResponse.isPresent()) { - assertEquals(this.commanderResponse.get(), appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - } - - @Test - public void testVisitSergeant() { - this.visitor.visitSergeant(new Sergeant()); - if (this.sergeantResponse.isPresent()) { - assertEquals(this.sergeantResponse.get(), appender.getLastMessage()); - assertEquals(1, appender.getLogSize()); - } - } - - @Test - public void testVisitSoldier() { - this.visitor.visitSoldier(new Soldier()); - if (this.soldierResponse.isPresent()) { - assertEquals(this.soldierResponse.get(), appender.getLastMessage()); - assertEquals(1, 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 String getLastMessage() { - return log.get(log.size() - 1).getFormattedMessage(); - } - } -}

    - * In this example we use Java serialization to write representations of {@link RainbowFish} objects - * to file. {@link RainbowFish} is the initial version which we can easily read and write using - * {@link RainbowFishSerializer} methods. {@link RainbowFish} then evolves to {@link RainbowFishV2} - * and we again write it to file with a method designed to do just that. However, the reader client - * does not know about the new format and still reads with the method designed for V1 schema. - * Fortunately the reading method has been designed with the Tolerant Reader pattern and does not - * break even though {@link RainbowFishV2} has new fields that are serialized. - * - */ -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); - 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"); - LOGGER.info("deserializedFishV1 name={} age={} length={} weight={}", - deserializedFishV1.getName(), deserializedFishV1.getAge(), - deserializedFishV1.getLengthMeters(), deserializedFishV1.getWeightTons()); - // Write V2 - RainbowFishV2 fishV2 = new RainbowFishV2("Scar", 5, 12, 15, true, true, true); - LOGGER.info( - "fishV2 name={} age={} length={} weight={} sleeping={} hungry={} angry={}", - fishV2.getName(), fishV2.getAge(), fishV2.getLengthMeters(), fishV2.getWeightTons(), - fishV2.getHungry(), fishV2.getAngry(), fishV2.getSleeping()); - RainbowFishSerializer.writeV2(fishV2, "fish2.out"); - // Read V2 with V1 method - RainbowFish deserializedFishV2 = RainbowFishSerializer.readV1("fish2.out"); - LOGGER.info("deserializedFishV2 name={} age={} length={} weight={}", - deserializedFishV2.getName(), deserializedFishV2.getAge(), - deserializedFishV2.getLengthMeters(), deserializedFishV2.getWeightTons()); - } -} diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java deleted file mode 100644 index 441b8a5ef873..000000000000 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import java.io.Serializable; - -/** - * - * RainbowFish is the initial schema - * - */ -public class RainbowFish implements Serializable { - - private static final long serialVersionUID = 1L; - - private String name; - private int age; - private int lengthMeters; - private int weightTons; - - /** - * Constructor - */ - public RainbowFish(String name, int age, int lengthMeters, int weightTons) { - this.name = name; - this.age = age; - this.lengthMeters = lengthMeters; - this.weightTons = weightTons; - } - - public String getName() { - return name; - } - - public int getAge() { - return age; - } - - public int getLengthMeters() { - return lengthMeters; - } - - public int getWeightTons() { - return weightTons; - } - -} diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java deleted file mode 100644 index 7445dec4d67f..000000000000 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.HashMap; -import java.util.Map; - -/** - * - * RainbowFishSerializer provides methods for reading and writing {@link RainbowFish} objects to - * file. Tolerant Reader pattern is implemented here by serializing maps instead of - * {@link RainbowFish} objects. This way the reader does not break even though new properties are - * added to the schema. - * - */ -public final class RainbowFishSerializer { - - private RainbowFishSerializer() { - } - - /** - * Write V1 RainbowFish to file - */ - public static void writeV1(RainbowFish rainbowFish, String filename) throws IOException { - Map map = new HashMap<>(); - map.put("name", rainbowFish.getName()); - map.put("age", String.format("%d", rainbowFish.getAge())); - map.put("lengthMeters", String.format("%d", rainbowFish.getLengthMeters())); - map.put("weightTons", String.format("%d", rainbowFish.getWeightTons())); - try (FileOutputStream fileOut = new FileOutputStream(filename); - ObjectOutputStream objOut = new ObjectOutputStream(fileOut)) { - objOut.writeObject(map); - } - } - - /** - * Write V2 RainbowFish to file - */ - public static void writeV2(RainbowFishV2 rainbowFish, String filename) throws IOException { - Map map = new HashMap<>(); - map.put("name", rainbowFish.getName()); - map.put("age", String.format("%d", rainbowFish.getAge())); - map.put("lengthMeters", String.format("%d", rainbowFish.getLengthMeters())); - map.put("weightTons", String.format("%d", rainbowFish.getWeightTons())); - map.put("angry", Boolean.toString(rainbowFish.getAngry())); - map.put("hungry", Boolean.toString(rainbowFish.getHungry())); - map.put("sleeping", Boolean.toString(rainbowFish.getSleeping())); - try (FileOutputStream fileOut = new FileOutputStream(filename); - ObjectOutputStream objOut = new ObjectOutputStream(fileOut)) { - objOut.writeObject(map); - } - } - - /** - * Read V1 RainbowFish from file - */ - public static RainbowFish readV1(String filename) throws IOException, ClassNotFoundException { - Map map = null; - - try (FileInputStream fileIn = new FileInputStream(filename); - ObjectInputStream objIn = new ObjectInputStream(fileIn)) { - map = (Map) objIn.readObject(); - } - - return new RainbowFish(map.get("name"), Integer.parseInt(map.get("age")), Integer.parseInt(map.get("lengthMeters")), - Integer.parseInt(map.get("weightTons"))); - } -} diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java deleted file mode 100644 index 67430f57c10d..000000000000 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -/** - * - * RainbowFishV2 is the evolved schema - * - */ -public class RainbowFishV2 extends RainbowFish { - - private static final long serialVersionUID = 1L; - - private boolean sleeping; - private boolean hungry; - private boolean angry; - - public RainbowFishV2(String name, int age, int lengthMeters, int weightTons) { - super(name, age, lengthMeters, weightTons); - } - - /** - * Constructor - */ - public RainbowFishV2(String name, int age, int lengthMeters, int weightTons, boolean sleeping, - boolean hungry, boolean angry) { - this(name, age, lengthMeters, weightTons); - this.sleeping = sleeping; - this.hungry = hungry; - this.angry = angry; - } - - public boolean getSleeping() { - return sleeping; - } - - public boolean getHungry() { - return hungry; - } - - public boolean getAngry() { - return angry; - } -} diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/AppTest.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/AppTest.java deleted file mode 100644 index f24393779cb3..000000000000 --- a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/AppTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() throws ClassNotFoundException, IOException { - String[] args = {}; - App.main(args); - } - - @Before - @After - public void cleanup() { - File file1 = new File("fish1.out"); - file1.delete(); - File file2 = new File("fish2.out"); - file2.delete(); - } -} diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java deleted file mode 100644 index a6c7fc641fcf..000000000000 --- a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; - -/** - * Date: 12/30/15 - 18:39 PM - * - * @author Jeroen Meulemeester - */ -public class RainbowFishSerializerTest { - - /** - * Create a temporary folder, used to generate files in during this test - */ - @Rule - public final TemporaryFolder testFolder = new TemporaryFolder(); - - /** - * Rainbow fish version 1 used during the tests - */ - private static final RainbowFish V1 = new RainbowFish("version1", 1, 2, 3); - - /** - * Rainbow fish version 2 used during the tests - */ - private static final RainbowFishV2 V2 = new RainbowFishV2("version2", 4, 5, 6, true, false, true); - - /** - * Verify if a fish, written as version 1 can be read back as version 1 - */ - @Test - public void testWriteV1ReadV1() throws Exception { - final File outputFile = this.testFolder.newFile(); - RainbowFishSerializer.writeV1(V1, outputFile.getPath()); - - final RainbowFish fish = RainbowFishSerializer.readV1(outputFile.getPath()); - assertNotSame(V1, fish); - assertEquals(V1.getName(), fish.getName()); - assertEquals(V1.getAge(), fish.getAge()); - assertEquals(V1.getLengthMeters(), fish.getLengthMeters()); - assertEquals(V1.getWeightTons(), fish.getWeightTons()); - - } - - /** - * Verify if a fish, written as version 2 can be read back as version 1 - */ - @Test - public void testWriteV2ReadV1() throws Exception { - final File outputFile = this.testFolder.newFile(); - RainbowFishSerializer.writeV2(V2, outputFile.getPath()); - - final RainbowFish fish = RainbowFishSerializer.readV1(outputFile.getPath()); - assertNotSame(V2, fish); - assertEquals(V2.getName(), fish.getName()); - assertEquals(V2.getAge(), fish.getAge()); - assertEquals(V2.getLengthMeters(), fish.getLengthMeters()); - assertEquals(V2.getWeightTons(), fish.getWeightTons()); - } - -} \ No newline at end of file diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java deleted file mode 100644 index 87c7a3e78f20..000000000000 --- a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/30/15 - 18:34 PM - * - * @author Jeroen Meulemeester - */ -public class RainbowFishTest { - - /** - * Verify if the getters of a {@link RainbowFish} return the expected values - */ - @Test - public void testValues() { - final RainbowFish fish = new RainbowFish("name", 1, 2, 3); - assertEquals("name", fish.getName()); - assertEquals(1, fish.getAge()); - assertEquals(2, fish.getLengthMeters()); - assertEquals(3, fish.getWeightTons()); - } - -} \ No newline at end of file diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java deleted file mode 100644 index 789da4f1e14f..000000000000 --- a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.tolerantreader; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Date: 12/30/15 - 18:35 PM - * - * @author Jeroen Meulemeester - */ -public class RainbowFishV2Test { - - /** - * Verify if the getters of a {@link RainbowFish} return the expected values - */ - @Test - public void testValues() { - final RainbowFishV2 fish = new RainbowFishV2("name", 1, 2, 3, false, true, false); - assertEquals("name", fish.getName()); - assertEquals(1, fish.getAge()); - assertEquals(2, fish.getLengthMeters()); - assertEquals(3, fish.getWeightTons()); - assertEquals(false, fish.getSleeping()); - assertEquals(true, fish.getHungry()); - assertEquals(false, fish.getAngry()); - } - -} \ No newline at end of file diff --git a/twin/.gitignore b/twin/.gitignore deleted file mode 100644 index b83d22266ac8..000000000000 --- a/twin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/twin/README.md b/twin/README.md deleted file mode 100644 index 092032a55f77..000000000000 --- a/twin/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Twin -folder: twin -permalink: /patterns/twin/ -pumlid: 7SR13OCm30NGLUW0n7UsCS42eyH4zdUpFbNVwNtKQij3qjjo0ICs8kTPJiMLUuPuVGnYAFNff2qdWvrk_l9wIEXfws10t88wno-4gKQ2-az9xsLaRoy0 -categories: Creational -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent - Twin pattern is a design pattern which provides a standard solution to simulate multiple -inheritance in java - -![alt text](./etc/twin.png "Twin") - -## Applicability -Use the Twin idiom when - -* to simulate multiple inheritance in a language that does not support this feature. -* to avoid certain problems of multiple inheritance such as name clashes. - -## Credits - -* [Twin – A Design Pattern for Modeling Multiple Inheritance](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf) diff --git a/twin/etc/twin.png b/twin/etc/twin.png deleted file mode 100644 index 724092525bd6a90f6da664b1038c2493228fb5e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29682 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

    4nMzkVrZ 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%0A7q{J_-UOqLOp3(!|U1qV;lIx<) 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 PE-^e^{an^LB{Ts5#7Ir7 diff --git a/layers/etc/layers.ucls b/layers/etc/layers.ucls deleted file mode 100644 index 060b391c0acf..000000000000 --- a/layers/etc/layers.ucls +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/layers/etc/layers.urm.puml b/layers/etc/layers.urm.puml deleted file mode 100644 index e597c7546ec4..000000000000 --- a/layers/etc/layers.urm.puml +++ /dev/null @@ -1,126 +0,0 @@ -@startuml -package com.iluwatar.layers { - class App { - - cakeBakingService : CakeBakingService {static} - + App() - - initializeData(cakeBakingService : CakeBakingService) {static} - + main(args : String[]) {static} - } - class Cake { - - id : Long - - layers : Set - - topping : CakeTopping - + Cake() - + addLayer(layer : CakeLayer) - + getId() : Long - + getLayers() : Set - + getTopping() : CakeTopping - + setId(id : Long) - + setLayers(layers : Set) - + setTopping(topping : CakeTopping) - + toString() : String - } - interface CakeBakingService { - + bakeNewCake(CakeInfo) {abstract} - + getAllCakes() : List {abstract} - + getAvailableLayers() : List {abstract} - + getAvailableToppings() : List {abstract} - + saveNewLayer(CakeLayerInfo) {abstract} - + saveNewTopping(CakeToppingInfo) {abstract} - } - class CakeBakingServiceImpl { - - context : AbstractApplicationContext - + CakeBakingServiceImpl() - + bakeNewCake(cakeInfo : CakeInfo) - + getAllCakes() : List - - getAvailableLayerEntities() : List - + getAvailableLayers() : List - - getAvailableToppingEntities() : List - + getAvailableToppings() : List - + saveNewLayer(layerInfo : CakeLayerInfo) - + saveNewTopping(toppingInfo : CakeToppingInfo) - } - interface CakeDao { - } - class CakeInfo { - + cakeLayerInfos : List - + cakeToppingInfo : CakeToppingInfo - + id : Optional - + CakeInfo(cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List) - + CakeInfo(id : Long, cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List) - + calculateTotalCalories() : int - + toString() : String - } - class CakeLayer { - - cake : Cake - - calories : int - - id : Long - - name : String - + CakeLayer() - + CakeLayer(name : String, calories : int) - + getCake() : Cake - + getCalories() : int - + getId() : Long - + getName() : String - + setCake(cake : Cake) - + setCalories(calories : int) - + setId(id : Long) - + setName(name : String) - + toString() : String - } - interface CakeLayerDao { - } - class CakeLayerInfo { - + calories : int - + id : Optional - + name : String - + CakeLayerInfo(id : Long, name : String, calories : int) - + CakeLayerInfo(name : String, calories : int) - + toString() : String - } - class CakeTopping { - - cake : Cake - - calories : int - - id : Long - - name : String - + CakeTopping() - + CakeTopping(name : String, calories : int) - + getCake() : Cake - + getCalories() : int - + getId() : Long - + getName() : String - + setCake(cake : Cake) - + setCalories(calories : int) - + setId(id : Long) - + setName(name : String) - + toString() : String - } - interface CakeToppingDao { - } - class CakeToppingInfo { - + calories : int - + id : Optional - + name : String - + CakeToppingInfo(id : Long, name : String, calories : int) - + CakeToppingInfo(name : String, calories : int) - + toString() : String - } - class CakeViewImpl { - - LOGGER : Logger {static} - - cakeBakingService : CakeBakingService - + CakeViewImpl(cakeBakingService : CakeBakingService) - + render() - } - interface View { - + render() {abstract} - } -} -CakeViewImpl --> "-cakeBakingService" CakeBakingService -CakeInfo --> "-cakeToppingInfo" CakeToppingInfo -CakeInfo --> "-cakeLayerInfos" CakeLayerInfo -App --> "-cakeBakingService" CakeBakingService -CakeLayer --> "-cake" Cake -Cake --> "-topping" CakeTopping -CakeBakingServiceImpl ..|> CakeBakingService -CakeViewImpl ..|> View -@enduml \ No newline at end of file diff --git a/layers/pom.xml b/layers/pom.xml deleted file mode 100644 index d15b524de4ed..000000000000 --- a/layers/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - com.iluwatar.layers - layers - - - org.springframework.data - spring-data-jpa - - - org.hibernate - hibernate-entitymanager - - - commons-dbcp - commons-dbcp - - - com.h2database - h2 - - - junit - junit - test - - - org.mockito - mockito-core - test - - - diff --git a/layers/src/main/java/com/iluwatar/layers/App.java b/layers/src/main/java/com/iluwatar/layers/App.java deleted file mode 100644 index 2dfeee90595b..000000000000 --- a/layers/src/main/java/com/iluwatar/layers/App.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.layers; - -import java.util.Arrays; - -/** - * - * Layers is an architectural style where software responsibilities are divided among the different layers of the - * application. - *

    - * 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.guarded.suspension; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * Test for Guarded Queue - */ -public class GuardedQueueTest { - private volatile Integer value; - - @Test - public void testGet() { - GuardedQueue g = new GuardedQueue(); - ExecutorService executorService = Executors.newFixedThreadPool(2); - executorService.submit(() -> value = g.get()); - executorService.submit(() -> g.put(Integer.valueOf(10))); - executorService.shutdown(); - try { - executorService.awaitTermination(30, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Assert.assertEquals(Integer.valueOf(10), value); - } - - @Test - public void testPut() { - GuardedQueue g = new GuardedQueue(); - g.put(12); - Assert.assertEquals(Integer.valueOf(12), g.get()); - - } - -} diff --git a/half-sync-half-async/README.md b/half-sync-half-async/README.md deleted file mode 100644 index 55891e770601..000000000000 --- a/half-sync-half-async/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: pattern -title: Half-Sync/Half-Async -folder: half-sync-half-async -permalink: /patterns/half-sync-half-async/ -pumlid: RScv3SCm3030LU819FRPXg5fIm552tnYPFiyjRi3RkbAaYkdoQr5JBy369vrxz7oaSv6XmPhL3e6TCaJ0msU-CAoilTToyG8DdKOw5z0GzcAlvNAN_WZSD1brBHHPmxv0000 -categories: Concurrency -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -The Half-Sync/Half-Async pattern decouples synchronous I/O from -asynchronous I/O in a system to simplify concurrent programming effort without -degrading execution efficiency. - -![Half-Sync/Half-Async class diagram](./etc/half-sync-half-async.png) - -## Applicability -Use Half-Sync/Half-Async pattern when - -* a system possesses following characteristics: - * the system must perform tasks in response to external events that occur asynchronously, like hardware interrupts in OS - * it is inefficient to dedicate separate thread of control to perform synchronous I/O for each external source of event - * the higher level tasks in the system can be simplified significantly if I/O is performed synchronously. -* one or more tasks in a system must run in a single thread of control, while other tasks may benefit from multi-threading. - -## Real world examples - -* [BSD Unix networking subsystem](http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf) -* [Real Time CORBA](http://www.omg.org/news/meetings/workshops/presentations/realtime2001/4-3_Pyarali_thread-pool.pdf) -* [Android AsyncTask framework](http://developer.android.com/reference/android/os/AsyncTask.html) - -## Credits - -* [Douglas C. Schmidt and Charles D. Cranor - Half Sync/Half Async](http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf) -* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697) diff --git a/half-sync-half-async/etc/half-sync-half-async.png b/half-sync-half-async/etc/half-sync-half-async.png deleted file mode 100644 index 84658dfdeafcdfd782629c4b55060404d04323a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32866 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 diff --git a/half-sync-half-async/etc/half-sync-half-async.ucls b/half-sync-half-async/etc/half-sync-half-async.ucls deleted file mode 100644 index 5b9941872447..000000000000 --- a/half-sync-half-async/etc/half-sync-half-async.ucls +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/half-sync-half-async/etc/half-sync-half-async.urm.puml b/half-sync-half-async/etc/half-sync-half-async.urm.puml deleted file mode 100644 index 1dd9c1d83432..000000000000 --- a/half-sync-half-async/etc/half-sync-half-async.urm.puml +++ /dev/null @@ -1,31 +0,0 @@ -@startuml -package com.iluwatar.halfsynchalfasync { - class App { - - LOGGER : Logger {static} - + App() - - ap(i : long) : long {static} - + main(args : String[]) {static} - } - ~class ArithmeticSumTask { - - n : long - + ArithmeticSumTask(n : long) - + call() : Long - + onError(throwable : Throwable) - + onPostCall(result : Long) - + onPreCall() - } - interface AsyncTask { - + call() : O {abstract} - + onError(Throwable) {abstract} - + onPostCall(O) {abstract} - + onPreCall() {abstract} - } - class AsynchronousService { - - service : ExecutorService - + AsynchronousService(workQueue : BlockingQueue) - + execute(task : AsyncTask) - } -} -ArithmeticSumTask ..+ App -ArithmeticSumTask ..|> AsyncTask -@enduml \ No newline at end of file diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml deleted file mode 100644 index ac8464d759d2..000000000000 --- a/half-sync-half-async/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - half-sync-half-async - - - junit - junit - test - - - org.mockito - mockito-core - test - - - 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 deleted file mode 100644 index bf35416ca180..000000000000 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.halfsynchalfasync; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.LinkedBlockingQueue; - -/** - * - * This application demonstrates Half-Sync/Half-Async pattern. Key parts of the pattern are - * {@link AsyncTask} and {@link AsynchronousService}. - * - *

  • - * 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.converter; - - -import java.util.Objects; - -/** - * User DTO class - */ -public class UserDto { - - private String firstName; - private String lastName; - private boolean isActive; - private String email; - - /** - * @param firstName user's first name - * @param lastName user's last name - * @param isActive flag indicating whether the user is active - * @param email user's email address - */ - public UserDto(String firstName, String lastName, boolean isActive, String email) { - this.firstName = firstName; - this.lastName = lastName; - this.isActive = isActive; - this.email = email; - } - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public boolean isActive() { - return isActive; - } - - public String getEmail() { - return email; - } - - @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - UserDto userDto = (UserDto) o; - return isActive == userDto.isActive && Objects.equals(firstName, userDto.firstName) && Objects - .equals(lastName, userDto.lastName) && Objects.equals(email, userDto.email); - } - - @Override public int hashCode() { - return Objects.hash(firstName, lastName, isActive, email); - } - - @Override public String toString() { - return "UserDto{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' - + ", isActive=" + isActive + ", email='" + email + '\'' + '}'; - } -} diff --git a/converter/src/test/java/com/iluwatar/converter/AppTest.java b/converter/src/test/java/com/iluwatar/converter/AppTest.java deleted file mode 100644 index 091fbe2cac2c..000000000000 --- a/converter/src/test/java/com/iluwatar/converter/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.converter; - -import org.junit.Test; - -/** - * App running test - */ -public class AppTest { - - @Test - public void testMain() { - String[] args = {}; - App.main(args); - } - -} diff --git a/converter/src/test/java/com/iluwatar/converter/ConverterTest.java b/converter/src/test/java/com/iluwatar/converter/ConverterTest.java deleted file mode 100644 index 9fc2e2a0c2a0..000000000000 --- a/converter/src/test/java/com/iluwatar/converter/ConverterTest.java +++ /dev/null @@ -1,84 +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.converter; - -import com.google.common.collect.Lists; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import static junit.framework.TestCase.assertEquals; - -/** - * Tests for {@link Converter} - */ -public class ConverterTest { - - private UserConverter userConverter = new UserConverter(); - - /** - * Tests whether a converter created of opposite functions holds equality as a bijection. - */ - @Test public void testConversionsStartingFromDomain() { - User u1 = new User("Tom", "Hanks", true, "tom@hanks.com"); - User u2 = userConverter.convertFromDto(userConverter.convertFromEntity(u1)); - assertEquals(u1, u2); - } - - /** - * Tests whether a converter created of opposite functions holds equality as a bijection. - */ - @Test public void testConversionsStartingFromDto() { - UserDto u1 = new UserDto("Tom", "Hanks", true, "tom@hanks.com"); - UserDto u2 = userConverter.convertFromEntity(userConverter.convertFromDto(u1)); - assertEquals(u1, u2); - } - - /** - * Tests the custom users converter. Thanks to Java8 lambdas, converter can be easily and - * cleanly instantiated allowing various different conversion strategies to be implemented. - */ - @Test public void testCustomConverter() { - Converter converter = new Converter<>( - userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(), - String.valueOf(new Random().nextInt())), - user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), - user.getFirstName().toLowerCase() + user.getLastName().toLowerCase() + "@whatever.com")); - User u1 = new User("John", "Doe", false, "12324"); - UserDto userDto = converter.convertFromEntity(u1); - assertEquals(userDto.getEmail(), "johndoe@whatever.com"); - } - - /** - * Test whether converting a collection of Users to DTO Users and then converting them back to domain - * users returns an equal collection. - */ - @Test public void testCollectionConversion() { - ArrayList users = Lists.newArrayList(new User("Camile", "Tough", false, "124sad"), - new User("Marti", "Luther", true, "42309fd"), new User("Kate", "Smith", true, "if0243")); - List fromDtos = userConverter.createFromDtos(userConverter.createFromEntities(users)); - assertEquals(fromDtos, users); - } -} diff --git a/cqrs/README.md b/cqrs/README.md deleted file mode 100644 index 3cdd429a17dd..000000000000 --- a/cqrs/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: pattern -title: CQRS -folder: cqrs -permalink: /patterns/cqrs/ -pumlid: 7SPR4a0m3030gt00pR_RH6I8QQFouFgC_TfHb6gkd5Q7FQBx363ub4rYpoMTZKuDrYXqDX37HIuuyCPfPPTDfuuHREhGqBy0NUR0GNzAMYizMtq1 -categories: Architectural -tags: - - Java - - Difficulty-Intermediate ---- - -## Intent -CQRS Command Query Responsibility Segregation - Separate the query side from the command side. - -![alt text](./etc/cqrs.png "CQRS") - -## Applicability -Use the CQRS pattern when - -* you want to scale the queries and commands independently. -* you want to use different data models for queries and commands. Useful when dealing with complex domains. -* you want to use architectures like event sourcing or task based UI. - -## Credits - -* [Greg Young - CQRS, Task Based UIs, Event Sourcing agh!](http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/) -* [Martin Fowler - CQRS](https://martinfowler.com/bliki/CQRS.html) -* [Oliver Wolf - CQRS for Great Good](https://www.youtube.com/watch?v=Ge53swja9Dw) diff --git a/cqrs/etc/cqrs.png b/cqrs/etc/cqrs.png deleted file mode 100644 index 28174bc9ab8ef388ca5142e26e54d0f9e3bab635..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105666 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ℑLH=hIn`f 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cqrs/etc/cqrs.urm.puml b/cqrs/etc/cqrs.urm.puml deleted file mode 100644 index 6dd65dd3a330..000000000000 --- a/cqrs/etc/cqrs.urm.puml +++ /dev/null @@ -1,124 +0,0 @@ -@startuml -package com.iluwatar.cqrs.util { - class HibernateUtil { - - LOGGER : Logger {static} - - SESSIONFACTORY : SessionFactory {static} - + HibernateUtil() - - buildSessionFactory() : SessionFactory {static} - + getSessionFactory() : SessionFactory {static} - } -} -package com.iluwatar.cqrs.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.cqrs.dto { - class Author { - - email : String - - name : String - - username : String - + Author() - + Author(name : String, email : String, username : String) - + equals(obj : Object) : boolean - + getEmail() : String - + getName() : String - + getUsername() : String - + hashCode() : int - + toString() : String - } - class Book { - - price : double - - title : String - + Book() - + Book(title : String, price : double) - + equals(obj : Object) : boolean - + getPrice() : double - + getTitle() : String - + hashCode() : int - + toString() : String - } -} -package com.iluwatar.cqrs.commandes { - class CommandServiceImpl { - - sessionFactory : SessionFactory - + CommandServiceImpl() - + authorCreated(username : String, name : String, email : String) - + authorEmailUpdated(username : String, email : String) - + authorNameUpdated(username : String, name : String) - + authorUsernameUpdated(oldUsername : String, newUsername : String) - + bookAddedToAuthor(title : String, price : double, username : String) - + bookPriceUpdated(title : String, price : double) - + bookTitleUpdated(oldTitle : String, newTitle : String) - - getAuthorByUsername(username : String) : Author - - getBookByTitle(title : String) : Book - } - interface ICommandService { - + authorCreated(String, String, String) {abstract} - + authorEmailUpdated(String, String) {abstract} - + authorNameUpdated(String, String) {abstract} - + authorUsernameUpdated(String, String) {abstract} - + bookAddedToAuthor(String, double, String) {abstract} - + bookPriceUpdated(String, double) {abstract} - + bookTitleUpdated(String, String) {abstract} - } -} -package com.iluwatar.cqrs.queries { - interface IQueryService { - + getAuthorBooks(String) : List {abstract} - + getAuthorBooksCount(String) : BigInteger {abstract} - + getAuthorByUsername(String) : Author {abstract} - + getAuthorsCount() : BigInteger {abstract} - + getBook(String) : Book {abstract} - } - class QueryServiceImpl { - - sessionFactory : SessionFactory - + QueryServiceImpl() - + getAuthorBooks(username : String) : List - + getAuthorBooksCount(username : String) : BigInteger - + getAuthorByUsername(username : String) : Author - + getAuthorsCount() : BigInteger - + getBook(title : String) : Book - } -} -package com.iluwatar.cqrs.domain.model { - class Author { - - email : String - - id : long - - name : String - - username : String - # Author() - + Author(username : String, name : String, email : String) - + getEmail() : String - + getId() : long - + getName() : String - + getUsername() : String - + setEmail(email : String) - + setId(id : long) - + setName(name : String) - + setUsername(username : String) - + toString() : String - } - class Book { - - author : Author - - id : long - - price : double - - title : String - # Book() - + Book(title : String, price : double, author : Author) - + getAuthor() : Author - + getId() : long - + getPrice() : double - + getTitle() : String - + setAuthor(author : Author) - + setId(id : long) - + setPrice(price : double) - + setTitle(title : String) - + toString() : String - } -} -Book --> "-author" Author -CommandServiceImpl ..|> ICommandService -QueryServiceImpl ..|> IQueryService -@enduml \ No newline at end of file diff --git a/cqrs/pom.xml b/cqrs/pom.xml deleted file mode 100644 index 2e5644bb6879..000000000000 --- a/cqrs/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - cqrs - - - junit - junit - test - - - com.h2database - h2 - - - org.hibernate - hibernate-core - - - diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/app/App.java b/cqrs/src/main/java/com/iluwatar/cqrs/app/App.java deleted file mode 100644 index a943a7f88891..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/app/App.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.cqrs.app; - -import java.math.BigInteger; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.iluwatar.cqrs.commandes.CommandServiceImpl; -import com.iluwatar.cqrs.commandes.ICommandService; -import com.iluwatar.cqrs.dto.Author; -import com.iluwatar.cqrs.dto.Book; -import com.iluwatar.cqrs.queries.IQueryService; -import com.iluwatar.cqrs.queries.QueryServiceImpl; -import com.iluwatar.cqrs.util.HibernateUtil; - -/** - * CQRS : Command Query Responsibility Segregation. A pattern used to separate query services from commands or writes - * services. The pattern is very simple but it has many consequences. For example, it can be used to tackle down a - * complex domain, or to use other architectures that were hard to implement with the classical way. - * - * This implementation is an example of managing books and authors in a library. The persistence of books and authors is - * done according to the CQRS architecture. A command side that deals with a data model to persist(insert,update,delete) - * objects to a database. And a query side that uses native queries to get data from the database and return objects as - * DTOs (Data transfer Objects). - * - */ -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) { - ICommandService commands = new CommandServiceImpl(); - - // Create Authors and Books using CommandService - commands.authorCreated("eEvans", "Eric Evans", "eEvans@email.com"); - commands.authorCreated("jBloch", "Joshua Bloch", "jBloch@email.com"); - commands.authorCreated("mFowler", "Martin Fowler", "mFowler@email.com"); - - commands.bookAddedToAuthor("Domain-Driven Design", 60.08, "eEvans"); - commands.bookAddedToAuthor("Effective Java", 40.54, "jBloch"); - commands.bookAddedToAuthor("Java Puzzlers", 39.99, "jBloch"); - commands.bookAddedToAuthor("Java Concurrency in Practice", 29.40, "jBloch"); - commands.bookAddedToAuthor("Patterns of Enterprise Application Architecture", 54.01, "mFowler"); - commands.bookAddedToAuthor("Domain Specific Languages", 48.89, "mFowler"); - commands.authorNameUpdated("eEvans", "Eric J. Evans"); - - IQueryService queries = new QueryServiceImpl(); - - // Query the database using QueryService - Author nullAuthor = queries.getAuthorByUsername("username"); - Author eEvans = queries.getAuthorByUsername("eEvans"); - BigInteger jBlochBooksCount = queries.getAuthorBooksCount("jBloch"); - BigInteger authorsCount = queries.getAuthorsCount(); - Book dddBook = queries.getBook("Domain-Driven Design"); - List jBlochBooks = queries.getAuthorBooks("jBloch"); - - LOGGER.info("Author username : {}", nullAuthor); - LOGGER.info("Author eEvans : {}", eEvans); - LOGGER.info("jBloch number of books : {}", jBlochBooksCount); - LOGGER.info("Number of authors : {}", authorsCount); - LOGGER.info("DDD book : {}", dddBook); - LOGGER.info("jBloch books : {}", jBlochBooks); - - HibernateUtil.getSessionFactory().close(); - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java b/cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java deleted file mode 100644 index a15f8a45716d..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java +++ /dev/null @@ -1,145 +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.cqrs.commandes; - -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -import com.iluwatar.cqrs.domain.model.Author; -import com.iluwatar.cqrs.domain.model.Book; -import com.iluwatar.cqrs.util.HibernateUtil; - -/** - * This class is an implementation of {@link ICommandService} interface. It uses Hibernate as an api for persistence. - * - */ -public class CommandServiceImpl implements ICommandService { - - private SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); - - private Author getAuthorByUsername(String username) { - Author author = null; - try (Session session = sessionFactory.openSession()) { - Query query = session.createQuery("from Author where username=:username"); - query.setParameter("username", username); - author = (Author) query.uniqueResult(); - } - if (author == null) { - HibernateUtil.getSessionFactory().close(); - throw new NullPointerException("Author " + username + " doesn't exist!"); - } - return author; - } - - private Book getBookByTitle(String title) { - Book book = null; - try (Session session = sessionFactory.openSession()) { - Query query = session.createQuery("from Book where title=:title"); - query.setParameter("title", title); - book = (Book) query.uniqueResult(); - } - if (book == null) { - HibernateUtil.getSessionFactory().close(); - throw new NullPointerException("Book " + title + " doesn't exist!"); - } - return book; - } - - @Override - public void authorCreated(String username, String name, String email) { - Author author = new Author(username, name, email); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.save(author); - session.getTransaction().commit(); - } - } - - @Override - public void bookAddedToAuthor(String title, double price, String username) { - Author author = getAuthorByUsername(username); - Book book = new Book(title, price, author); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.save(book); - session.getTransaction().commit(); - } - } - - @Override - public void authorNameUpdated(String username, String name) { - Author author = getAuthorByUsername(username); - author.setName(name); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.update(author); - session.getTransaction().commit(); - } - } - - @Override - public void authorUsernameUpdated(String oldUsername, String newUsername) { - Author author = getAuthorByUsername(oldUsername); - author.setUsername(newUsername); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.update(author); - session.getTransaction().commit(); - } - } - - @Override - public void authorEmailUpdated(String username, String email) { - Author author = getAuthorByUsername(username); - author.setEmail(email); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.update(author); - session.getTransaction().commit(); - } - } - - @Override - public void bookTitleUpdated(String oldTitle, String newTitle) { - Book book = getBookByTitle(oldTitle); - book.setTitle(newTitle); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.update(book); - session.getTransaction().commit(); - } - } - - @Override - public void bookPriceUpdated(String title, double price) { - Book book = getBookByTitle(title); - book.setPrice(price); - try (Session session = sessionFactory.openSession()) { - session.beginTransaction(); - session.update(book); - session.getTransaction().commit(); - } - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java b/cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java deleted file mode 100644 index 1da3f6c42392..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java +++ /dev/null @@ -1,45 +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.cqrs.commandes; - -/** - * This interface represents the commands of the CQRS pattern - * - */ -public interface ICommandService { - - void authorCreated(String username, String name, String email); - - void bookAddedToAuthor(String title, double price, String username); - - void authorNameUpdated(String username, String name); - - void authorUsernameUpdated(String oldUsername, String newUsername); - - void authorEmailUpdated(String username, String email); - - void bookTitleUpdated(String oldTitle, String newTitle); - - void bookPriceUpdated(String title, double price); - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java b/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java deleted file mode 100644 index 1d110cb59c27..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java +++ /dev/null @@ -1,100 +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.cqrs.domain.model; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -/** - * This is an Author entity. It is used by Hibernate for persistence. - * - */ -@Entity -public class Author { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; - private String username; - private String name; - private String email; - - /** - * - * @param username - * username of the author - * @param name - * name of the author - * @param email - * email of the author - */ - public Author(String username, String name, String email) { - super(); - this.username = username; - this.name = name; - this.email = email; - } - - protected Author() { - super(); - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - @Override - public String toString() { - return "Author [name=" + name + ", email=" + email + "]"; - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java b/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java deleted file mode 100644 index 8d9ba0ca3020..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java +++ /dev/null @@ -1,102 +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.cqrs.domain.model; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.ManyToOne; - -/** - * This is a Book entity. It is used by Hibernate for persistence. Many books can be written by one {@link Author} - * - */ -@Entity -public class Book { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; - private String title; - private double price; - @ManyToOne - private Author author; - - /** - * - * @param title - * title of the book - * @param price - * price of the book - * @param author - * author of the book - */ - public Book(String title, double price, Author author) { - super(); - this.title = title; - this.price = price; - this.author = author; - } - - protected Book() { - super(); - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public double getPrice() { - return price; - } - - public void setPrice(double price) { - this.price = price; - } - - public Author getAuthor() { - return author; - } - - public void setAuthor(Author author) { - this.author = author; - } - - @Override - public String toString() { - return "Book [title=" + title + ", price=" + price + ", author=" + author + "]"; - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java b/cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java deleted file mode 100644 index 34d082e864e7..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java +++ /dev/null @@ -1,93 +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.cqrs.dto; - -import java.util.Objects; - -/** - * - * This is a DTO (Data Transfer Object) author, contains only useful information to be returned - * - */ -public class Author { - - private String name; - private String email; - private String username; - - /** - * - * @param name - * name of the author - * @param email - * email of the author - * @param username - * username of the author - */ - public Author(String name, String email, String username) { - super(); - this.name = name; - this.email = email; - this.username = username; - } - - public Author() { - super(); - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getUsername() { - return username; - } - - @Override - public String toString() { - return "AuthorDTO [name=" + name + ", email=" + email + ", username=" + username + "]"; - } - - @Override - public int hashCode() { - return Objects.hash(username, name, email); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Author)) { - return false; - } - Author other = (Author) obj; - return username.equals(other.getUsername()) && email.equals(other.getEmail()) && name.equals(other.getName()); - - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java b/cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java deleted file mode 100644 index ff4d258aff1d..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java +++ /dev/null @@ -1,84 +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.cqrs.dto; - -import java.util.Objects; - -/** - * - * This is a DTO (Data Transfer Object) book, contains only useful information to be returned - * - */ -public class Book { - - private String title; - private double price; - - /** - * - * @param title - * title of the book - * @param price - * price of the book - */ - public Book(String title, double price) { - super(); - this.title = title; - this.price = price; - } - - public Book() { - super(); - } - - public String getTitle() { - return title; - } - - public double getPrice() { - return price; - } - - @Override - public String toString() { - return "BookDTO [title=" + title + ", price=" + price + "]"; - } - - @Override - public int hashCode() { - return Objects.hash(title, price); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Book)) { - return false; - } - Book book = (Book) obj; - return title.equals(book.getTitle()) && price == book.getPrice(); - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java b/cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java deleted file mode 100644 index 9c0252b0aeab..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java +++ /dev/null @@ -1,48 +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.cqrs.queries; - -import java.math.BigInteger; -import java.util.List; - -import com.iluwatar.cqrs.dto.Author; -import com.iluwatar.cqrs.dto.Book; - -/** - * - * This interface represents the query methods of the CQRS pattern - * - */ -public interface IQueryService { - - Author getAuthorByUsername(String username); - - Book getBook(String title); - - List getAuthorBooks(String username); - - BigInteger getAuthorBooksCount(String username); - - BigInteger getAuthorsCount(); - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java b/cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java deleted file mode 100644 index dc44d0f1b7c8..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java +++ /dev/null @@ -1,105 +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.cqrs.queries; - -import java.math.BigInteger; -import java.util.List; - -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.transform.Transformers; - -import com.iluwatar.cqrs.dto.Author; -import com.iluwatar.cqrs.dto.Book; -import com.iluwatar.cqrs.util.HibernateUtil; - -/** - * This class is an implementation of {@link IQueryService}. It uses Hibernate native queries to return DTOs from the - * database. - * - */ -public class QueryServiceImpl implements IQueryService { - - private SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); - - @Override - public Author getAuthorByUsername(String username) { - Author authorDTo = null; - try (Session session = sessionFactory.openSession()) { - SQLQuery sqlQuery = session - .createSQLQuery("SELECT a.username as \"username\", a.name as \"name\", a.email as \"email\"" - + "FROM Author a where a.username=:username"); - sqlQuery.setParameter("username", username); - authorDTo = (Author) sqlQuery.setResultTransformer(Transformers.aliasToBean(Author.class)).uniqueResult(); - } - return authorDTo; - } - - @Override - public Book getBook(String title) { - Book bookDTo = null; - try (Session session = sessionFactory.openSession()) { - SQLQuery sqlQuery = session - .createSQLQuery("SELECT b.title as \"title\", b.price as \"price\"" + " FROM Book b where b.title=:title"); - sqlQuery.setParameter("title", title); - bookDTo = (Book) sqlQuery.setResultTransformer(Transformers.aliasToBean(Book.class)).uniqueResult(); - } - return bookDTo; - } - - @Override - public List getAuthorBooks(String username) { - List bookDTos = null; - try (Session session = sessionFactory.openSession()) { - SQLQuery sqlQuery = session.createSQLQuery("SELECT b.title as \"title\", b.price as \"price\"" - + " FROM Author a , Book b where b.author_id = a.id and a.username=:username"); - sqlQuery.setParameter("username", username); - bookDTos = sqlQuery.setResultTransformer(Transformers.aliasToBean(Book.class)).list(); - } - return bookDTos; - } - - @Override - public BigInteger getAuthorBooksCount(String username) { - BigInteger bookcount = null; - try (Session session = sessionFactory.openSession()) { - SQLQuery sqlQuery = session.createSQLQuery( - "SELECT count(b.title)" + " FROM Book b, Author a where b.author_id = a.id and a.username=:username"); - sqlQuery.setParameter("username", username); - bookcount = (BigInteger) sqlQuery.uniqueResult(); - } - return bookcount; - } - - @Override - public BigInteger getAuthorsCount() { - BigInteger authorcount = null; - try (Session session = sessionFactory.openSession()) { - SQLQuery sqlQuery = session.createSQLQuery("SELECT count(id) from Author"); - authorcount = (BigInteger) sqlQuery.uniqueResult(); - } - return authorcount; - } - -} diff --git a/cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java b/cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java deleted file mode 100644 index a5b59e20dc27..000000000000 --- a/cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java +++ /dev/null @@ -1,58 +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.cqrs.util; - -import org.hibernate.SessionFactory; -import org.hibernate.boot.MetadataSources; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class simply returns one instance of {@link SessionFactory} initialized when the application is started - * - */ -public class HibernateUtil { - - private static final SessionFactory SESSIONFACTORY = buildSessionFactory(); - private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); - - private static SessionFactory buildSessionFactory() { - - // configures settings from hibernate.cfg.xml - final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); - try { - return new MetadataSources(registry).buildMetadata().buildSessionFactory(); - } catch (Exception ex) { - StandardServiceRegistryBuilder.destroy(registry); - LOGGER.error("Initial SessionFactory creation failed." + ex); - throw new ExceptionInInitializerError(ex); - } - } - - public static SessionFactory getSessionFactory() { - return SESSIONFACTORY; - } - -} diff --git a/cqrs/src/main/resources/hibernate.cfg.xml b/cqrs/src/main/resources/hibernate.cfg.xml deleted file mode 100644 index 4ea1421667e1..000000000000 --- a/cqrs/src/main/resources/hibernate.cfg.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - org.hibernate.dialect.H2Dialect - org.h2.Driver - jdbc:h2:mem:test - sa - create - - - - \ No newline at end of file diff --git a/cqrs/src/main/resources/logback.xml b/cqrs/src/main/resources/logback.xml deleted file mode 100644 index e9694c41c398..000000000000 --- a/cqrs/src/main/resources/logback.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - diff --git a/cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java b/cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java deleted file mode 100644 index dd10f658d0a2..000000000000 --- a/cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java +++ /dev/null @@ -1,120 +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.cqrs; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.math.BigInteger; -import java.util.List; - -import org.junit.BeforeClass; -import org.junit.Test; - -import com.iluwatar.cqrs.commandes.CommandServiceImpl; -import com.iluwatar.cqrs.commandes.ICommandService; -import com.iluwatar.cqrs.dto.Author; -import com.iluwatar.cqrs.dto.Book; -import com.iluwatar.cqrs.queries.IQueryService; -import com.iluwatar.cqrs.queries.QueryServiceImpl; - -/** - * Integration test of IQueryService and ICommandService with h2 data - * - */ -public class IntegrationTest { - - private static IQueryService queryService; - private static ICommandService commandService; - - @BeforeClass - public static void initialize() { - commandService = new CommandServiceImpl(); - queryService = new QueryServiceImpl(); - } - - @BeforeClass - public static void populateDatabase() { - // create first author1 - commandService.authorCreated("username1", "name1", "email1"); - - // create author1 and update all its data - commandService.authorCreated("username2", "name2", "email2"); - commandService.authorEmailUpdated("username2", "new_email2"); - commandService.authorNameUpdated("username2", "new_name2"); - commandService.authorUsernameUpdated("username2", "new_username2"); - - // add book1 to author1 - commandService.bookAddedToAuthor("title1", 10, "username1"); - - // add book2 to author1 and update all its data - commandService.bookAddedToAuthor("title2", 20, "username1"); - commandService.bookPriceUpdated("title2", 30); - commandService.bookTitleUpdated("title2", "new_title2"); - - } - - @Test - public void testGetAuthorByUsername() { - Author author = queryService.getAuthorByUsername("username1"); - assertEquals("username1", author.getUsername()); - assertEquals("name1", author.getName()); - assertEquals("email1", author.getEmail()); - } - - @Test - public void testGetUpdatedAuthorByUsername() { - Author author = queryService.getAuthorByUsername("new_username2"); - Author expectedAuthor = new Author("new_name2", "new_email2", "new_username2"); - assertEquals(expectedAuthor, author); - - } - - @Test - public void testGetBook() { - Book book = queryService.getBook("title1"); - assertEquals("title1", book.getTitle()); - assertEquals(10, book.getPrice(), 0); - } - - @Test - public void testGetAuthorBooks() { - List books = queryService.getAuthorBooks("username1"); - assertTrue(books.size() == 2); - assertTrue(books.contains(new Book("title1", 10))); - assertTrue(books.contains(new Book("new_title2", 30))); - } - - @Test - public void testGetAuthorBooksCount() { - BigInteger bookCount = queryService.getAuthorBooksCount("username1"); - assertEquals(new BigInteger("2"), bookCount); - } - - @Test - public void testGetAuthorsCount() { - BigInteger authorCount = queryService.getAuthorsCount(); - assertEquals(new BigInteger("2"), authorCount); - } - -} diff --git a/cqrs/src/test/resources/hibernate.cfg.xml b/cqrs/src/test/resources/hibernate.cfg.xml deleted file mode 100644 index 4ea1421667e1..000000000000 --- a/cqrs/src/test/resources/hibernate.cfg.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - org.hibernate.dialect.H2Dialect - org.h2.Driver - jdbc:h2:mem:test - sa - create - - - - \ No newline at end of file diff --git a/cqrs/src/test/resources/logback.xml b/cqrs/src/test/resources/logback.xml deleted file mode 100644 index e9694c41c398..000000000000 --- a/cqrs/src/test/resources/logback.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - diff --git a/dao/README.md b/dao/README.md deleted file mode 100644 index b1b655edf96f..000000000000 --- a/dao/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: pattern -title: Data Access Object -folder: dao -permalink: /patterns/dao/ -pumlid: 5SR14OKW30N0LhG0oVrt4o6ZE12Ov4NR_thQNQlc5aN2sd82qtz4naywAixOmyNoK8WYvT6fjdWOR7JnpLiHhuTkam4nTUhiRwZm847-J64zpUZj3m00 -categories: Persistence Tier -tags: - - Java - - Difficulty-Beginner ---- - -## Intent -Object provides an abstract interface to some type of database or -other persistence mechanism. - -![alt text](./etc/dao.png "Data Access Object") - -## Applicability -Use the Data Access Object in any of the following situations - -* when you want to consolidate how the data layer is accessed -* when you want to avoid writing multiple data retrieval/persistence layers - -## Credits - -* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) diff --git a/dao/etc/dao.png b/dao/etc/dao.png deleted file mode 100644 index 452e72ba10acd5399dcabf1740de9f3806b3fc42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39783 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 diff --git a/dao/etc/dao.ucls b/dao/etc/dao.ucls deleted file mode 100644 index 0706837fc075..000000000000 --- a/dao/etc/dao.ucls +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dao/etc/dao.urm.puml b/dao/etc/dao.urm.puml deleted file mode 100644 index b0a5b2c54c57..000000000000 --- a/dao/etc/dao.urm.puml +++ /dev/null @@ -1,66 +0,0 @@ -@startuml -package com.iluwatar.dao { - class App { - - DB_URL : String {static} - - log : Logger {static} - + App() - - addCustomers(customerDao : CustomerDao) {static} - - createDataSource() : DataSource {static} - - createSchema(dataSource : DataSource) {static} - - deleteSchema(dataSource : DataSource) {static} - + generateSampleCustomers() : List {static} - + main(args : String[]) {static} - - performOperationsUsing(customerDao : CustomerDao) {static} - } - class Customer { - - firstName : String - - id : int - - lastName : String - + Customer(id : int, firstName : String, lastName : String) - + equals(that : Object) : boolean - + getFirstName() : String - + getId() : int - + getLastName() : String - + hashCode() : int - + setFirstName(firstName : String) - + setId(id : int) - + setLastName(lastName : String) - + toString() : String - } - interface CustomerDao { - + add(Customer) : boolean {abstract} - + delete(Customer) : boolean {abstract} - + getAll() : Stream {abstract} - + getById(int) : Optional {abstract} - + update(Customer) : boolean {abstract} - } - class CustomerSchemaSql { - + CREATE_SCHEMA_SQL : String {static} - + DELETE_SCHEMA_SQL : String {static} - - CustomerSchemaSql() - } - class DbCustomerDao { - - dataSource : DataSource - + DbCustomerDao(dataSource : DataSource) - + add(customer : Customer) : boolean - - createCustomer(resultSet : ResultSet) : Customer - + delete(customer : Customer) : boolean - + getAll() : Stream - + getById(id : int) : Optional - - getConnection() : Connection - - mutedClose(connection : Connection) - + update(customer : Customer) : boolean - } - class InMemoryCustomerDao { - - idToCustomer : Map - + InMemoryCustomerDao() - + add(customer : Customer) : boolean - + delete(customer : Customer) : boolean - + getAll() : Stream - + getById(id : int) : Optional - + update(customer : Customer) : boolean - } -} -DbCustomerDao ..|> CustomerDao -InMemoryCustomerDao ..|> CustomerDao -@enduml \ No newline at end of file diff --git a/dao/pom.xml b/dao/pom.xml deleted file mode 100644 index 4c4c8500da9e..000000000000 --- a/dao/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.18.0-SNAPSHOT - - dao - - - - junit - junit - test - - - log4j - log4j - - - com.h2database - h2 - - - de.bechte.junit - junit-hierarchicalcontextrunner - - - org.mockito - mockito-core - - - - - - - - - - src/main/resources - - - src/main/resources - - log4j.xml - - .. - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - log4j.xml - - - - true - - - - - - - - diff --git a/dao/src/main/java/com/iluwatar/dao/App.java b/dao/src/main/java/com/iluwatar/dao/App.java deleted file mode 100644 index d2fa945b617d..000000000000 --- a/dao/src/main/java/com/iluwatar/dao/App.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014-2016 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.iluwatar.dao; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import javax.sql.DataSource; - -import org.apache.log4j.Logger; -import org.h2.jdbcx.JdbcDataSource; - -/** - * Data Access Object (DAO) is an object that provides an abstract interface to some type of - * database or other persistence mechanism. By mapping application calls to the persistence layer, - * DAO provide some specific data operations without exposing details of the database. This - * isolation supports the Single responsibility principle. It separates what data accesses the - * application needs, in terms of domain-specific objects and data types (the public interface of - * the DAO), from how these needs can be satisfied with a specific DBMS. - * - *