Merge pull request #421 from iluwatar/hexagonal
Implements #86 Hexagonal Architecture
This commit is contained in:
commit
9de2cbe73e
34
hexagonal/README.md
Normal file
34
hexagonal/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Hexagonal Architecture
|
||||
folder: hexagonal
|
||||
permalink: /patterns/hexagonal/
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Java
|
||||
- Difficulty-Expert
|
||||
---
|
||||
|
||||
## Also known as
|
||||
Ports and Adapters
|
||||
Clean Architecture
|
||||
Onion Architecture
|
||||
|
||||
## Intent
|
||||
Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
Use Hexagonal Architecture pattern when
|
||||
|
||||
* it is important that the application is fully testable
|
||||
* you use Domain Driven Design methodology and/or Microservices architectural style
|
||||
|
||||
## Real world examples
|
||||
|
||||
* [Apache Isis](https://isis.apache.org/)
|
||||
|
||||
## Credits
|
||||
|
||||
* [Alistair Cockburn - Hexagonal Architecture](http://alistair.cockburn.us/Hexagonal+architecture)
|
BIN
hexagonal/etc/hexagonal.png
Normal file
BIN
hexagonal/etc/hexagonal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
325
hexagonal/etc/hexagonal.ucls
Normal file
325
hexagonal/etc/hexagonal.ucls
Normal file
@ -0,0 +1,325 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.9" 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.domain.LotteryTicket" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="169" width="270" x="2042" y="351"/>
|
||||
<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="2" 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="115" width="215" x="1490" y="351"/>
|
||||
<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="3" language="java" name="com.iluwatar.hexagonal.administration.LotteryAdministrationImpl"
|
||||
project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministrationImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="133" width="311" x="992" y="124"/>
|
||||
<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="4" 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="133" width="257" x="1745" y="351"/>
|
||||
<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="5" language="java" name="com.iluwatar.hexagonal.domain.LotteryConstants" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="169" width="227" x="205" y="124"/>
|
||||
<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="6" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketId" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="115" width="140" x="508" y="124"/>
|
||||
<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="7" 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="277" width="206" x="2042" y="560"/>
|
||||
<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="8" language="java" name="com.iluwatar.hexagonal.notifications.LotteryNotificationsImpl" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotificationsImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="169" width="229" x="723" y="124"/>
|
||||
<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="9" language="java" name="com.iluwatar.hexagonal.banking.WireTransfersImpl" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfersImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="151" width="215" x="1787" y="124"/>
|
||||
<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="10" language="java" name="com.iluwatar.hexagonal.administration.LotteryAdministration"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministration.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="115" width="311" x="426" y="351"/>
|
||||
<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="11" 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="115" width="188" x="2042" y="877"/>
|
||||
<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="12" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketCheckResult" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="187" width="229" x="2352" y="124"/>
|
||||
<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.PlayerDetails" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="241" width="219" x="1106" y="560"/>
|
||||
<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.database.LotteryTicketInMemoryRepository"
|
||||
project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketInMemoryRepository.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="151" width="257" x="2042" y="124"/>
|
||||
<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.service.LotteryService" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryService.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="97" width="404" x="1046" y="351"/>
|
||||
<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>
|
||||
<enumeration id="16" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="133" width="229" x="2352" y="351"/>
|
||||
<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>
|
||||
</enumeration>
|
||||
<class id="17" 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="133" width="217" x="169" y="351"/>
|
||||
<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="18" language="java" name="com.iluwatar.hexagonal.service.LotteryServiceImpl" project="hexagonal"
|
||||
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryServiceImpl.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="115" width="404" x="1343" y="124"/>
|
||||
<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="19" language="java" name="com.iluwatar.hexagonal.notifications.LotteryNotifications"
|
||||
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotifications.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="151" width="229" x="777" y="351"/>
|
||||
<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="20">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="21" name="repository"/>
|
||||
<multiplicity id="22" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="23">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="24" name="notifications"/>
|
||||
<multiplicity id="25" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="19" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="26">
|
||||
<end type="SOURCE" refId="18" navigable="false">
|
||||
<attribute id="27" name="notifications"/>
|
||||
<multiplicity id="28" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="19" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="29">
|
||||
<end type="SOURCE" refId="14" navigable="false">
|
||||
<attribute id="30" name="tickets"/>
|
||||
<multiplicity id="31" minimum="0" maximum="2147483647"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="32">
|
||||
<end type="SOURCE" refId="8"/>
|
||||
<end type="TARGET" refId="19"/>
|
||||
</realization>
|
||||
<realization id="33">
|
||||
<end type="SOURCE" refId="18"/>
|
||||
<end type="TARGET" refId="15"/>
|
||||
</realization>
|
||||
<realization id="34">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="10"/>
|
||||
</realization>
|
||||
<association id="35">
|
||||
<end type="SOURCE" refId="18" navigable="false">
|
||||
<attribute id="36" name="bank"/>
|
||||
<multiplicity id="37" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="2" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="38">
|
||||
<end type="SOURCE" refId="18" navigable="false">
|
||||
<attribute id="39" name="repository"/>
|
||||
<multiplicity id="40" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="41">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="42" name="bank"/>
|
||||
<multiplicity id="43" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="2" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="44">
|
||||
<end type="SOURCE" refId="12" navigable="false">
|
||||
<attribute id="45" name="checkResult"/>
|
||||
<multiplicity id="46" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="16" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<nesting id="47">
|
||||
<end type="SOURCE" refId="12"/>
|
||||
<end type="TARGET" refId="16"/>
|
||||
</nesting>
|
||||
<association id="48">
|
||||
<end type="SOURCE" refId="17" navigable="false">
|
||||
<attribute id="49" name="allPlayerDetails"/>
|
||||
<multiplicity id="50" minimum="0" maximum="2147483647"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="13" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="51">
|
||||
<end type="SOURCE" refId="1" navigable="false">
|
||||
<attribute id="52" name="playerDetails"/>
|
||||
<multiplicity id="53" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="13" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="54">
|
||||
<end type="SOURCE" refId="1" navigable="false">
|
||||
<attribute id="55" name="lotteryNumbers"/>
|
||||
<multiplicity id="56" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="7" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="57">
|
||||
<end type="SOURCE" refId="14"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</realization>
|
||||
<nesting id="58">
|
||||
<end type="SOURCE" refId="7"/>
|
||||
<end type="TARGET" refId="11"/>
|
||||
</nesting>
|
||||
<realization id="59">
|
||||
<end type="SOURCE" refId="9"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</realization>
|
||||
<association id="60">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="61" name="service"/>
|
||||
<multiplicity id="62" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="15" 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>
|
43
hexagonal/pom.xml
Normal file
43
hexagonal/pom.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright (c) 2014 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.12.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hexagonal</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
151
hexagonal/src/main/java/com/iluwatar/hexagonal/App.java
Normal file
151
hexagonal/src/main/java/com/iluwatar/hexagonal/App.java
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.iluwatar.hexagonal.administration.LotteryAdministration;
|
||||
import com.iluwatar.hexagonal.administration.LotteryAdministrationImpl;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
|
||||
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
import com.iluwatar.hexagonal.service.LotteryService;
|
||||
import com.iluwatar.hexagonal.service.LotteryServiceImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* 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 {@link LotteryAdministration}
|
||||
* through which the lottery round is initiated and run and
|
||||
* {@link LotteryService} that allows players to submit lottery tickets for
|
||||
* the draw.<p>
|
||||
*
|
||||
* The secondary ports that application core uses are {@link WireTransfers}
|
||||
* which is a banking service, {@link LotteryNotifications} that delivers
|
||||
* notifications as lottery events occur and {@link LotteryTicketRepository}
|
||||
* that is the storage for the lottery tickets.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static List<PlayerDetails> allPlayerDetails;
|
||||
|
||||
static {
|
||||
allPlayerDetails = new ArrayList<>();
|
||||
allPlayerDetails.add(PlayerDetails.create("john@google.com", "312-342", "+3242434242"));
|
||||
allPlayerDetails.add(PlayerDetails.create("mary@google.com", "234-987", "+23452346"));
|
||||
allPlayerDetails.add(PlayerDetails.create("steve@google.com", "833-836", "+63457543"));
|
||||
allPlayerDetails.add(PlayerDetails.create("wayne@google.com", "319-826", "+24626"));
|
||||
allPlayerDetails.add(PlayerDetails.create("johnie@google.com", "983-322", "+3635635"));
|
||||
allPlayerDetails.add(PlayerDetails.create("andy@google.com", "934-734", "+0898245"));
|
||||
allPlayerDetails.add(PlayerDetails.create("richard@google.com", "536-738", "+09845325"));
|
||||
allPlayerDetails.add(PlayerDetails.create("kevin@google.com", "453-936", "+2423532"));
|
||||
allPlayerDetails.add(PlayerDetails.create("arnold@google.com", "114-988", "+5646346524"));
|
||||
allPlayerDetails.add(PlayerDetails.create("ian@google.com", "663-765", "+928394235"));
|
||||
allPlayerDetails.add(PlayerDetails.create("robin@google.com", "334-763", "+35448"));
|
||||
allPlayerDetails.add(PlayerDetails.create("ted@google.com", "735-964", "+98752345"));
|
||||
allPlayerDetails.add(PlayerDetails.create("larry@google.com", "734-853", "+043842423"));
|
||||
allPlayerDetails.add(PlayerDetails.create("calvin@google.com", "334-746", "+73294135"));
|
||||
allPlayerDetails.add(PlayerDetails.create("jacob@google.com", "444-766", "+358042354"));
|
||||
allPlayerDetails.add(PlayerDetails.create("edwin@google.com", "895-345", "+9752435"));
|
||||
allPlayerDetails.add(PlayerDetails.create("mary@google.com", "760-009", "+34203542"));
|
||||
allPlayerDetails.add(PlayerDetails.create("lolita@google.com", "425-907", "+9872342"));
|
||||
allPlayerDetails.add(PlayerDetails.create("bruno@google.com", "023-638", "+673824122"));
|
||||
allPlayerDetails.add(PlayerDetails.create("peter@google.com", "335-886", "+5432503945"));
|
||||
allPlayerDetails.add(PlayerDetails.create("warren@google.com", "225-946", "+9872341324"));
|
||||
allPlayerDetails.add(PlayerDetails.create("monica@google.com", "265-748", "+134124"));
|
||||
allPlayerDetails.add(PlayerDetails.create("ollie@google.com", "190-045", "+34453452"));
|
||||
allPlayerDetails.add(PlayerDetails.create("yngwie@google.com", "241-465", "+9897641231"));
|
||||
allPlayerDetails.add(PlayerDetails.create("lars@google.com", "746-936", "+42345298345"));
|
||||
allPlayerDetails.add(PlayerDetails.create("bobbie@google.com", "946-384", "+79831742"));
|
||||
allPlayerDetails.add(PlayerDetails.create("tyron@google.com", "310-992", "+0498837412"));
|
||||
allPlayerDetails.add(PlayerDetails.create("tyrell@google.com", "032-045", "+67834134"));
|
||||
allPlayerDetails.add(PlayerDetails.create("nadja@google.com", "000-346", "+498723"));
|
||||
allPlayerDetails.add(PlayerDetails.create("wendy@google.com", "994-989", "+987324454"));
|
||||
allPlayerDetails.add(PlayerDetails.create("luke@google.com", "546-634", "+987642435"));
|
||||
allPlayerDetails.add(PlayerDetails.create("bjorn@google.com", "342-874", "+7834325"));
|
||||
allPlayerDetails.add(PlayerDetails.create("lisa@google.com", "024-653", "+980742154"));
|
||||
allPlayerDetails.add(PlayerDetails.create("anton@google.com", "834-935", "+876423145"));
|
||||
allPlayerDetails.add(PlayerDetails.create("bruce@google.com", "284-936", "+09843212345"));
|
||||
allPlayerDetails.add(PlayerDetails.create("ray@google.com", "843-073", "+678324123"));
|
||||
allPlayerDetails.add(PlayerDetails.create("ron@google.com", "637-738", "+09842354"));
|
||||
allPlayerDetails.add(PlayerDetails.create("xavier@google.com", "143-947", "+375245"));
|
||||
allPlayerDetails.add(PlayerDetails.create("harriet@google.com", "842-404", "+131243252"));
|
||||
WireTransfersImpl wireTransfers = new WireTransfersImpl();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < allPlayerDetails.size(); i++) {
|
||||
wireTransfers.setFunds(allPlayerDetails.get(i).getBankAccount(),
|
||||
random.nextInt(LotteryConstants.PLAYER_MAX_SALDO));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// start new lottery round
|
||||
LotteryAdministration administartion = new LotteryAdministrationImpl();
|
||||
administartion.resetLottery();
|
||||
|
||||
// submit some lottery tickets
|
||||
LotteryServiceImpl service = new LotteryServiceImpl();
|
||||
submitTickets(service, 20);
|
||||
|
||||
// perform lottery
|
||||
administartion.performLottery();
|
||||
}
|
||||
|
||||
private static void submitTickets(LotteryService lotteryService, int numTickets) {
|
||||
for (int i = 0; i < numTickets; i++) {
|
||||
LotteryTicket ticket = LotteryTicket.create(getRandomPlayerDetails(), LotteryNumbers.createRandom());
|
||||
lotteryService.submitTicket(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
private static PlayerDetails getRandomPlayerDetails() {
|
||||
Random random = new Random();
|
||||
int idx = random.nextInt(allPlayerDetails.size());
|
||||
return allPlayerDetails.get(idx);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.administration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
|
||||
/**
|
||||
*
|
||||
* Administrator interface for lottery service.
|
||||
*
|
||||
*/
|
||||
public interface LotteryAdministration {
|
||||
|
||||
/**
|
||||
* Get all the lottery tickets submitted for lottery
|
||||
*/
|
||||
Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets();
|
||||
|
||||
/**
|
||||
* Draw lottery numbers
|
||||
*/
|
||||
LotteryNumbers performLottery();
|
||||
|
||||
/**
|
||||
* Begin new lottery round
|
||||
*/
|
||||
void resetLottery();
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.administration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
|
||||
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import com.iluwatar.hexagonal.notifications.LotteryNotifications;
|
||||
import com.iluwatar.hexagonal.notifications.LotteryNotificationsImpl;
|
||||
import com.iluwatar.hexagonal.service.LotteryService;
|
||||
import com.iluwatar.hexagonal.service.LotteryServiceImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* Lottery administration implementation
|
||||
*
|
||||
*/
|
||||
public class LotteryAdministrationImpl implements LotteryAdministration {
|
||||
|
||||
private final LotteryTicketRepository repository;
|
||||
private final LotteryService service = new LotteryServiceImpl();
|
||||
private final LotteryNotifications notifications = new LotteryNotificationsImpl();
|
||||
private final WireTransfers bank = new WireTransfersImpl();
|
||||
public LotteryAdministrationImpl() {
|
||||
repository = new LotteryTicketInMemoryRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LotteryNumbers performLottery() {
|
||||
LotteryNumbers numbers = LotteryNumbers.createRandom();
|
||||
Map<LotteryTicketId, LotteryTicket> tickets = getAllSubmittedTickets();
|
||||
for (LotteryTicketId id: tickets.keySet()) {
|
||||
LotteryTicketCheckResult result = service.checkTicketForPrize(id, numbers);
|
||||
if (result.getResult().equals(CheckResult.WIN_PRIZE)) {
|
||||
boolean transferred = bank.transferFunds(LotteryConstants.PRIZE_AMOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT,
|
||||
tickets.get(id).getPlayerDetails().getBankAccount());
|
||||
if (transferred) {
|
||||
notifications.notifyPrize(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
||||
} else {
|
||||
notifications.notifyPrizeError(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
||||
}
|
||||
} else if (result.getResult().equals(CheckResult.NO_PRIZE)) {
|
||||
notifications.notifyNoWin(tickets.get(id).getPlayerDetails());
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetLottery() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.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);
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.banking;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Banking implementation
|
||||
*
|
||||
*/
|
||||
public class WireTransfersImpl implements WireTransfers {
|
||||
|
||||
private static Map<String, Integer> accounts = new HashMap<>();
|
||||
|
||||
static {
|
||||
accounts.put(LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_SALDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFunds(String bankAccount, int amount) {
|
||||
accounts.put(bankAccount, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFunds(String bankAccount) {
|
||||
return accounts.getOrDefault(bankAccount, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount) {
|
||||
if (accounts.getOrDefault(sourceBackAccount, 0) >= amount) {
|
||||
accounts.put(sourceBackAccount, accounts.get(sourceBackAccount) - amount);
|
||||
accounts.put(destinationBankAccount, accounts.get(destinationBankAccount) + amount);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.database;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
|
||||
/**
|
||||
*
|
||||
* Mock database for lottery tickets.
|
||||
*
|
||||
*/
|
||||
public class LotteryTicketInMemoryRepository implements LotteryTicketRepository {
|
||||
|
||||
private static Map<LotteryTicketId, LotteryTicket> tickets = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicket> findById(LotteryTicketId id) {
|
||||
LotteryTicket ticket = tickets.get(id);
|
||||
if (ticket == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicketId> save(LotteryTicket ticket) {
|
||||
LotteryTicketId 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();
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.database;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface for accessing lottery tickets in database.
|
||||
*
|
||||
*/
|
||||
public interface LotteryTicketRepository {
|
||||
|
||||
/**
|
||||
* Find lottery ticket by id
|
||||
*/
|
||||
Optional<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();
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* Lottery domain constants
|
||||
*
|
||||
*/
|
||||
public class LotteryConstants {
|
||||
|
||||
public static final int PRIZE_AMOUNT = 100000;
|
||||
public static final String SERVICE_BANK_ACCOUNT = "123-123";
|
||||
public static final int TICKET_PRIZE = 3;
|
||||
public static final int SERVICE_BANK_ACCOUNT_SALDO = 150000;
|
||||
public static final int PLAYER_MAX_SALDO = 100;
|
||||
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must be unique and
|
||||
* between 1 and 20.
|
||||
*
|
||||
*/
|
||||
public class LotteryNumbers {
|
||||
|
||||
private final Set<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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return random LotteryNumbers
|
||||
*/
|
||||
public static LotteryNumbers createRandom() {
|
||||
return new LotteryNumbers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return given LotteryNumbers
|
||||
*/
|
||||
public static LotteryNumbers create(Set<Integer> givenNumbers) {
|
||||
return new LotteryNumbers(givenNumbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lottery numbers
|
||||
*/
|
||||
public Set<Integer> getNumbers() {
|
||||
return Collections.unmodifiableSet(numbers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((numbers == null) ? 0 : numbers.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LotteryNumbers other = (LotteryNumbers) obj;
|
||||
if (numbers == null) {
|
||||
if (other.numbers != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!numbers.equals(other.numbers)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 4 unique random numbers between 1-20 into numbers set.
|
||||
*/
|
||||
private void generateRandomNumbers() {
|
||||
numbers.clear();
|
||||
RandomNumberGenerator generator = new RandomNumberGenerator(MIN_NUMBER, MAX_NUMBER);
|
||||
while (numbers.size() < NUM_NUMBERS) {
|
||||
int num = generator.nextInt();
|
||||
if (!numbers.contains(num)) {
|
||||
numbers.add(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Helper class for generating random numbers.
|
||||
*
|
||||
*/
|
||||
private static class RandomNumberGenerator {
|
||||
|
||||
private PrimitiveIterator.OfInt randomIterator;
|
||||
|
||||
/**
|
||||
* Initialize a new random number generator that generates random numbers in the range [min, max]
|
||||
*
|
||||
* @param min the min value (inclusive)
|
||||
* @param max the max value (inclusive)
|
||||
*/
|
||||
public RandomNumberGenerator(int min, int max) {
|
||||
randomIterator = new Random().ints(min, max + 1).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a random number in the range (min, max)
|
||||
*/
|
||||
public int nextInt() {
|
||||
return randomIterator.nextInt();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* Immutable value object representing lottery ticket.
|
||||
*
|
||||
*/
|
||||
public class LotteryTicket {
|
||||
|
||||
private final PlayerDetails playerDetails;
|
||||
private final LotteryNumbers lotteryNumbers;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private LotteryTicket(PlayerDetails details, LotteryNumbers numbers) {
|
||||
playerDetails = details;
|
||||
lotteryNumbers = numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating lottery tickets;
|
||||
*/
|
||||
public static LotteryTicket create(PlayerDetails details, LotteryNumbers numbers) {
|
||||
return new LotteryTicket(details, numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return player details
|
||||
*/
|
||||
public PlayerDetails getPlayerDetails() {
|
||||
return playerDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lottery numbers
|
||||
*/
|
||||
public LotteryNumbers getNumbers() {
|
||||
return lotteryNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((lotteryNumbers == null) ? 0 : lotteryNumbers.hashCode());
|
||||
result = prime * result + ((playerDetails == null) ? 0 : playerDetails.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LotteryTicket other = (LotteryTicket) obj;
|
||||
if (lotteryNumbers == null) {
|
||||
if (other.lotteryNumbers != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!lotteryNumbers.equals(other.lotteryNumbers)) {
|
||||
return false;
|
||||
}
|
||||
if (playerDetails == null) {
|
||||
if (other.playerDetails != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!playerDetails.equals(other.playerDetails)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents lottery ticket check result.
|
||||
*
|
||||
*/
|
||||
public class LotteryTicketCheckResult {
|
||||
|
||||
public enum CheckResult { WIN_PRIZE, NO_PRIZE, TICKET_NOT_SUBMITTED };
|
||||
|
||||
private final CheckResult checkResult;
|
||||
private final int prizeAmount;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public LotteryTicketCheckResult(CheckResult result) {
|
||||
checkResult = result;
|
||||
prizeAmount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public LotteryTicketCheckResult(CheckResult result, int amount) {
|
||||
checkResult = result;
|
||||
prizeAmount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return check result
|
||||
*/
|
||||
public CheckResult getResult() {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return prize amount
|
||||
*/
|
||||
public int getPrizeAmount() {
|
||||
return prizeAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((checkResult == null) ? 0 : checkResult.hashCode());
|
||||
result = prime * result + prizeAmount;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LotteryTicketCheckResult other = (LotteryTicketCheckResult) obj;
|
||||
if (checkResult != other.checkResult) {
|
||||
return false;
|
||||
}
|
||||
if (prizeAmount != other.prizeAmount) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Lottery ticked id
|
||||
*/
|
||||
public class LotteryTicketId {
|
||||
|
||||
private final UUID id;
|
||||
|
||||
public LotteryTicketId() {
|
||||
id = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* Immutable value object containing lottery player details.
|
||||
*
|
||||
*/
|
||||
public class PlayerDetails {
|
||||
|
||||
private final String emailAddress;
|
||||
private final String bankAccountNumber;
|
||||
private final String phoneNumber;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private PlayerDetails(String email, String bankAccount, String phone) {
|
||||
emailAddress = email;
|
||||
bankAccountNumber = bankAccount;
|
||||
phoneNumber = phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating new objects.
|
||||
*/
|
||||
public static PlayerDetails create(String email, String bankAccount, String phone) {
|
||||
return new PlayerDetails(email, bankAccount, phone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bank account number
|
||||
*/
|
||||
public String getBankAccount() {
|
||||
return bankAccountNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return phone number
|
||||
*/
|
||||
public String getPhoneNumber() {
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((bankAccountNumber == null) ? 0 : bankAccountNumber.hashCode());
|
||||
result = prime * result + ((emailAddress == null) ? 0 : emailAddress.hashCode());
|
||||
result = prime * result + ((phoneNumber == null) ? 0 : phoneNumber.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PlayerDetails other = (PlayerDetails) obj;
|
||||
if (bankAccountNumber == null) {
|
||||
if (other.bankAccountNumber != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!bankAccountNumber.equals(other.bankAccountNumber)) {
|
||||
return false;
|
||||
}
|
||||
if (emailAddress == null) {
|
||||
if (other.emailAddress != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!emailAddress.equals(other.emailAddress)) {
|
||||
return false;
|
||||
}
|
||||
if (phoneNumber == null) {
|
||||
if (other.phoneNumber != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!phoneNumber.equals(other.phoneNumber)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.notifications;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides notifications for lottery events.
|
||||
*
|
||||
*/
|
||||
public interface LotteryNotifications {
|
||||
|
||||
/**
|
||||
* Notify lottery ticket was submitted
|
||||
*/
|
||||
void notifyTicketSubmitted(PlayerDetails details);
|
||||
|
||||
/**
|
||||
* Notify there was an error submitting lottery ticket
|
||||
*/
|
||||
void notifyTicketSubmitError(PlayerDetails details);
|
||||
|
||||
/**
|
||||
* Notify lottery ticket did not win
|
||||
*/
|
||||
void notifyNoWin(PlayerDetails details);
|
||||
|
||||
/**
|
||||
* Notify that prize has been paid
|
||||
*/
|
||||
void notifyPrize(PlayerDetails details, int prizeAmount);
|
||||
|
||||
/**
|
||||
* Notify that there was an error paying the prize
|
||||
*/
|
||||
void notifyPrizeError(PlayerDetails details, int prizeAmount);
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.notifications;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
|
||||
public class LotteryNotificationsImpl implements LotteryNotifications {
|
||||
|
||||
@Override
|
||||
public void notifyTicketSubmitted(PlayerDetails details) {
|
||||
System.out.println(String.format("Lottery ticket for %s was submitted. Bank account %s was charged for 3 credits.",
|
||||
details.getEmail(), details.getBankAccount()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNoWin(PlayerDetails details) {
|
||||
System.out.println(String.format("Lottery ticket for %s was checked and unfortunately did not win this time.",
|
||||
details.getEmail()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPrize(PlayerDetails details, int prizeAmount) {
|
||||
System.out
|
||||
.println(String.format("Lottery ticket for %s has won! The bank account %s was deposited with %d credits.",
|
||||
details.getEmail(), details.getBankAccount(), prizeAmount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPrizeError(PlayerDetails details, int prizeAmount) {
|
||||
System.out
|
||||
.println(String.format("Lottery ticket for %s has won! Unfortunately the bank credit transfer of %d failed.",
|
||||
details.getEmail(), prizeAmount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyTicketSubmitError(PlayerDetails details) {
|
||||
System.out.println(
|
||||
String.format("Lottery ticket for %s could not be submitted because the credit transfer of 3 credits failed.",
|
||||
details.getEmail()));
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface for submitting and checking lottery tickets.
|
||||
*
|
||||
*/
|
||||
public interface LotteryService {
|
||||
|
||||
/**
|
||||
* Submit lottery ticket to participate in the lottery
|
||||
*/
|
||||
Optional<LotteryTicketId> submitTicket(LotteryTicket ticket);
|
||||
|
||||
/**
|
||||
* Check if lottery ticket has won
|
||||
*/
|
||||
LotteryTicketCheckResult checkTicketForPrize(LotteryTicketId id, LotteryNumbers winningNumbers);
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
|
||||
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
import com.iluwatar.hexagonal.notifications.LotteryNotifications;
|
||||
import com.iluwatar.hexagonal.notifications.LotteryNotificationsImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implementation for lottery service
|
||||
*
|
||||
*/
|
||||
public class LotteryServiceImpl implements LotteryService {
|
||||
|
||||
private final LotteryTicketRepository repository;
|
||||
|
||||
private final WireTransfers bank = new WireTransfersImpl();
|
||||
|
||||
private final LotteryNotifications notifications = new LotteryNotificationsImpl();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public LotteryServiceImpl() {
|
||||
repository = new LotteryTicketInMemoryRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {
|
||||
boolean result = bank.transferFunds(LotteryConstants.TICKET_PRIZE, ticket.getPlayerDetails().getBankAccount(),
|
||||
LotteryConstants.SERVICE_BANK_ACCOUNT);
|
||||
if (result == false) {
|
||||
notifications.notifyTicketSubmitError(ticket.getPlayerDetails());
|
||||
return Optional.empty();
|
||||
}
|
||||
Optional<LotteryTicketId> optional = repository.save(ticket);
|
||||
if (optional.isPresent()) {
|
||||
notifications.notifyTicketSubmitted(ticket.getPlayerDetails());
|
||||
}
|
||||
return optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LotteryTicketCheckResult checkTicketForPrize(LotteryTicketId id, LotteryNumbers winningNumbers) {
|
||||
Optional<LotteryTicket> optional = repository.findById(id);
|
||||
if (optional.isPresent()) {
|
||||
if (optional.get().getNumbers().equals(winningNumbers)) {
|
||||
return new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 1000);
|
||||
} else {
|
||||
return new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
}
|
||||
} else {
|
||||
return new LotteryTicketCheckResult(CheckResult.TICKET_NOT_SUBMITTED);
|
||||
}
|
||||
}
|
||||
}
|
37
hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java
Normal file
37
hexagonal/src/test/java/com/iluwatar/hexagonal/AppTest.java
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void testApp() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.banking;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Tests for banking
|
||||
*
|
||||
*/
|
||||
public class WireTransfersTest {
|
||||
|
||||
private final WireTransfers bank = new WireTransfersImpl();
|
||||
|
||||
@Test
|
||||
public void testInit() {
|
||||
assertEquals(bank.getFunds("foo"), 0);
|
||||
bank.setFunds("foo", 100);
|
||||
assertEquals(bank.getFunds("foo"), 100);
|
||||
bank.setFunds("bar", 150);
|
||||
assertEquals(bank.getFunds("bar"), 150);
|
||||
assertTrue(bank.transferFunds(50, "bar", "foo"));
|
||||
assertEquals(bank.getFunds("foo"), 150);
|
||||
assertEquals(bank.getFunds("bar"), 100);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.database;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import com.iluwatar.hexagonal.test.LotteryTestUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* Tests for {@link LotteryTicketRepository}
|
||||
*
|
||||
*/
|
||||
public class LotteryTicketRepositoryTest {
|
||||
|
||||
private final LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
|
||||
|
||||
@Before
|
||||
public void clear() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrudOperations() {
|
||||
LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
|
||||
assertEquals(repository.findAll().size(), 0);
|
||||
LotteryTicket ticket = LotteryTestUtils.createLotteryTicket();
|
||||
Optional<LotteryTicketId> id = repository.save(ticket);
|
||||
assertTrue(id.isPresent());
|
||||
assertEquals(repository.findAll().size(), 1);
|
||||
Optional<LotteryTicket> optionalTicket = repository.findById(id.get());
|
||||
assertTrue(optionalTicket.isPresent());
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link LotteryNumbers}
|
||||
*
|
||||
*/
|
||||
public class LotteryNumbersTest {
|
||||
|
||||
@Test
|
||||
public void testGivenNumbers() {
|
||||
LotteryNumbers numbers = LotteryNumbers.create(
|
||||
new HashSet<>(Arrays.asList(1, 2, 3, 4)));
|
||||
assertEquals(numbers.getNumbers().size(), 4);
|
||||
assertTrue(numbers.getNumbers().contains(1));
|
||||
assertTrue(numbers.getNumbers().contains(2));
|
||||
assertTrue(numbers.getNumbers().contains(3));
|
||||
assertTrue(numbers.getNumbers().contains(4));
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testNumbersCantBeModified() {
|
||||
LotteryNumbers numbers = LotteryNumbers.create(
|
||||
new HashSet<>(Arrays.asList(1, 2, 3, 4)));
|
||||
numbers.getNumbers().add(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomNumbers() {
|
||||
LotteryNumbers numbers = LotteryNumbers.createRandom();
|
||||
assertEquals(numbers.getNumbers().size(), LotteryNumbers.NUM_NUMBERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
LotteryNumbers numbers1 = LotteryNumbers.create(
|
||||
new HashSet<>(Arrays.asList(1, 2, 3, 4)));
|
||||
LotteryNumbers numbers2 = LotteryNumbers.create(
|
||||
new HashSet<>(Arrays.asList(1, 2, 3, 4)));
|
||||
assertTrue(numbers1.equals(numbers2));
|
||||
LotteryNumbers numbers3 = LotteryNumbers.create(
|
||||
new HashSet<>(Arrays.asList(11, 12, 13, 14)));
|
||||
assertFalse(numbers1.equals(numbers3));
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link LotteryTicketCheckResult}
|
||||
*
|
||||
*/
|
||||
public class LotteryTicketCheckResultTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
LotteryTicketCheckResult result1 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
LotteryTicketCheckResult result2 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||
assertEquals(result1, result2);
|
||||
LotteryTicketCheckResult result3 = new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 300000);
|
||||
assertFalse(result1.equals(result3));
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class LotteryTicketTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
PlayerDetails details1 = PlayerDetails.create("bob@foo.bar", "1212-121212", "+34332322");
|
||||
LotteryNumbers numbers1 = LotteryNumbers.create(new HashSet<Integer>(Arrays.asList(1, 2, 3, 4)));
|
||||
LotteryTicket ticket1 = LotteryTicket.create(details1, numbers1);
|
||||
PlayerDetails details2 = PlayerDetails.create("bob@foo.bar", "1212-121212", "+34332322");
|
||||
LotteryNumbers numbers2 = LotteryNumbers.create(new HashSet<Integer>(Arrays.asList(1, 2, 3, 4)));
|
||||
LotteryTicket ticket2 = LotteryTicket.create(details2, numbers2);
|
||||
assertEquals(ticket1, ticket2);
|
||||
PlayerDetails details3 = PlayerDetails.create("elsa@foo.bar", "1223-121212", "+49332322");
|
||||
LotteryNumbers numbers3 = LotteryNumbers.create(new HashSet<Integer>(Arrays.asList(1, 2, 3, 8)));
|
||||
LotteryTicket ticket3 = LotteryTicket.create(details3, numbers3);
|
||||
assertFalse(ticket1.equals(ticket3));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.domain;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link PlayerDetails}
|
||||
*
|
||||
*/
|
||||
public class PlayerDetailsTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
PlayerDetails details1 = PlayerDetails.create("tom@foo.bar", "11212-123434", "+12323425");
|
||||
PlayerDetails details2 = PlayerDetails.create("tom@foo.bar", "11212-123434", "+12323425");
|
||||
assertEquals(details1, details2);
|
||||
PlayerDetails details3 = PlayerDetails.create("john@foo.bar", "16412-123439", "+34323432");
|
||||
assertFalse(details1.equals(details3));
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.lottery;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.iluwatar.hexagonal.administration.LotteryAdministration;
|
||||
import com.iluwatar.hexagonal.administration.LotteryAdministrationImpl;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||
import com.iluwatar.hexagonal.service.LotteryService;
|
||||
import com.iluwatar.hexagonal.service.LotteryServiceImpl;
|
||||
import com.iluwatar.hexagonal.test.LotteryTestUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test the lottery system
|
||||
*
|
||||
*/
|
||||
public class LotteryTest {
|
||||
|
||||
private final LotteryAdministration admin = new LotteryAdministrationImpl();
|
||||
private final LotteryService service = new LotteryServiceImpl();
|
||||
private final LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
|
||||
private final WireTransfers wireTransfers = new WireTransfersImpl();
|
||||
|
||||
@Before
|
||||
public void clear() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLottery() {
|
||||
|
||||
// setup bank account with funds
|
||||
wireTransfers.setFunds("123-12312", 100);
|
||||
|
||||
// admin resets the lottery
|
||||
admin.resetLottery();
|
||||
assertEquals(admin.getAllSubmittedTickets().size(), 0);
|
||||
|
||||
// players submit the lottery tickets
|
||||
Optional<LotteryTicketId> ticket1 = service.submitTicket(LotteryTestUtils.createLotteryTicket("cvt@bbb.com",
|
||||
"123-12312", "+32425255", new HashSet<>(Arrays.asList(1, 2, 3, 4))));
|
||||
assertTrue(ticket1.isPresent());
|
||||
Optional<LotteryTicketId> ticket2 = service.submitTicket(LotteryTestUtils.createLotteryTicket("ant@bac.com",
|
||||
"123-12312", "+32423455", new HashSet<>(Arrays.asList(11, 12, 13, 14))));
|
||||
assertTrue(ticket2.isPresent());
|
||||
Optional<LotteryTicketId> ticket3 = service.submitTicket(LotteryTestUtils.createLotteryTicket("arg@boo.com",
|
||||
"123-12312", "+32421255", new HashSet<>(Arrays.asList(6, 8, 13, 19))));
|
||||
assertTrue(ticket3.isPresent());
|
||||
assertEquals(admin.getAllSubmittedTickets().size(), 3);
|
||||
|
||||
// perform lottery
|
||||
LotteryNumbers winningNumbers = admin.performLottery();
|
||||
|
||||
// cheat a bit for testing sake, use winning numbers to submit another ticket
|
||||
Optional<LotteryTicketId> ticket4 = service.submitTicket(LotteryTestUtils.createLotteryTicket("lucky@orb.com",
|
||||
"123-12312", "+12421255", winningNumbers.getNumbers()));
|
||||
assertTrue(ticket4.isPresent());
|
||||
assertEquals(admin.getAllSubmittedTickets().size(), 4);
|
||||
|
||||
// check winners
|
||||
Map<LotteryTicketId, LotteryTicket> tickets = admin.getAllSubmittedTickets();
|
||||
for (LotteryTicketId id: tickets.keySet()) {
|
||||
LotteryTicketCheckResult checkResult = service.checkTicketForPrize(id, winningNumbers);
|
||||
assertTrue(checkResult.getResult() != CheckResult.TICKET_NOT_SUBMITTED);
|
||||
if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) {
|
||||
assertTrue(checkResult.getPrizeAmount() > 0);
|
||||
} else if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) {
|
||||
assertEquals(checkResult.getPrizeAmount(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// check another ticket that has not been submitted
|
||||
LotteryTicketCheckResult checkResult = service.checkTicketForPrize(new LotteryTicketId(), winningNumbers);
|
||||
assertTrue(checkResult.getResult() == CheckResult.TICKET_NOT_SUBMITTED);
|
||||
assertEquals(checkResult.getPrizeAmount(), 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.hexagonal.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||
|
||||
/**
|
||||
*
|
||||
* Utilities for lottery tests
|
||||
*
|
||||
*/
|
||||
public class LotteryTestUtils {
|
||||
|
||||
/**
|
||||
* @return lottery ticket
|
||||
*/
|
||||
public static LotteryTicket createLotteryTicket() {
|
||||
return createLotteryTicket("foo@bar.com", "12231-213132", "+99324554", new HashSet<>(Arrays.asList(1, 2, 3, 4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lottery ticket
|
||||
*/
|
||||
public static LotteryTicket createLotteryTicket(String email, String account, String phone,
|
||||
Set<Integer> givenNumbers) {
|
||||
PlayerDetails details = PlayerDetails.create(email, account, phone);
|
||||
LotteryNumbers numbers = LotteryNumbers.create(givenNumbers);
|
||||
return LotteryTicket.create(details, numbers);
|
||||
}
|
||||
}
|
9
pom.xml
9
pom.xml
@ -17,9 +17,7 @@
|
||||
LIABILITY, WHETHER IN AN ACTION 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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
--><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>
|
||||
|
||||
<groupId>com.iluwatar</groupId>
|
||||
@ -126,7 +124,8 @@
|
||||
<module>mute-idiom</module>
|
||||
<module>mutex</module>
|
||||
<module>semaphore</module>
|
||||
</modules>
|
||||
<module>hexagonal</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@ -425,4 +424,4 @@
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user