Merge pull request #421 from iluwatar/hexagonal

Implements #86 Hexagonal Architecture
This commit is contained in:
Ilkka Seppälä 2016-05-21 22:19:16 +03:00
commit 9de2cbe73e
31 changed files with 2274 additions and 5 deletions

34
hexagonal/README.md Normal file
View 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.
![Hexagonal Architecture class diagram](./etc/hexagonal.png)
## 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View 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
View 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>

View 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);
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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()));
}
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View 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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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>