mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-08-05 08:23:06 +00:00
docs: Content SEO updates (#2990)
* update yaml frontmatter format * update abstract document * update abstract factory * use the new pattern template * acyclic visitor seo * adapter seo * ambassador seo * acl seo * aaa seo * async method invocation seo * balking seo * bridge seo * builder seo * business delegate and bytecode seo * caching seo * callback seo * chain seo * update headings * circuit breaker seo * client session + collecting parameter seo * collection pipeline seo * combinator SEO * command seo * cqrs seo * commander seo * component seo * composite seo * composite entity seo * composite view seo * context object seo * converter seo * crtp seo * currying seo * dao seo * data bus seo * data locality seo * data mapper seo * dto seo * decorator seo * delegation seo * di seo * dirty flag seo * domain model seo * double buffer seo * double checked locking seo * double dispatch seo * dynamic proxy seo * event aggregator seo * event-based asynchronous seo * eda seo * event queue seo * event sourcing seo * execute around seo * extension objects seo * facade seo * factory seo * factory kit seo * factory method seo * fanout/fanin seo * feature toggle seo * filterer seo * fluent interface seo * flux seo * flyweight seo * front controller seo * function composition seo * game loop seo * gateway seo * guarded suspension seo * half-sync/half-async seo * health check seo * hexagonal seo * identity map seo * intercepting filter seo * interpreter seo * iterator seo * layers seo * lazy loading seo * leader election seo * leader/followers seo * lockable object seo * rename and add seo for marker interface * master-worker seo * mediator seo * memento seo * metadata mapping seo * microservice aggregator seo * api gw seo * microservices log aggregration seo * mvc seo * mvi seo * mvp seo * mvvm seo * monad seo * monitor seo * monostate seo * multiton seo * mute idiom seo * naked objects & notification seo * null object seo * object mother seo * object pool seo * observer seo * optimistic locking seo * page controller seo * page object seo * parameter object seo * partial response seo * pipeline seo * poison pill seo * presentation model seo * private class data seo * producer-consumer seo * promise seo * property seo * prototype seo * proxy seo * queue-based load leveling seo * reactor seo * registry seo * repository seo * RAII seo * retry seo * role object seo * saga seo * separated interface seo * serialized entity seo * serialized lob seo * servant seo * server session seo * service layer seo * service locator seo * service to worker seo * sharding seo * single table inheritance seo * singleton seo * spatial partition seo * special case seo * specification seo * state seo * step builder seo * strangler seo * strategy seo * subclass sandbox seo * table module seo * template method seo * throttling seo * tolerant reader seo * trampoline seo * transaction script seo * twin seo * type object seo * unit of work seo * update method seo * value object seo * version number seo * virtual proxy seo * visitor seo * seo enhancements * seo improvements * SEO enhancements * SEO improvements * SEO additions * SEO improvements * more SEO improvements * rename hexagonal + SEO improvements * SEO improvements * more SEO stuff * SEO improvements * SEO optimizations * SEO enhancements * enchance SEO * improve SEO * SEO improvements * update headers
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
---
|
||||
title: "Hexagonal Architecture Pattern in Java: Decoupling Core Logic for Enhanced Flexibility"
|
||||
shortTitle: Hexagonal Architecture
|
||||
description: "Explore the Hexagonal Architecture pattern in Java. Learn how it decouples core logic from external interfaces, enhances maintainability, and improves testability with practical examples."
|
||||
category: Architectural
|
||||
language: en
|
||||
tag:
|
||||
- Decoupling
|
||||
- Layered architecture
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
* Ports and Adapters
|
||||
|
||||
## Intent of Hexagonal Architecture Design Pattern
|
||||
|
||||
Hexagonal Architecture, also known as Ports and Adapters, is a design pattern in Java that promotes decoupling of core business logic from external interfaces like databases and user interfaces. This architectural approach enhances maintainability and testability of software systems.
|
||||
|
||||
## Detailed Explanation of Hexagonal Architecture Pattern with Real-World Examples
|
||||
|
||||
Real-world example
|
||||
|
||||
> In online banking systems, Hexagonal Architecture allows core banking logic to remain unaffected by changes in user interfaces or third-party services. This decoupling ensures the system's maintainability and flexibility. In such systems, the core banking logic (like processing transactions, managing accounts, and calculating interest) represents the application's core. This core is then surrounded by various adapters that allow the system to interact with different external interfaces without affecting the business logic. For instance, customers might access their accounts through a web interface, a mobile app, or even through ATM services. Meanwhile, the banking system also needs to interface with external services for credit checks, fraud detection, and interbank transactions. Each of these interfaces interacts with the core banking logic through specific adapters designed to translate the external calls to and from the application's internal APIs. This setup allows the bank to modify or extend its external interfaces without having to alter the core business logic, enhancing flexibility and maintainability.
|
||||
|
||||
In plain words
|
||||
|
||||
> Hexagonal Architecture organizes an application into a central core of business logic surrounded by ports and adapters that manage interactions with external systems like user interfaces and databases, allowing the core to remain independent of external concerns.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> The hexagonal architecture, or ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation.
|
||||
|
||||
## Programmatic Example of Hexagonal Architecture Pattern in Java
|
||||
|
||||
The Hexagonal Architecture, also known as Ports and Adapters, is a design pattern that aims to create a loosely coupled application where the core business logic is isolated from external interfaces like databases, user interfaces, or third-party services. This allows the core application to be independent and easily testable.
|
||||
|
||||
The Java code example below illustrates how Hexagonal Architecture isolates core business logic using dependency injection, making the application highly testable and independent from external components.
|
||||
|
||||
In the provided code, we can see an example of the Hexagonal Architecture pattern in the `App` class and the use of Google's Guice for dependency injection.
|
||||
|
||||
The `App` class is the entry point of the application. It creates an instance of `LotteryAdministration` and `LotteryService` through dependency injection and uses them to handle various tasks.
|
||||
|
||||
```java
|
||||
public class App {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
var injector = Guice.createInjector(new LotteryTestingModule());
|
||||
|
||||
// start new lottery round
|
||||
var administration = injector.getInstance(LotteryAdministration.class);
|
||||
administration.resetLottery();
|
||||
|
||||
// submit some lottery tickets
|
||||
var service = injector.getInstance(LotteryService.class);
|
||||
SampleData.submitTickets(service, 20);
|
||||
|
||||
// perform lottery
|
||||
administration.performLottery();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `LotteryAdministration` class is responsible for managing the lottery rounds. It has methods to start a new round, perform the lottery, and reset the lottery.
|
||||
|
||||
```java
|
||||
public class LotteryAdministration {
|
||||
|
||||
private final LotteryTicketRepository repository;
|
||||
private final LotteryEventLog notifications;
|
||||
private final WireTransfers wireTransfers;
|
||||
|
||||
@Inject
|
||||
public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications,
|
||||
WireTransfers wireTransfers) {
|
||||
this.repository = repository;
|
||||
this.notifications = notifications;
|
||||
this.wireTransfers = wireTransfers;
|
||||
}
|
||||
|
||||
public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
public LotteryNumbers performLottery() {
|
||||
// Implementation details...
|
||||
}
|
||||
|
||||
public void resetLottery() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `LotteryService` class is responsible for managing the lottery tickets. It has methods to submit a ticket, check a ticket's status, and get the winning ticket.
|
||||
|
||||
```java
|
||||
public class LotteryService {
|
||||
|
||||
private final LotteryTicketRepository repository;
|
||||
private final LotteryEventLog notifications;
|
||||
private final WireTransfers wireTransfers;
|
||||
|
||||
@Inject
|
||||
public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications,
|
||||
WireTransfers wireTransfers) {
|
||||
this.repository = repository;
|
||||
this.notifications = notifications;
|
||||
this.wireTransfers = wireTransfers;
|
||||
}
|
||||
|
||||
public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {
|
||||
// Implementation details...
|
||||
}
|
||||
|
||||
public LotteryTicketCheckResult checkTicketForPrize(
|
||||
LotteryTicketId id,
|
||||
LotteryNumbers winningNumbers
|
||||
) {
|
||||
// Implementation details...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Running the main function of App class produces the following output:
|
||||
|
||||
```
|
||||
11:06:58.357 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.
|
||||
11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for arnold@google.com was submitted. Bank account 114-988 was charged for 3 credits.
|
||||
11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ollie@google.com was submitted. Bank account 190-045 was charged for 3 credits.
|
||||
11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for peter@google.com was submitted. Bank account 335-886 was charged for 3 credits.
|
||||
11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ray@google.com was submitted. Bank account 843-073 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lisa@google.com was submitted. Bank account 024-653 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for harriet@google.com was submitted. Bank account 842-404 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com was submitted. Bank account 734-853 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lars@google.com was submitted. Bank account 746-936 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for tyron@google.com was submitted. Bank account 310-992 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for xavier@google.com was submitted. Bank account 143-947 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for kevin@google.com was submitted. Bank account 453-936 was charged for 3 credits.
|
||||
11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for yngwie@google.com was submitted. Bank account 241-465 was charged for 3 credits.
|
||||
11:06:58.361 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.
|
||||
11:06:58.361 [main] ERROR com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com could not be submitted because the credit transfer of 3 credits failed.
|
||||
11:06:58.362 [main] ERROR com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com could not be submitted because the credit transfer of 3 credits failed.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for mary@google.com was submitted. Bank account 234-987 was charged for 3 credits.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for edwin@google.com was submitted. Bank account 895-345 was charged for 3 credits.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for jacob@google.com was submitted. Bank account 444-766 was charged for 3 credits.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ollie@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for jacob@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for peter@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ray@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lisa@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for harriet@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lars@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for tyron@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for xavier@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for kevin@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for yngwie@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for mary@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for arnold@google.com was checked and unfortunately did not win this time.
|
||||
11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for edwin@google.com was checked and unfortunately did not win this time.
|
||||
```
|
||||
|
||||
In this example, the `LotteryAdministration` and `LotteryService` classes are the core of the application. They interact with external interfaces like `LotteryTicketRepository`, `LotteryEventLog`, and `WireTransfers` through dependency injection, keeping the core business logic decoupled from external concerns. This is a basic example of the Hexagonal Architecture pattern, where the core application is at the center of input/output systems.
|
||||
|
||||
## Detailed Explanation of Hexagonal Architecture Pattern with Real-World Examples
|
||||
|
||||

|
||||
|
||||
## When to Use the Hexagonal Architecture Pattern in Java
|
||||
|
||||
Hexagonal Architecture is particularly beneficial in scenarios:
|
||||
|
||||
* The application needs to interact with multiple external systems.
|
||||
* There is a requirement for high testability and maintainability.
|
||||
* The application should remain unaffected by changes in external interfaces.
|
||||
|
||||
## Real-World Applications of Hexagonal Architecure Pattern in Java
|
||||
|
||||
* Implemented extensively within enterprise applications that leverage frameworks like Spring.
|
||||
* Used in microservices architectures to maintain clear boundaries and protocols between services.
|
||||
* Adopted in systems that require integration with various databases or external APIs without impacting the business logic.
|
||||
|
||||
## Benefits and Trade-offs of Hexagonal Architecture Pattern
|
||||
|
||||
Benefits:
|
||||
|
||||
* Improved Testability: Allows the core functionality to be tested independently of external components.
|
||||
* Flexibility: Facilitates the addition or replacement of components that interact with the application without modifying the core business logic.
|
||||
* Maintainability: Reduces dependencies on external interfaces, simplifying upgrades and maintenance.
|
||||
|
||||
Trade-offs:
|
||||
|
||||
* Complexity: Introduces more abstractions and layers, which can complicate the system design and understanding.
|
||||
* Overhead: Might be an over-engineering for simple applications, where simpler architectural patterns could suffice.
|
||||
|
||||
## Related Java Design Patterns
|
||||
|
||||
* [Layered Architecture](https://java-design-patterns.com/patterns/layers/): Shares the concept of organizing code into responsibilities; however, Hexagonal emphasizes port-based interaction with external elements.
|
||||
* Microservices: Often used in conjunction with Hexagonal Architecture to define clear boundaries and protocols between services.
|
||||
|
||||
## References and Credits
|
||||
|
||||
* [Implementing Domain-Driven Design](https://amzn.to/4dmBjrB)
|
||||
* [Building Microservices](https://amzn.to/3UACtrU)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 145 KiB |
@@ -0,0 +1,280 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.10" icons="true" automaticImage="PNG" always-add-relationships="false"
|
||||
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"
|
||||
router="FAN">
|
||||
<class id="1" language="java" name="com.iluwatar.hexagonal.eventlog.StdOutEventLog" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/StdOutNotifications.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="167" width="235" x="731" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.hexagonal.banking.InMemoryBank" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="149" width="217" x="1006" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.hexagonal.domain.LotterySystem" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotterySystemImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="167" width="421" x="1263" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicket" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="167" width="278" x="1568" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="5" language="java" name="com.iluwatar.hexagonal.database.InMemoryTicketRepository" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="149" width="265" x="1724" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="6" language="java" name="com.iluwatar.hexagonal.banking.WireTransfers" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="113" width="217" x="1006" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="7" language="java" name="com.iluwatar.hexagonal.domain.LotteryService" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleService.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="113" width="421" x="2029" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="8" language="java" name="com.iluwatar.hexagonal.database.LotteryTicketRepository" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="131" width="265" x="1263" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<interface id="9" language="java" name="com.iluwatar.hexagonal.domain.LotterySystem" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotterySystem.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="149" width="421" x="1886" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="10" language="java" name="com.iluwatar.hexagonal.domain.LotteryNumbers" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="275" width="209" x="1568" y="554"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="11" language="java" name="com.iluwatar.hexagonal.domain.LotteryAdministration"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministration.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="113" width="320" x="2808" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="12" language="java" name="com.iluwatar.hexagonal.domain.LotteryNumbers.RandomNumberGenerator"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="113" width="189" x="1568" y="869"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="13" language="java" name="com.iluwatar.hexagonal.domain.LotteryAdministration" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="131" width="320" x="2490" y="122"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="14" language="java" name="com.iluwatar.hexagonal.domain.PlayerDetails" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="239" width="222" x="1019" y="554"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="15" language="java" name="com.iluwatar.hexagonal.domain.LotteryService" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryService.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="95" width="421" x="2347" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="16" language="java" name="com.iluwatar.hexagonal.App" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="131" width="221" x="470" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="17" language="java" name="com.iluwatar.hexagonal.eventlog.LotteryEventLog"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotifications.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="149" width="235" x="731" y="347"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<association id="18">
|
||||
<end type="SOURCE" refId="16" navigable="false">
|
||||
<attribute id="19" name="PLAYERS"/>
|
||||
<multiplicity id="20" minimum="0" maximum="2147483647"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="14" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="21">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="22" name="wireTransfers"/>
|
||||
<multiplicity id="23" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="6" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="24">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</realization>
|
||||
<nesting id="25">
|
||||
<end type="SOURCE" refId="10"/>
|
||||
<end type="TARGET" refId="12"/>
|
||||
</nesting>
|
||||
<association id="26">
|
||||
<end type="SOURCE" refId="5" navigable="false">
|
||||
<attribute id="27" name="tickets"/>
|
||||
<multiplicity id="28" minimum="0" maximum="2147483647"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="29">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="17"/>
|
||||
</realization>
|
||||
<realization id="30">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</realization>
|
||||
<realization id="31">
|
||||
<end type="SOURCE" refId="7"/>
|
||||
<end type="TARGET" refId="15"/>
|
||||
</realization>
|
||||
<association id="32">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="33" name="lotteryNumbers"/>
|
||||
<multiplicity id="34" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="10" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="35">
|
||||
<end type="SOURCE" refId="13"/>
|
||||
<end type="TARGET" refId="11"/>
|
||||
</realization>
|
||||
<association id="36">
|
||||
<end type="SOURCE" refId="13" navigable="false">
|
||||
<attribute id="37" name="lotterySystem"/>
|
||||
<multiplicity id="38" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="9" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="39">
|
||||
<end type="SOURCE" refId="7" navigable="false">
|
||||
<attribute id="40" name="lotterySystem"/>
|
||||
<multiplicity id="41" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="9" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="42">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="43" name="repository"/>
|
||||
<multiplicity id="44" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="8" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="45">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="6"/>
|
||||
</realization>
|
||||
<association id="46">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="47" name="notifications"/>
|
||||
<multiplicity id="48" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="17" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="49">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="50" name="playerDetails"/>
|
||||
<multiplicity id="51" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="14" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
||||
@@ -0,0 +1,305 @@
|
||||
@startuml
|
||||
package com.iluwatar.hexagonal.sampledata {
|
||||
class SampleData {
|
||||
- PLAYERS : List<PlayerDetails> {static}
|
||||
- RANDOM : Random {static}
|
||||
+ SampleData()
|
||||
- getRandomPlayerDetails() : PlayerDetails {static}
|
||||
+ submitTickets(lotteryService : LotteryService, numTickets : int) {static}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.hexagonal.service {
|
||||
class ConsoleLottery {
|
||||
- LOGGER : Logger {static}
|
||||
+ ConsoleLottery()
|
||||
+ main(args : String[]) {static}
|
||||
- printMainMenu() {static}
|
||||
- readString(scanner : Scanner) : String {static}
|
||||
}
|
||||
interface LotteryConsoleService {
|
||||
+ addFundsToLotteryAccount(WireTransfers, Scanner) {abstract}
|
||||
+ checkTicket(LotteryService, Scanner) {abstract}
|
||||
+ queryLotteryAccountFunds(WireTransfers, Scanner) {abstract}
|
||||
+ submitTicket(LotteryService, Scanner) {abstract}
|
||||
}
|
||||
class LotteryConsoleServiceImpl {
|
||||
- logger : Logger
|
||||
+ LotteryConsoleServiceImpl(logger : Logger)
|
||||
+ addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner)
|
||||
+ checkTicket(service : LotteryService, scanner : Scanner)
|
||||
+ queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner)
|
||||
- readString(scanner : Scanner) : String
|
||||
+ submitTicket(service : LotteryService, scanner : Scanner)
|
||||
}
|
||||
}
|
||||
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<LotteryTicketId, LotteryTicket>
|
||||
+ performLottery() : LotteryNumbers
|
||||
+ resetLottery()
|
||||
}
|
||||
class LotteryConstants {
|
||||
+ PLAYER_MAX_BALANCE : int {static}
|
||||
+ PRIZE_AMOUNT : int {static}
|
||||
+ SERVICE_BANK_ACCOUNT : String {static}
|
||||
+ SERVICE_BANK_ACCOUNT_BALANCE : int {static}
|
||||
+ TICKET_PRIZE : int {static}
|
||||
- LotteryConstants()
|
||||
}
|
||||
class LotteryNumbers {
|
||||
+ MAX_NUMBER : int {static}
|
||||
+ MIN_NUMBER : int {static}
|
||||
+ NUM_NUMBERS : int {static}
|
||||
- numbers : Set<Integer>
|
||||
- LotteryNumbers()
|
||||
- LotteryNumbers(givenNumbers : Set<Integer>)
|
||||
+ create(givenNumbers : Set<Integer>) : LotteryNumbers {static}
|
||||
+ createRandom() : LotteryNumbers {static}
|
||||
+ equals(obj : Object) : boolean
|
||||
- generateRandomNumbers()
|
||||
+ getNumbers() : Set<Integer>
|
||||
+ 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<LotteryTicketId>
|
||||
}
|
||||
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 : AtomicInteger {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<String, Integer> {static}
|
||||
+ InMemoryBank()
|
||||
+ getFunds(bankAccount : String) : int
|
||||
+ setFunds(bankAccount : String, amount : int)
|
||||
+ transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean
|
||||
}
|
||||
class MongoBank {
|
||||
- DEFAULT_ACCOUNTS_COLLECTION : String {static}
|
||||
- DEFAULT_DB : String {static}
|
||||
- accountsCollection : MongoCollection<Document>
|
||||
- database : MongoDatabase
|
||||
- mongoClient : MongoClient
|
||||
+ MongoBank()
|
||||
+ MongoBank(dbName : String, accountsCollectionName : String)
|
||||
+ connect()
|
||||
+ connect(dbName : String, accountsCollectionName : String)
|
||||
+ getAccountsCollection() : MongoCollection<Document>
|
||||
+ getFunds(bankAccount : String) : int
|
||||
+ getMongoClient() : MongoClient
|
||||
+ getMongoDatabase() : MongoDatabase
|
||||
+ setFunds(bankAccount : String, amount : int)
|
||||
+ transferFunds(amount : int, sourceAccount : String, destinationAccount : 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<LotteryTicketId, LotteryTicket> {static}
|
||||
+ InMemoryTicketRepository()
|
||||
+ deleteAll()
|
||||
+ findAll() : Map<LotteryTicketId, LotteryTicket>
|
||||
+ findById(id : LotteryTicketId) : Optional<LotteryTicket>
|
||||
+ save(ticket : LotteryTicket) : Optional<LotteryTicketId>
|
||||
}
|
||||
interface LotteryTicketRepository {
|
||||
+ deleteAll() {abstract}
|
||||
+ findAll() : Map<LotteryTicketId, LotteryTicket> {abstract}
|
||||
+ findById(LotteryTicketId) : Optional<LotteryTicket> {abstract}
|
||||
+ save(LotteryTicket) : Optional<LotteryTicketId> {abstract}
|
||||
}
|
||||
class MongoTicketRepository {
|
||||
- DEFAULT_COUNTERS_COLLECTION : String {static}
|
||||
- DEFAULT_DB : String {static}
|
||||
- DEFAULT_TICKETS_COLLECTION : String {static}
|
||||
- countersCollection : MongoCollection<Document>
|
||||
- database : MongoDatabase
|
||||
- mongoClient : MongoClient
|
||||
- ticketsCollection : MongoCollection<Document>
|
||||
+ MongoTicketRepository()
|
||||
+ MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String)
|
||||
+ connect()
|
||||
+ connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String)
|
||||
+ deleteAll()
|
||||
- docToTicket(doc : Document) : LotteryTicket
|
||||
+ findAll() : Map<LotteryTicketId, LotteryTicket>
|
||||
+ findById(id : LotteryTicketId) : Optional<LotteryTicket>
|
||||
+ getCountersCollection() : MongoCollection<Document>
|
||||
+ getNextId() : int
|
||||
+ getTicketsCollection() : MongoCollection<Document>
|
||||
- initCounters()
|
||||
+ save(ticket : LotteryTicket) : Optional<LotteryTicketId>
|
||||
}
|
||||
}
|
||||
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}
|
||||
}
|
||||
interface ConsoleAdministrationSrv {
|
||||
+ getAllSubmittedTickets() {abstract}
|
||||
+ performLottery() {abstract}
|
||||
+ resetLottery() {abstract}
|
||||
}
|
||||
class ConsoleAdministrationSrvImpl {
|
||||
- administration : LotteryAdministration
|
||||
- logger : Logger
|
||||
+ ConsoleAdministrationSrvImpl(administration : LotteryAdministration, logger : Logger)
|
||||
+ getAllSubmittedTickets()
|
||||
+ performLottery()
|
||||
+ resetLottery()
|
||||
}
|
||||
}
|
||||
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<Document>
|
||||
- mongoClient : MongoClient
|
||||
- stdOutEventLog : StdOutEventLog
|
||||
+ MongoEventLog()
|
||||
+ MongoEventLog(dbName : String, eventsCollectionName : String)
|
||||
+ connect()
|
||||
+ connect(dbName : String, eventsCollectionName : String)
|
||||
+ getEventsCollection() : MongoCollection<Document>
|
||||
+ 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
|
||||
LotteryTicket --> "-id" LotteryTicketId
|
||||
LotteryAdministration --> "-repository" LotteryTicketRepository
|
||||
LotteryService --> "-notifications" LotteryEventLog
|
||||
LotteryTicket --> "-lotteryNumbers" LotteryNumbers
|
||||
SampleData --> "-PLAYERS" PlayerDetails
|
||||
ConsoleAdministrationSrvImpl --> "-administration" LotteryAdministration
|
||||
RandomNumberGenerator ..+ LotteryNumbers
|
||||
LotteryService --> "-repository" LotteryTicketRepository
|
||||
CheckResult ..+ LotteryTicketCheckResult
|
||||
LotteryTicketCheckResult --> "-checkResult" CheckResult
|
||||
ConsoleAdministrationSrvImpl ..|> ConsoleAdministrationSrv
|
||||
InMemoryBank ..|> WireTransfers
|
||||
MongoBank ..|> WireTransfers
|
||||
InMemoryTicketRepository ..|> LotteryTicketRepository
|
||||
MongoTicketRepository ..|> LotteryTicketRepository
|
||||
MongoEventLog ..|> LotteryEventLog
|
||||
StdOutEventLog ..|> LotteryEventLog
|
||||
LotteryConsoleServiceImpl ..|> LotteryConsoleService
|
||||
@enduml
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2022 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.26.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hexagonal-architecture</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>bson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-legacy</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.hexagonal.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>The primary ports for the application are console interfaces {@link
|
||||
* com.iluwatar.hexagonal.administration.ConsoleAdministration} through which the lottery round is
|
||||
* initiated and run and {@link com.iluwatar.hexagonal.service.ConsoleLottery} that allows players
|
||||
* to submit lottery tickets for the draw.
|
||||
*
|
||||
* <p>The secondary ports that application core uses are{@link
|
||||
* com.iluwatar.hexagonal.banking.WireTransfers} which is a banking service, {@link
|
||||
* com.iluwatar.hexagonal.eventlog.LotteryEventLog} that delivers eventlog as lottery events occur
|
||||
* and {@link com.iluwatar.hexagonal.database.LotteryTicketRepository} that is the storage for the
|
||||
* lottery tickets.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
var injector = Guice.createInjector(new LotteryTestingModule());
|
||||
|
||||
// start new lottery round
|
||||
var administration = injector.getInstance(LotteryAdministration.class);
|
||||
administration.resetLottery();
|
||||
|
||||
// submit some lottery tickets
|
||||
var service = injector.getInstance(LotteryService.class);
|
||||
SampleData.submitTickets(service, 20);
|
||||
|
||||
// perform lottery
|
||||
administration.performLottery();
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.iluwatar.hexagonal.domain.LotteryAdministration;
|
||||
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 java.util.Scanner;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Console interface for lottery administration.
|
||||
*/
|
||||
@Slf4j
|
||||
public class ConsoleAdministration {
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
MongoConnectionPropertiesLoader.load();
|
||||
var injector = Guice.createInjector(new LotteryModule());
|
||||
var administration = injector.getInstance(LotteryAdministration.class);
|
||||
var service = injector.getInstance(LotteryService.class);
|
||||
SampleData.submitTickets(service, 20);
|
||||
var consoleAdministration = new ConsoleAdministrationSrvImpl(administration, LOGGER);
|
||||
try (var scanner = new Scanner(System.in)) {
|
||||
var exit = false;
|
||||
while (!exit) {
|
||||
printMainMenu();
|
||||
var cmd = readString(scanner);
|
||||
if ("1".equals(cmd)) {
|
||||
consoleAdministration.getAllSubmittedTickets();
|
||||
} else if ("2".equals(cmd)) {
|
||||
consoleAdministration.performLottery();
|
||||
} else if ("3".equals(cmd)) {
|
||||
consoleAdministration.resetLottery();
|
||||
} 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) {
|
||||
LOGGER.info("> ");
|
||||
return scanner.next();
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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;
|
||||
|
||||
/**
|
||||
* Console interface for lottery administration.
|
||||
*/
|
||||
public interface ConsoleAdministrationSrv {
|
||||
|
||||
/**
|
||||
* Get all submitted tickets.
|
||||
*/
|
||||
void getAllSubmittedTickets();
|
||||
|
||||
/**
|
||||
* Draw lottery numbers.
|
||||
*/
|
||||
void performLottery();
|
||||
|
||||
/**
|
||||
* Begin new lottery round.
|
||||
*/
|
||||
void resetLottery();
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.iluwatar.hexagonal.domain.LotteryAdministration;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Console implementation for lottery administration.
|
||||
*/
|
||||
public class ConsoleAdministrationSrvImpl implements ConsoleAdministrationSrv {
|
||||
private final LotteryAdministration administration;
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ConsoleAdministrationSrvImpl(LotteryAdministration administration, Logger logger) {
|
||||
this.administration = administration;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAllSubmittedTickets() {
|
||||
administration.getAllSubmittedTickets()
|
||||
.forEach((k, v) -> logger.info("Key: {}, Value: {}", k, v));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performLottery() {
|
||||
var numbers = administration.performLottery();
|
||||
logger.info("The winning numbers: {}", numbers.getNumbersAsString());
|
||||
logger.info("Time to reset the database for next round, eh?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetLottery() {
|
||||
administration.resetLottery();
|
||||
logger.info("The lottery ticket database was cleared.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.domain.LotteryConstants;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Banking implementation.
|
||||
*/
|
||||
public class InMemoryBank implements WireTransfers {
|
||||
|
||||
private static final Map<String, Integer> accounts = new HashMap<>();
|
||||
|
||||
static {
|
||||
accounts
|
||||
.put(LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_BALANCE);
|
||||
}
|
||||
|
||||
@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 sourceAccount, String destinationAccount) {
|
||||
if (accounts.getOrDefault(sourceAccount, 0) >= amount) {
|
||||
accounts.put(sourceAccount, accounts.get(sourceAccount) - amount);
|
||||
accounts.put(destinationAccount, accounts.get(destinationAccount) + amount);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 java.util.ArrayList;
|
||||
import lombok.Getter;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Mongo based banking adapter.
|
||||
*/
|
||||
public class MongoBank implements WireTransfers {
|
||||
|
||||
private static final String DEFAULT_DB = "lotteryDB";
|
||||
private static final String DEFAULT_ACCOUNTS_COLLECTION = "accounts";
|
||||
|
||||
@Getter
|
||||
private MongoClient mongoClient;
|
||||
@Getter
|
||||
private MongoDatabase database;
|
||||
@Getter
|
||||
private MongoCollection<Document> 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFunds(String bankAccount, int amount) {
|
||||
var search = new Document("_id", bankAccount);
|
||||
var update = new Document("_id", bankAccount).append("funds", amount);
|
||||
var updateOptions = new UpdateOptions().upsert(true);
|
||||
accountsCollection.updateOne(search, new Document("$set", update), updateOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFunds(String bankAccount) {
|
||||
return accountsCollection
|
||||
.find(new Document("_id", bankAccount))
|
||||
.limit(1)
|
||||
.into(new ArrayList<>())
|
||||
.stream()
|
||||
.findFirst()
|
||||
.map(x -> x.getInteger("funds"))
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transferFunds(int amount, String sourceAccount, String destinationAccount) {
|
||||
var sourceFunds = getFunds(sourceAccount);
|
||||
if (sourceFunds < amount) {
|
||||
return false;
|
||||
} else {
|
||||
var destFunds = getFunds(destinationAccount);
|
||||
setFunds(sourceAccount, sourceFunds - amount);
|
||||
setFunds(destinationAccount, destFunds + amount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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);
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Mock database for lottery tickets.
|
||||
*/
|
||||
public class InMemoryTicketRepository implements LotteryTicketRepository {
|
||||
|
||||
private static final Map<LotteryTicketId, LotteryTicket> tickets = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicket> findById(LotteryTicketId id) {
|
||||
return Optional.ofNullable(tickets.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicketId> save(LotteryTicket ticket) {
|
||||
var id = new LotteryTicketId();
|
||||
tickets.put(id, ticket);
|
||||
return Optional.of(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LotteryTicketId, LotteryTicket> findAll() {
|
||||
return tickets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
tickets.clear();
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Interface for accessing lottery tickets in database.
|
||||
*/
|
||||
public interface LotteryTicketRepository {
|
||||
|
||||
/**
|
||||
* Find lottery ticket by id.
|
||||
*/
|
||||
Optional<LotteryTicket> findById(LotteryTicketId id);
|
||||
|
||||
/**
|
||||
* Save lottery ticket.
|
||||
*/
|
||||
Optional<LotteryTicketId> save(LotteryTicket ticket);
|
||||
|
||||
/**
|
||||
* Get all lottery tickets.
|
||||
*/
|
||||
Map<LotteryTicketId, LotteryTicket> findAll();
|
||||
|
||||
/**
|
||||
* Delete all lottery tickets.
|
||||
*/
|
||||
void deleteAll();
|
||||
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* 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 static final String TICKET_ID = "ticketId";
|
||||
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase database;
|
||||
@Getter
|
||||
private MongoCollection<Document> ticketsCollection;
|
||||
@Getter
|
||||
private MongoCollection<Document> 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.countDocuments() <= 0) {
|
||||
initCounters();
|
||||
}
|
||||
}
|
||||
|
||||
private void initCounters() {
|
||||
var doc = new Document("_id", TICKET_ID).append("seq", 1);
|
||||
countersCollection.insertOne(doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next ticket id.
|
||||
*
|
||||
* @return next ticket id
|
||||
*/
|
||||
public int getNextId() {
|
||||
var find = new Document("_id", TICKET_ID);
|
||||
var increase = new Document("seq", 1);
|
||||
var update = new Document("$inc", increase);
|
||||
var result = countersCollection.findOneAndUpdate(find, update);
|
||||
return result.getInteger("seq");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicket> findById(LotteryTicketId id) {
|
||||
return ticketsCollection
|
||||
.find(new Document(TICKET_ID, id.getId()))
|
||||
.limit(1)
|
||||
.into(new ArrayList<>())
|
||||
.stream()
|
||||
.findFirst()
|
||||
.map(this::docToTicket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicketId> save(LotteryTicket ticket) {
|
||||
var ticketId = getNextId();
|
||||
var doc = new Document(TICKET_ID, ticketId);
|
||||
doc.put("email", ticket.playerDetails().email());
|
||||
doc.put("bank", ticket.playerDetails().bankAccount());
|
||||
doc.put("phone", ticket.playerDetails().phoneNumber());
|
||||
doc.put("numbers", ticket.lotteryNumbers().getNumbersAsString());
|
||||
ticketsCollection.insertOne(doc);
|
||||
return Optional.of(new LotteryTicketId(ticketId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LotteryTicketId, LotteryTicket> findAll() {
|
||||
return ticketsCollection
|
||||
.find(new Document())
|
||||
.into(new ArrayList<>())
|
||||
.stream()
|
||||
.map(this::docToTicket)
|
||||
.collect(Collectors.toMap(LotteryTicket::id, Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
ticketsCollection.deleteMany(new Document());
|
||||
}
|
||||
|
||||
private LotteryTicket docToTicket(Document doc) {
|
||||
var playerDetails = new PlayerDetails(doc.getString("email"), doc.getString("bank"),
|
||||
doc.getString("phone"));
|
||||
var numbers = Arrays.stream(doc.getString("numbers").split(","))
|
||||
.map(Integer::parseInt)
|
||||
.collect(Collectors.toSet());
|
||||
var lotteryNumbers = LotteryNumbers.create(numbers);
|
||||
var ticketId = new LotteryTicketId(doc.getInteger(TICKET_ID));
|
||||
return new LotteryTicket(ticketId, playerDetails, lotteryNumbers);
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 com.iluwatar.hexagonal.domain.LotteryConstants.PRIZE_AMOUNT;
|
||||
import static com.iluwatar.hexagonal.domain.LotteryConstants.SERVICE_BANK_ACCOUNT;
|
||||
|
||||
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<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw lottery numbers.
|
||||
*/
|
||||
public LotteryNumbers performLottery() {
|
||||
var numbers = LotteryNumbers.createRandom();
|
||||
var tickets = getAllSubmittedTickets();
|
||||
for (var id : tickets.keySet()) {
|
||||
var lotteryTicket = tickets.get(id);
|
||||
var playerDetails = lotteryTicket.playerDetails();
|
||||
var playerAccount = playerDetails.bankAccount();
|
||||
var result = LotteryUtils.checkTicketForPrize(repository, id, numbers).getResult();
|
||||
if (result == LotteryTicketCheckResult.CheckResult.WIN_PRIZE) {
|
||||
if (wireTransfers.transferFunds(PRIZE_AMOUNT, SERVICE_BANK_ACCOUNT, playerAccount)) {
|
||||
notifications.ticketWon(playerDetails, PRIZE_AMOUNT);
|
||||
} else {
|
||||
notifications.prizeError(playerDetails, PRIZE_AMOUNT);
|
||||
}
|
||||
} else if (result == LotteryTicketCheckResult.CheckResult.NO_PRIZE) {
|
||||
notifications.ticketDidNotWin(playerDetails);
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin new lottery round.
|
||||
*/
|
||||
public void resetLottery() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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_BALANCE = 150000;
|
||||
public static final int PLAYER_MAX_BALANCE = 100;
|
||||
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.common.base.Joiner;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Set;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must
|
||||
* be unique and between 1 and 20.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public class LotteryNumbers {
|
||||
|
||||
private final Set<Integer> 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<Integer> givenNumbers) {
|
||||
numbers = new HashSet<>();
|
||||
numbers.addAll(givenNumbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a random lottery number.
|
||||
*
|
||||
* @return random LotteryNumbers
|
||||
*/
|
||||
public static LotteryNumbers createRandom() {
|
||||
return new LotteryNumbers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates lottery number from given set of numbers.
|
||||
*
|
||||
* @return given LotteryNumbers
|
||||
*/
|
||||
public static LotteryNumbers create(Set<Integer> givenNumbers) {
|
||||
return new LotteryNumbers(givenNumbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numbers.
|
||||
*
|
||||
* @return lottery numbers
|
||||
*/
|
||||
public Set<Integer> getNumbers() {
|
||||
return Collections.unmodifiableSet(numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numbers as string.
|
||||
*
|
||||
* @return numbers as comma separated string
|
||||
*/
|
||||
public String getNumbersAsString() {
|
||||
return Joiner.on(',').join(numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 4 unique random numbers between 1-20 into numbers set.
|
||||
*/
|
||||
private void generateRandomNumbers() {
|
||||
numbers.clear();
|
||||
var generator = new RandomNumberGenerator(MIN_NUMBER, MAX_NUMBER);
|
||||
while (numbers.size() < NUM_NUMBERS) {
|
||||
var num = generator.nextInt();
|
||||
numbers.add(num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for generating random numbers.
|
||||
*/
|
||||
private static class RandomNumberGenerator {
|
||||
|
||||
private final 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 SecureRandom().ints(min, max + 1).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets next random integer in [min, max] range.
|
||||
*
|
||||
* @return a random number in the range (min, max)
|
||||
*/
|
||||
public int nextInt() {
|
||||
return randomIterator.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 com.iluwatar.hexagonal.domain.LotteryConstants.SERVICE_BANK_ACCOUNT;
|
||||
import static com.iluwatar.hexagonal.domain.LotteryConstants.TICKET_PRIZE;
|
||||
|
||||
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<LotteryTicketId> submitTicket(LotteryTicket ticket) {
|
||||
var playerDetails = ticket.playerDetails();
|
||||
var playerAccount = playerDetails.bankAccount();
|
||||
var result = wireTransfers.transferFunds(TICKET_PRIZE, playerAccount, SERVICE_BANK_ACCOUNT);
|
||||
if (!result) {
|
||||
notifications.ticketSubmitError(playerDetails);
|
||||
return Optional.empty();
|
||||
}
|
||||
var optional = repository.save(ticket);
|
||||
if (optional.isPresent()) {
|
||||
notifications.ticketSubmitted(playerDetails);
|
||||
}
|
||||
return optional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if lottery ticket has won.
|
||||
*/
|
||||
public LotteryTicketCheckResult checkTicketForPrize(
|
||||
LotteryTicketId id,
|
||||
LotteryNumbers winningNumbers
|
||||
) {
|
||||
return LotteryUtils.checkTicketForPrize(repository, id, winningNumbers);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 record LotteryTicket(LotteryTicketId id, PlayerDetails playerDetails, LotteryNumbers lotteryNumbers) {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final var prime = 31;
|
||||
var 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;
|
||||
}
|
||||
var other = (LotteryTicket) obj;
|
||||
if (lotteryNumbers == null) {
|
||||
if (other.lotteryNumbers != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!lotteryNumbers.equals(other.lotteryNumbers)) {
|
||||
return false;
|
||||
}
|
||||
if (playerDetails == null) {
|
||||
return other.playerDetails == null;
|
||||
} else {
|
||||
return playerDetails.equals(other.playerDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* Represents lottery ticket check result.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
public class LotteryTicketCheckResult {
|
||||
|
||||
/**
|
||||
* Enumeration of Type of Outcomes of a Lottery.
|
||||
*/
|
||||
public enum CheckResult {
|
||||
WIN_PRIZE,
|
||||
NO_PRIZE,
|
||||
TICKET_NOT_SUBMITTED
|
||||
}
|
||||
|
||||
private final CheckResult result;
|
||||
private final int prizeAmount;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public LotteryTicketCheckResult(CheckResult result) {
|
||||
this.result = result;
|
||||
prizeAmount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.concurrent.atomic.AtomicInteger;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* Lottery ticked id.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
public class LotteryTicketId {
|
||||
|
||||
private static final AtomicInteger numAllocated = new AtomicInteger(0);
|
||||
private final int id;
|
||||
|
||||
public LotteryTicketId() {
|
||||
this.id = numAllocated.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d", id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
|
||||
/**
|
||||
* Lottery utilities.
|
||||
*/
|
||||
public class LotteryUtils {
|
||||
|
||||
private LotteryUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if lottery ticket has won.
|
||||
*/
|
||||
public static LotteryTicketCheckResult checkTicketForPrize(
|
||||
LotteryTicketRepository repository,
|
||||
LotteryTicketId id,
|
||||
LotteryNumbers winningNumbers
|
||||
) {
|
||||
var optional = repository.findById(id);
|
||||
if (optional.isPresent()) {
|
||||
if (optional.get().lotteryNumbers().equals(winningNumbers)) {
|
||||
return new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 1000);
|
||||
} else {
|
||||
return new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
}
|
||||
} else {
|
||||
return new LotteryTicketCheckResult(CheckResult.TICKET_NOT_SUBMITTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 record PlayerDetails(String email, String bankAccount, String phoneNumber) {}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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);
|
||||
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 lombok.Getter;
|
||||
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 static final String EMAIL = "email";
|
||||
private static final String PHONE = "phone";
|
||||
public static final String MESSAGE = "message";
|
||||
|
||||
@Getter
|
||||
private MongoClient mongoClient;
|
||||
@Getter
|
||||
private MongoDatabase database;
|
||||
@Getter
|
||||
private MongoCollection<Document> eventsCollection;
|
||||
|
||||
private final 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ticketSubmitted(PlayerDetails details) {
|
||||
var document = new Document(EMAIL, details.email());
|
||||
document.put(PHONE, details.phoneNumber());
|
||||
document.put("bank", details.bankAccount());
|
||||
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) {
|
||||
var document = new Document(EMAIL, details.email());
|
||||
document.put(PHONE, details.phoneNumber());
|
||||
document.put("bank", details.bankAccount());
|
||||
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) {
|
||||
var document = new Document(EMAIL, details.email());
|
||||
document.put(PHONE, details.phoneNumber());
|
||||
document.put("bank", details.bankAccount());
|
||||
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) {
|
||||
var document = new Document(EMAIL, details.email());
|
||||
document.put(PHONE, details.phoneNumber());
|
||||
document.put("bank", details.bankAccount());
|
||||
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) {
|
||||
var document = new Document(EMAIL, details.email());
|
||||
document.put(PHONE, details.phoneNumber());
|
||||
document.put("bank", details.bankAccount());
|
||||
document.put(MESSAGE, String
|
||||
.format("Lottery ticket won! Unfortunately the bank credit transfer of %d failed.",
|
||||
prizeAmount));
|
||||
eventsCollection.insertOne(document);
|
||||
stdOutEventLog.prizeError(details, prizeAmount);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Standard output event log.
|
||||
*/
|
||||
@Slf4j
|
||||
public class StdOutEventLog implements LotteryEventLog {
|
||||
|
||||
@Override
|
||||
public void ticketSubmitted(PlayerDetails details) {
|
||||
LOGGER.info("Lottery ticket for {} was submitted. Bank account {} was charged for 3 credits.",
|
||||
details.email(), details.bankAccount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ticketDidNotWin(PlayerDetails details) {
|
||||
LOGGER.info("Lottery ticket for {} was checked and unfortunately did not win this time.",
|
||||
details.email());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ticketWon(PlayerDetails details, int prizeAmount) {
|
||||
LOGGER.info("Lottery ticket for {} has won! The bank account {} was deposited with {} credits.",
|
||||
details.email(), details.bankAccount(), prizeAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prizeError(PlayerDetails details, int prizeAmount) {
|
||||
LOGGER.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of"
|
||||
+ " {} failed.", details.email(), 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.email());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Mongo connection properties loader.
|
||||
*/
|
||||
@Slf4j
|
||||
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() {
|
||||
var host = DEFAULT_HOST;
|
||||
var port = DEFAULT_PORT;
|
||||
var path = System.getProperty("hexagonal.properties.path");
|
||||
var properties = new Properties();
|
||||
if (path != null) {
|
||||
try (var 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
|
||||
LOGGER.error("Error occurred: ", e);
|
||||
}
|
||||
}
|
||||
System.setProperty("mongo-host", host);
|
||||
System.setProperty("mongo-port", String.format("%d", port));
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.security.SecureRandom;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Utilities for creating sample lottery tickets.
|
||||
*/
|
||||
public class SampleData {
|
||||
|
||||
private static final List<PlayerDetails> PLAYERS;
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
static {
|
||||
PLAYERS = List.of(
|
||||
new PlayerDetails("john@google.com", "312-342", "+3242434242"),
|
||||
new PlayerDetails("mary@google.com", "234-987", "+23452346"),
|
||||
new PlayerDetails("steve@google.com", "833-836", "+63457543"),
|
||||
new PlayerDetails("wayne@google.com", "319-826", "+24626"),
|
||||
new PlayerDetails("johnie@google.com", "983-322", "+3635635"),
|
||||
new PlayerDetails("andy@google.com", "934-734", "+0898245"),
|
||||
new PlayerDetails("richard@google.com", "536-738", "+09845325"),
|
||||
new PlayerDetails("kevin@google.com", "453-936", "+2423532"),
|
||||
new PlayerDetails("arnold@google.com", "114-988", "+5646346524"),
|
||||
new PlayerDetails("ian@google.com", "663-765", "+928394235"),
|
||||
new PlayerDetails("robin@google.com", "334-763", "+35448"),
|
||||
new PlayerDetails("ted@google.com", "735-964", "+98752345"),
|
||||
new PlayerDetails("larry@google.com", "734-853", "+043842423"),
|
||||
new PlayerDetails("calvin@google.com", "334-746", "+73294135"),
|
||||
new PlayerDetails("jacob@google.com", "444-766", "+358042354"),
|
||||
new PlayerDetails("edwin@google.com", "895-345", "+9752435"),
|
||||
new PlayerDetails("mary@google.com", "760-009", "+34203542"),
|
||||
new PlayerDetails("lolita@google.com", "425-907", "+9872342"),
|
||||
new PlayerDetails("bruno@google.com", "023-638", "+673824122"),
|
||||
new PlayerDetails("peter@google.com", "335-886", "+5432503945"),
|
||||
new PlayerDetails("warren@google.com", "225-946", "+9872341324"),
|
||||
new PlayerDetails("monica@google.com", "265-748", "+134124"),
|
||||
new PlayerDetails("ollie@google.com", "190-045", "+34453452"),
|
||||
new PlayerDetails("yngwie@google.com", "241-465", "+9897641231"),
|
||||
new PlayerDetails("lars@google.com", "746-936", "+42345298345"),
|
||||
new PlayerDetails("bobbie@google.com", "946-384", "+79831742"),
|
||||
new PlayerDetails("tyron@google.com", "310-992", "+0498837412"),
|
||||
new PlayerDetails("tyrell@google.com", "032-045", "+67834134"),
|
||||
new PlayerDetails("nadja@google.com", "000-346", "+498723"),
|
||||
new PlayerDetails("wendy@google.com", "994-989", "+987324454"),
|
||||
new PlayerDetails("luke@google.com", "546-634", "+987642435"),
|
||||
new PlayerDetails("bjorn@google.com", "342-874", "+7834325"),
|
||||
new PlayerDetails("lisa@google.com", "024-653", "+980742154"),
|
||||
new PlayerDetails("anton@google.com", "834-935", "+876423145"),
|
||||
new PlayerDetails("bruce@google.com", "284-936", "+09843212345"),
|
||||
new PlayerDetails("ray@google.com", "843-073", "+678324123"),
|
||||
new PlayerDetails("ron@google.com", "637-738", "+09842354"),
|
||||
new PlayerDetails("xavier@google.com", "143-947", "+375245"),
|
||||
new PlayerDetails("harriet@google.com", "842-404", "+131243252")
|
||||
);
|
||||
var wireTransfers = new InMemoryBank();
|
||||
PLAYERS.stream()
|
||||
.map(PlayerDetails::bankAccount)
|
||||
.map(e -> new SimpleEntry<>(e, RANDOM.nextInt(LotteryConstants.PLAYER_MAX_BALANCE)))
|
||||
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue))
|
||||
.forEach(wireTransfers::setFunds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts lottery tickets into the database based on the sample data.
|
||||
*/
|
||||
public static void submitTickets(LotteryService lotteryService, int numTickets) {
|
||||
for (var i = 0; i < numTickets; i++) {
|
||||
var randomPlayerDetails = getRandomPlayerDetails();
|
||||
var lotteryNumbers = LotteryNumbers.createRandom();
|
||||
var lotteryTicketId = new LotteryTicketId();
|
||||
var ticket = new LotteryTicket(lotteryTicketId, randomPlayerDetails, lotteryNumbers);
|
||||
lotteryService.submitTicket(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
private static PlayerDetails getRandomPlayerDetails() {
|
||||
return PLAYERS.get(RANDOM.nextInt(PLAYERS.size()));
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryService;
|
||||
import com.iluwatar.hexagonal.module.LotteryModule;
|
||||
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
||||
import java.util.Scanner;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Console interface for lottery players.
|
||||
*/
|
||||
@Slf4j
|
||||
public class ConsoleLottery {
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
MongoConnectionPropertiesLoader.load();
|
||||
var injector = Guice.createInjector(new LotteryModule());
|
||||
var service = injector.getInstance(LotteryService.class);
|
||||
var bank = injector.getInstance(WireTransfers.class);
|
||||
try (Scanner scanner = new Scanner(System.in)) {
|
||||
var exit = false;
|
||||
while (!exit) {
|
||||
printMainMenu();
|
||||
var cmd = readString(scanner);
|
||||
var lotteryConsoleService = new LotteryConsoleServiceImpl(LOGGER);
|
||||
if ("1".equals(cmd)) {
|
||||
lotteryConsoleService.queryLotteryAccountFunds(bank, scanner);
|
||||
} else if ("2".equals(cmd)) {
|
||||
lotteryConsoleService.addFundsToLotteryAccount(bank, scanner);
|
||||
} else if ("3".equals(cmd)) {
|
||||
lotteryConsoleService.submitTicket(service, scanner);
|
||||
} else if ("4".equals(cmd)) {
|
||||
lotteryConsoleService.checkTicket(service, scanner);
|
||||
} else if ("5".equals(cmd)) {
|
||||
exit = true;
|
||||
} else {
|
||||
LOGGER.info("Unknown command");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
LOGGER.info("> ");
|
||||
return scanner.next();
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryService;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
/**
|
||||
* Console interface for lottery service.
|
||||
*/
|
||||
public interface LotteryConsoleService {
|
||||
|
||||
void checkTicket(LotteryService service, Scanner scanner);
|
||||
|
||||
/**
|
||||
* Submit lottery ticket to participate in the lottery.
|
||||
*/
|
||||
void submitTicket(LotteryService service, Scanner scanner);
|
||||
|
||||
/**
|
||||
* Add funds to lottery account.
|
||||
*/
|
||||
void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner);
|
||||
|
||||
|
||||
/**
|
||||
* Recovery funds from lottery account.
|
||||
*/
|
||||
void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner);
|
||||
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.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 java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Console implementation for lottery console service.
|
||||
*/
|
||||
public class LotteryConsoleServiceImpl implements LotteryConsoleService {
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public LotteryConsoleServiceImpl(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkTicket(LotteryService service, Scanner scanner) {
|
||||
logger.info("What is the ID of the lottery ticket?");
|
||||
var id = readString(scanner);
|
||||
logger.info("Give the 4 comma separated winning numbers?");
|
||||
var numbers = readString(scanner);
|
||||
try {
|
||||
var winningNumbers = Arrays.stream(numbers.split(","))
|
||||
.map(Integer::parseInt)
|
||||
.limit(4)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var lotteryTicketId = new LotteryTicketId(Integer.parseInt(id));
|
||||
final var lotteryNumbers = LotteryNumbers.create(winningNumbers);
|
||||
var result = service.checkTicketForPrize(lotteryTicketId, lotteryNumbers);
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitTicket(LotteryService service, Scanner scanner) {
|
||||
logger.info("What is your email address?");
|
||||
var email = readString(scanner);
|
||||
logger.info("What is your bank account number?");
|
||||
var account = readString(scanner);
|
||||
logger.info("What is your phone number?");
|
||||
var phone = readString(scanner);
|
||||
var details = new PlayerDetails(email, account, phone);
|
||||
logger.info("Give 4 comma separated lottery numbers?");
|
||||
var numbers = readString(scanner);
|
||||
try {
|
||||
var chosen = Arrays.stream(numbers.split(","))
|
||||
.map(Integer::parseInt)
|
||||
.collect(Collectors.toSet());
|
||||
var lotteryNumbers = LotteryNumbers.create(chosen);
|
||||
var lotteryTicket = new LotteryTicket(new LotteryTicketId(), details, lotteryNumbers);
|
||||
service.submitTicket(lotteryTicket).ifPresentOrElse(
|
||||
(id) -> logger.info("Submitted lottery ticket with id: {}", id),
|
||||
() -> logger.info("Failed submitting lottery ticket - please try again.")
|
||||
);
|
||||
} catch (Exception e) {
|
||||
logger.info("Failed submitting lottery ticket - please try again.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner) {
|
||||
logger.info("What is the account number?");
|
||||
var account = readString(scanner);
|
||||
logger.info("How many credits do you want to deposit?");
|
||||
var amount = readString(scanner);
|
||||
bank.setFunds(account, Integer.parseInt(amount));
|
||||
logger.info("The account {} now has {} credits.", account, bank.getFunds(account));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner) {
|
||||
logger.info("What is the account number?");
|
||||
var account = readString(scanner);
|
||||
logger.info("The account {} has {} credits.", account, bank.getFunds(account));
|
||||
}
|
||||
|
||||
private String readString(Scanner scanner) {
|
||||
logger.info("> ");
|
||||
return scanner.next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
class AppTest {
|
||||
|
||||
@Test
|
||||
void shouldExecuteApplicationWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for banking
|
||||
*/
|
||||
class InMemoryBankTest {
|
||||
|
||||
private final WireTransfers bank = new InMemoryBank();
|
||||
|
||||
@Test
|
||||
void testInit() {
|
||||
assertEquals(0, bank.getFunds("foo"));
|
||||
bank.setFunds("foo", 100);
|
||||
assertEquals(100, bank.getFunds("foo"));
|
||||
bank.setFunds("bar", 150);
|
||||
assertEquals(150, bank.getFunds("bar"));
|
||||
assertTrue(bank.transferFunds(50, "bar", "foo"));
|
||||
assertEquals(150, bank.getFunds("foo"));
|
||||
assertEquals(100, bank.getFunds("bar"));
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import de.flapdoodle.embed.mongo.commands.ServerAddress;
|
||||
import de.flapdoodle.embed.mongo.distribution.Version;
|
||||
import de.flapdoodle.embed.mongo.transitions.Mongod;
|
||||
import de.flapdoodle.embed.mongo.transitions.RunningMongodProcess;
|
||||
import de.flapdoodle.reverse.TransitionWalker;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for Mongo banking adapter
|
||||
*/
|
||||
class MongoBankTest {
|
||||
|
||||
private static final String TEST_DB = "lotteryDBTest";
|
||||
private static final String TEST_ACCOUNTS_COLLECTION = "testAccounts";
|
||||
|
||||
private static MongoClient mongoClient;
|
||||
private static MongoDatabase mongoDatabase;
|
||||
|
||||
private MongoBank mongoBank;
|
||||
|
||||
private static TransitionWalker.ReachedState<RunningMongodProcess> mongodProcess;
|
||||
|
||||
private static ServerAddress serverAddress;
|
||||
|
||||
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() {
|
||||
mongodProcess = Mongod.instance().start(Version.Main.V7_0);
|
||||
serverAddress = mongodProcess.current().getServerAddress();
|
||||
mongoClient = MongoClients.create("mongodb://" + serverAddress.toString());
|
||||
mongoClient.startSession();
|
||||
mongoDatabase = mongoClient.getDatabase(TEST_DB);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
mongoClient.close();
|
||||
mongodProcess.close();
|
||||
}
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
System.setProperty("mongo-host", serverAddress.getHost());
|
||||
System.setProperty("mongo-port", String.valueOf(serverAddress.getPort()));
|
||||
mongoDatabase.drop();
|
||||
mongoBank = new MongoBank(mongoDatabase.getName(), TEST_ACCOUNTS_COLLECTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetup() {
|
||||
assertEquals(0, mongoBank.getAccountsCollection().countDocuments());
|
||||
}
|
||||
|
||||
@Test
|
||||
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"));
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.iluwatar.hexagonal.test.LotteryTestUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for {@link LotteryTicketRepository}
|
||||
*/
|
||||
class InMemoryTicketRepositoryTest {
|
||||
|
||||
private final LotteryTicketRepository repository = new InMemoryTicketRepository();
|
||||
|
||||
@BeforeEach
|
||||
void clear() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCrudOperations() {
|
||||
var repository = new InMemoryTicketRepository();
|
||||
assertTrue(repository.findAll().isEmpty());
|
||||
var ticket = LotteryTestUtils.createLotteryTicket();
|
||||
var id = repository.save(ticket);
|
||||
assertTrue(id.isPresent());
|
||||
assertEquals(1, repository.findAll().size());
|
||||
var optionalTicket = repository.findById(id.get());
|
||||
assertTrue(optionalTicket.isPresent());
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
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.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for Mongo based ticket repository
|
||||
*/
|
||||
@Disabled
|
||||
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;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
MongoConnectionPropertiesLoader.load();
|
||||
var 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
|
||||
void testSetup() {
|
||||
assertEquals(1, repository.getCountersCollection().countDocuments());
|
||||
assertEquals(0, repository.getTicketsCollection().countDocuments());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNextId() {
|
||||
assertEquals(1, repository.getNextId());
|
||||
assertEquals(2, repository.getNextId());
|
||||
assertEquals(3, repository.getNextId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCrudOperations() {
|
||||
// create new lottery ticket and save it
|
||||
var details = new PlayerDetails("foo@bar.com", "123-123", "07001234");
|
||||
var random = LotteryNumbers.createRandom();
|
||||
var original = new LotteryTicket(new LotteryTicketId(), details, random);
|
||||
var saved = repository.save(original);
|
||||
assertEquals(1, repository.getTicketsCollection().countDocuments());
|
||||
assertTrue(saved.isPresent());
|
||||
// fetch the saved lottery ticket from database and check its contents
|
||||
var found = repository.findById(saved.get());
|
||||
assertTrue(found.isPresent());
|
||||
var ticket = found.get();
|
||||
assertEquals("foo@bar.com", ticket.playerDetails().email());
|
||||
assertEquals("123-123", ticket.playerDetails().bankAccount());
|
||||
assertEquals("07001234", ticket.playerDetails().phoneNumber());
|
||||
assertEquals(original.lotteryNumbers(), ticket.lotteryNumbers());
|
||||
// clear the collection
|
||||
repository.deleteAll();
|
||||
assertEquals(0, repository.getTicketsCollection().countDocuments());
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LotteryNumbers}
|
||||
*/
|
||||
class LotteryNumbersTest {
|
||||
|
||||
@Test
|
||||
void testGivenNumbers() {
|
||||
var numbers = LotteryNumbers.create(Set.of(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
|
||||
void testNumbersCantBeModified() {
|
||||
var numbers = LotteryNumbers.create(Set.of(1, 2, 3, 4));
|
||||
assertThrows(UnsupportedOperationException.class, () -> numbers.getNumbers().add(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRandomNumbers() {
|
||||
var numbers = LotteryNumbers.createRandom();
|
||||
assertEquals(numbers.getNumbers().size(), LotteryNumbers.NUM_NUMBERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
var numbers1 = LotteryNumbers.create(Set.of(1, 2, 3, 4));
|
||||
var numbers2 = LotteryNumbers.create(Set.of(1, 2, 3, 4));
|
||||
assertEquals(numbers1, numbers2);
|
||||
var numbers3 = LotteryNumbers.create(Set.of(11, 12, 13, 14));
|
||||
assertNotEquals(numbers1, numbers3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
import com.iluwatar.hexagonal.module.LotteryTestingModule;
|
||||
import com.iluwatar.hexagonal.test.LotteryTestUtils;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test the lottery system
|
||||
*/
|
||||
class LotteryTest {
|
||||
|
||||
private final Injector injector;
|
||||
@Inject
|
||||
private LotteryAdministration administration;
|
||||
@Inject
|
||||
private LotteryService service;
|
||||
@Inject
|
||||
private WireTransfers wireTransfers;
|
||||
|
||||
LotteryTest() {
|
||||
this.injector = Guice.createInjector(new LotteryTestingModule());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
injector.injectMembers(this);
|
||||
// add funds to the test player's bank account
|
||||
wireTransfers.setFunds("123-12312", 100);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLottery() {
|
||||
// admin resets the lottery
|
||||
administration.resetLottery();
|
||||
assertEquals(0, administration.getAllSubmittedTickets().size());
|
||||
|
||||
// players submit the lottery tickets
|
||||
var ticket1 = service.submitTicket(LotteryTestUtils.createLotteryTicket("cvt@bbb.com",
|
||||
"123-12312", "+32425255", Set.of(1, 2, 3, 4)));
|
||||
assertTrue(ticket1.isPresent());
|
||||
var ticket2 = service.submitTicket(LotteryTestUtils.createLotteryTicket("ant@bac.com",
|
||||
"123-12312", "+32423455", Set.of(11, 12, 13, 14)));
|
||||
assertTrue(ticket2.isPresent());
|
||||
var ticket3 = service.submitTicket(LotteryTestUtils.createLotteryTicket("arg@boo.com",
|
||||
"123-12312", "+32421255", Set.of(6, 8, 13, 19)));
|
||||
assertTrue(ticket3.isPresent());
|
||||
assertEquals(3, administration.getAllSubmittedTickets().size());
|
||||
|
||||
// perform lottery
|
||||
var winningNumbers = administration.performLottery();
|
||||
|
||||
// cheat a bit for testing sake, use winning numbers to submit another ticket
|
||||
var ticket4 = service.submitTicket(LotteryTestUtils.createLotteryTicket("lucky@orb.com",
|
||||
"123-12312", "+12421255", winningNumbers.getNumbers()));
|
||||
assertTrue(ticket4.isPresent());
|
||||
assertEquals(4, administration.getAllSubmittedTickets().size());
|
||||
|
||||
// check winners
|
||||
var tickets = administration.getAllSubmittedTickets();
|
||||
for (var id : tickets.keySet()) {
|
||||
var checkResult = service.checkTicketForPrize(id, winningNumbers);
|
||||
assertNotEquals(CheckResult.TICKET_NOT_SUBMITTED, checkResult.getResult());
|
||||
if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) {
|
||||
assertTrue(checkResult.getPrizeAmount() > 0);
|
||||
} else {
|
||||
assertEquals(0, checkResult.getPrizeAmount());
|
||||
}
|
||||
}
|
||||
|
||||
// check another ticket that has not been submitted
|
||||
var checkResult = service.checkTicketForPrize(new LotteryTicketId(), winningNumbers);
|
||||
assertEquals(CheckResult.TICKET_NOT_SUBMITTED, checkResult.getResult());
|
||||
assertEquals(0, checkResult.getPrizeAmount());
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LotteryTicketCheckResult}
|
||||
*/
|
||||
class LotteryTicketCheckResultTest {
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
var result1 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
var result2 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
assertEquals(result1, result2);
|
||||
var result3 = new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 300000);
|
||||
assertNotEquals(result1, result3);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for lottery ticket id
|
||||
*/
|
||||
class LotteryTicketIdTest {
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
var ticketId1 = new LotteryTicketId();
|
||||
var ticketId2 = new LotteryTicketId();
|
||||
var ticketId3 = new LotteryTicketId();
|
||||
assertNotEquals(ticketId1, ticketId2);
|
||||
assertNotEquals(ticketId2, ticketId3);
|
||||
var ticketId4 = new LotteryTicketId(ticketId1.getId());
|
||||
assertEquals(ticketId1, ticketId4);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test Lottery Tickets for equality
|
||||
*/
|
||||
class LotteryTicketTest {
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
var details1 = new PlayerDetails("bob@foo.bar", "1212-121212", "+34332322");
|
||||
var numbers1 = LotteryNumbers.create(Set.of(1, 2, 3, 4));
|
||||
var ticket1 = new LotteryTicket(new LotteryTicketId(), details1, numbers1);
|
||||
var details2 = new PlayerDetails("bob@foo.bar", "1212-121212", "+34332322");
|
||||
var numbers2 = LotteryNumbers.create(Set.of(1, 2, 3, 4));
|
||||
var ticket2 = new LotteryTicket(new LotteryTicketId(), details2, numbers2);
|
||||
assertEquals(ticket1, ticket2);
|
||||
var details3 = new PlayerDetails("elsa@foo.bar", "1223-121212", "+49332322");
|
||||
var numbers3 = LotteryNumbers.create(Set.of(1, 2, 3, 8));
|
||||
var ticket3 = new LotteryTicket(new LotteryTicketId(), details3, numbers3);
|
||||
assertNotEquals(ticket1, ticket3);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PlayerDetails}
|
||||
*/
|
||||
class PlayerDetailsTest {
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
var details1 = new PlayerDetails("tom@foo.bar", "11212-123434", "+12323425");
|
||||
var details2 = new PlayerDetails("tom@foo.bar", "11212-123434", "+12323425");
|
||||
assertEquals(details1, details2);
|
||||
var details3 = new PlayerDetails("john@foo.bar", "16412-123439", "+34323432");
|
||||
assertNotEquals(details1, details3);
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
||||
import com.mongodb.MongoClient;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for Mongo event log
|
||||
*/
|
||||
@Disabled
|
||||
class MongoEventLogTest {
|
||||
|
||||
private static final String TEST_DB = "lotteryDBTest";
|
||||
private static final String TEST_EVENTS_COLLECTION = "testEvents";
|
||||
|
||||
private MongoEventLog mongoEventLog;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
MongoConnectionPropertiesLoader.load();
|
||||
var 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
|
||||
void testSetup() {
|
||||
assertEquals(0, mongoEventLog.getEventsCollection().countDocuments());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFundTransfers() {
|
||||
var playerDetails = new PlayerDetails("john@wayne.com", "000-000", "03432534543");
|
||||
mongoEventLog.prizeError(playerDetails, 1000);
|
||||
assertEquals(1, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.prizeError(playerDetails, 1000);
|
||||
assertEquals(2, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketDidNotWin(playerDetails);
|
||||
assertEquals(3, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketDidNotWin(playerDetails);
|
||||
assertEquals(4, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketSubmitError(playerDetails);
|
||||
assertEquals(5, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketSubmitError(playerDetails);
|
||||
assertEquals(6, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketSubmitted(playerDetails);
|
||||
assertEquals(7, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketSubmitted(playerDetails);
|
||||
assertEquals(8, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketWon(playerDetails, 1000);
|
||||
assertEquals(9, mongoEventLog.getEventsCollection().countDocuments());
|
||||
mongoEventLog.ticketWon(playerDetails, 1000);
|
||||
assertEquals(10, mongoEventLog.getEventsCollection().countDocuments());
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 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 com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utilities for lottery tests
|
||||
*/
|
||||
public class LotteryTestUtils {
|
||||
|
||||
/**
|
||||
* @return lottery ticket
|
||||
*/
|
||||
public static LotteryTicket createLotteryTicket() {
|
||||
return createLotteryTicket("foo@bar.com", "12231-213132", "+99324554", Set.of(1, 2, 3, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lottery ticket
|
||||
*/
|
||||
public static LotteryTicket createLotteryTicket(String email, String account, String phone,
|
||||
Set<Integer> givenNumbers) {
|
||||
var details = new PlayerDetails(email, account, phone);
|
||||
var numbers = LotteryNumbers.create(givenNumbers);
|
||||
return new LotteryTicket(new LotteryTicketId(), details, numbers);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user