Resolves checkstyle errors for guarded-suspension, half-sync-half-async, hexagonal (#1064)
* Reduces checkstyle errors in guarded-suspension * Reduces checkstyle errors in half-sync-half-async * Reduces checkstyle errors in hexagonal
This commit is contained in:
parent
4f9ee0189c
commit
dda09535e6
@ -21,15 +21,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Guarded-suspension is a concurrent design pattern for handling situation when to execute some action we need
|
|
||||||
* condition to be satisfied.
|
|
||||||
* <p>
|
|
||||||
* Implementation is based on GuardedQueue, which has two methods: get and put,
|
|
||||||
* the condition is that we cannot get from empty queue so when thread attempt
|
|
||||||
* to break the condition we invoke Object's wait method on him and when other thread put an element
|
|
||||||
* to the queue he notify the waiting one that now he can get from queue.
|
|
||||||
*/
|
|
||||||
package com.iluwatar.guarded.suspension;
|
package com.iluwatar.guarded.suspension;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -38,10 +29,18 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by robertt240 on 1/26/17.
|
* Created by robertt240 on 1/26/17.
|
||||||
|
*
|
||||||
|
* <p>Guarded-suspension is a concurrent design pattern for handling situation when to execute some
|
||||||
|
* action we need condition to be satisfied.
|
||||||
|
*
|
||||||
|
* <p>Implementation is based on GuardedQueue, which has two methods: get and put, the condition is
|
||||||
|
* that we cannot get from empty queue so when thread attempt to break the condition we invoke
|
||||||
|
* Object's wait method on him and when other thread put an element to the queue he notify the
|
||||||
|
* waiting one that now he can get from queue.
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
/**
|
/**
|
||||||
* Example pattern execution
|
* Example pattern execution.
|
||||||
*
|
*
|
||||||
* @param args - command line args
|
* @param args - command line args
|
||||||
*/
|
*/
|
||||||
@ -55,13 +54,15 @@ public class App {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
//here we wait two seconds to show that the thread which is trying to get from guardedQueue will be waiting
|
// here we wait two seconds to show that the thread which is trying
|
||||||
|
// to get from guardedQueue will be waiting
|
||||||
try {
|
try {
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
//now we execute second thread which will put number to guardedQueue and notify first thread that it could get
|
// now we execute second thread which will put number to guardedQueue
|
||||||
|
// and notify first thread that it could get
|
||||||
executorService.execute(() -> {
|
executorService.execute(() -> {
|
||||||
guardedQueue.put(20);
|
guardedQueue.put(20);
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,16 @@
|
|||||||
|
|
||||||
package com.iluwatar.guarded.suspension;
|
package com.iluwatar.guarded.suspension;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guarded Queue is an implementation for Guarded Suspension Pattern
|
* Guarded Queue is an implementation for Guarded Suspension Pattern Guarded suspension pattern is
|
||||||
* Guarded suspension pattern is used to handle a situation when you want to execute a method
|
* used to handle a situation when you want to execute a method on an object which is not in a
|
||||||
* on an object which is not in a proper state.
|
* proper state.
|
||||||
|
*
|
||||||
* @see <a href="http://java-design-patterns.com/patterns/guarded-suspension/">http://java-design-patterns.com/patterns/guarded-suspension/</a>
|
* @see <a href="http://java-design-patterns.com/patterns/guarded-suspension/">http://java-design-patterns.com/patterns/guarded-suspension/</a>
|
||||||
*/
|
*/
|
||||||
public class GuardedQueue {
|
public class GuardedQueue {
|
||||||
@ -44,6 +44,8 @@ public class GuardedQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get the last element of the queue is exists.
|
||||||
|
*
|
||||||
* @return last element of a queue if queue is not empty
|
* @return last element of a queue if queue is not empty
|
||||||
*/
|
*/
|
||||||
public synchronized Integer get() {
|
public synchronized Integer get() {
|
||||||
@ -60,6 +62,8 @@ public class GuardedQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Put a value in the queue.
|
||||||
|
*
|
||||||
* @param e number which we want to put to our queue
|
* @param e number which we want to put to our queue
|
||||||
*/
|
*/
|
||||||
public synchronized void put(Integer e) {
|
public synchronized void put(Integer e) {
|
||||||
|
@ -23,42 +23,35 @@
|
|||||||
|
|
||||||
package com.iluwatar.halfsynchalfasync;
|
package com.iluwatar.halfsynchalfasync;
|
||||||
|
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This application demonstrates Half-Sync/Half-Async pattern. Key parts of the pattern are {@link
|
||||||
|
* AsyncTask} and {@link AsynchronousService}.
|
||||||
*
|
*
|
||||||
* This application demonstrates Half-Sync/Half-Async pattern. Key parts of the pattern are
|
* <p><i>PROBLEM</i> <br>
|
||||||
* {@link AsyncTask} and {@link AsynchronousService}.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <i>PROBLEM</i> <br>
|
|
||||||
* A concurrent system have a mixture of short duration, mid duration and long duration tasks. Mid
|
* A concurrent system have a mixture of short duration, mid duration and long duration tasks. Mid
|
||||||
* or long duration tasks should be performed asynchronously to meet quality of service
|
* or long duration tasks should be performed asynchronously to meet quality of service
|
||||||
* requirements.
|
* requirements.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p><i>INTENT</i> <br>
|
||||||
* <i>INTENT</i> <br>
|
|
||||||
* The intent of this pattern is to separate the the synchronous and asynchronous processing in the
|
* The intent of this pattern is to separate the the synchronous and asynchronous processing in the
|
||||||
* concurrent application by introducing two intercommunicating layers - one for sync and one for
|
* concurrent application by introducing two intercommunicating layers - one for sync and one for
|
||||||
* async. This simplifies the programming without unduly affecting the performance.
|
* async. This simplifies the programming without unduly affecting the performance.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p><i>APPLICABILITY</i> <br>
|
||||||
* <i>APPLICABILITY</i> <br>
|
* UNIX network subsystems - In operating systems network operations are carried out asynchronously
|
||||||
* UNIX network subsystems - In operating systems network operations are carried out
|
* with help of hardware level interrupts.<br> CORBA - At the asynchronous layer one thread is
|
||||||
* asynchronously with help of hardware level interrupts.<br>
|
* associated with each socket that is connected to the client. Thread blocks waiting for CORBA
|
||||||
* CORBA - At the asynchronous layer one thread is associated with each socket that is connected
|
* requests from the client. On receiving request it is inserted in the queuing layer which is then
|
||||||
* to the client. Thread blocks waiting for CORBA requests from the client. On receiving request it
|
* picked up by synchronous layer which processes the request and sends response back to the
|
||||||
* is inserted in the queuing layer which is then picked up by synchronous layer which processes the
|
* client.<br> Android AsyncTask framework - Framework provides a way to execute long running
|
||||||
* request and sends response back to the client.<br>
|
* blocking calls, such as downloading a file, in background threads so that the UI thread remains
|
||||||
* Android AsyncTask framework - Framework provides a way to execute long running blocking
|
* free to respond to user inputs.<br>
|
||||||
* calls, such as downloading a file, in background threads so that the UI thread remains free to
|
|
||||||
* respond to user inputs.<br>
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p><i>IMPLEMENTATION</i> <br>
|
||||||
* <i>IMPLEMENTATION</i> <br>
|
|
||||||
* The main method creates an asynchronous service which does not block the main thread while the
|
* The main method creates an asynchronous service which does not block the main thread while the
|
||||||
* task is being performed. The main thread continues its work which is similar to Async Method
|
* task is being performed. The main thread continues its work which is similar to Async Method
|
||||||
* Invocation pattern. The difference between them is that there is a queuing layer between
|
* Invocation pattern. The difference between them is that there is a queuing layer between
|
||||||
@ -66,14 +59,13 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
* between both layers. Such as Priority Queue can be used as queuing layer to prioritize the way
|
* between both layers. Such as Priority Queue can be used as queuing layer to prioritize the way
|
||||||
* tasks are executed. Our implementation is just one simple way of implementing this pattern, there
|
* tasks are executed. Our implementation is just one simple way of implementing this pattern, there
|
||||||
* are many variants possible as described in its applications.
|
* are many variants possible as described in its applications.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point
|
* Program entry point.
|
||||||
*
|
*
|
||||||
* @param args command line args
|
* @param args command line args
|
||||||
*/
|
*/
|
||||||
@ -100,15 +92,13 @@ public class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* ArithmeticSumTask.
|
||||||
* ArithmeticSumTask
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static class ArithmeticSumTask implements AsyncTask<Long> {
|
static class ArithmeticSumTask implements AsyncTask<Long> {
|
||||||
private long n;
|
private long numberOfElements;
|
||||||
|
|
||||||
public ArithmeticSumTask(long n) {
|
public ArithmeticSumTask(long numberOfElements) {
|
||||||
this.n = n;
|
this.numberOfElements = numberOfElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -117,7 +107,7 @@ public class App {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Long call() throws Exception {
|
public Long call() throws Exception {
|
||||||
return ap(n);
|
return ap(numberOfElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -128,7 +118,7 @@ public class App {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onPreCall() {
|
public void onPreCall() {
|
||||||
if (n < 0) {
|
if (numberOfElements < 0) {
|
||||||
throw new IllegalArgumentException("n is less than 0");
|
throw new IllegalArgumentException("n is less than 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,15 +23,14 @@
|
|||||||
|
|
||||||
package com.iluwatar.halfsynchalfasync;
|
package com.iluwatar.halfsynchalfasync;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the asynchronous layer which does not block when a new request arrives. It just passes
|
* This is the asynchronous layer which does not block when a new request arrives. It just passes
|
||||||
@ -63,13 +62,14 @@ public class AsynchronousService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A non-blocking method which performs the task provided in background and returns immediately.
|
* A non-blocking method which performs the task provided in background and returns immediately.
|
||||||
* <p>
|
*
|
||||||
* On successful completion of task the result is posted back using callback method
|
* <p>On successful completion of task the result is posted back using callback method {@link
|
||||||
* {@link AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally due to
|
* AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally due to some
|
||||||
* some exception then the reason for error is posted back using callback method
|
* exception then the reason for error is posted back using callback method {@link
|
||||||
* {@link AsyncTask#onError(Throwable)}.
|
* AsyncTask#onError(Throwable)}.
|
||||||
* <p>
|
*
|
||||||
* NOTE: The results are posted back in the context of background thread in this implementation.
|
* <p>NOTE: The results are posted back in the context of background thread in this
|
||||||
|
* implementation.
|
||||||
*/
|
*/
|
||||||
public <T> void execute(final AsyncTask<T> task) {
|
public <T> void execute(final AsyncTask<T> task) {
|
||||||
try {
|
try {
|
||||||
|
@ -31,40 +31,35 @@ import com.iluwatar.hexagonal.module.LotteryTestingModule;
|
|||||||
import com.iluwatar.hexagonal.sampledata.SampleData;
|
import com.iluwatar.hexagonal.sampledata.SampleData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Hexagonal Architecture pattern decouples the application core from the services it uses. This
|
||||||
|
* allows the services to be plugged in and the application will run with or without the services.
|
||||||
*
|
*
|
||||||
* Hexagonal Architecture pattern decouples the application core from the
|
* <p>The core logic, or business logic, of an application consists of the algorithms that are
|
||||||
* services it uses. This allows the services to be plugged in and the
|
* essential to its purpose. They implement the use cases that are the heart of the application.
|
||||||
* application will run with or without the services.<p>
|
* When you change them, you change the essence of the application.
|
||||||
*
|
*
|
||||||
* The core logic, or business logic, of an application consists of the
|
* <p>The services are not essential. They can be replaced without changing the purpose of the
|
||||||
* algorithms that are essential to its purpose. They implement the use
|
* application. Examples: database access and other types of storage, user interface components,
|
||||||
* cases that are the heart of the application. When you change them, you
|
* e-mail and other communication components, hardware devices.
|
||||||
* change the essence of the application.<p>
|
|
||||||
*
|
*
|
||||||
* The services are not essential. They can be replaced without changing
|
* <p>This example demonstrates Hexagonal Architecture with a lottery system. The application core
|
||||||
* the purpose of the application. Examples: database access and other
|
* is separate from the services that drive it and from the services it uses.
|
||||||
* types of storage, user interface components, e-mail and other
|
|
||||||
* communication components, hardware devices.<p>
|
|
||||||
*
|
*
|
||||||
* This example demonstrates Hexagonal Architecture with a lottery system.
|
* <p>The primary ports for the application are console interfaces {@link
|
||||||
* The application core is separate from the services that drive it and
|
* com.iluwatar.hexagonal.administration.ConsoleAdministration} through which the lottery round is
|
||||||
* from the services it uses.<p>
|
* initiated and run and {@link com.iluwatar.hexagonal.service.ConsoleLottery} that allows players
|
||||||
*
|
* to submit lottery tickets for the draw.
|
||||||
* The primary ports for the application are console interfaces
|
|
||||||
* {@link com.iluwatar.hexagonal.administration.ConsoleAdministration} through which the lottery round is
|
|
||||||
* initiated and run and {@link com.iluwatar.hexagonal.service.ConsoleLottery} that allows players to
|
|
||||||
* submit lottery tickets for the draw.<p>
|
|
||||||
*
|
|
||||||
* The secondary ports that application core uses are {@link com.iluwatar.hexagonal.banking.WireTransfers}
|
|
||||||
* which is a banking service, {@link com.iluwatar.hexagonal.eventlog.LotteryEventLog} that delivers
|
|
||||||
* eventlog as lottery events occur and {@link com.iluwatar.hexagonal.database.LotteryTicketRepository}
|
|
||||||
* that is the storage for the lottery tickets.
|
|
||||||
*
|
*
|
||||||
|
* <p>The secondary ports that application core uses are{@link
|
||||||
|
* com.iluwatar.hexagonal.banking.WireTransfers} which is a banking service, {@link
|
||||||
|
* com.iluwatar.hexagonal.eventlog.LotteryEventLog} that delivers eventlog as lottery events occur
|
||||||
|
* and {@link com.iluwatar.hexagonal.database.LotteryTicketRepository} that is the storage for the
|
||||||
|
* lottery tickets.
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point
|
* Program entry point.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
@ -30,20 +30,19 @@ import com.iluwatar.hexagonal.domain.LotteryService;
|
|||||||
import com.iluwatar.hexagonal.module.LotteryModule;
|
import com.iluwatar.hexagonal.module.LotteryModule;
|
||||||
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
||||||
import com.iluwatar.hexagonal.sampledata.SampleData;
|
import com.iluwatar.hexagonal.sampledata.SampleData;
|
||||||
|
import java.util.Scanner;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console interface for lottery administration
|
* Console interface for lottery administration.
|
||||||
*/
|
*/
|
||||||
public class ConsoleAdministration {
|
public class ConsoleAdministration {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleAdministration.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleAdministration.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point
|
* Program entry point.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
MongoConnectionPropertiesLoader.load();
|
MongoConnectionPropertiesLoader.load();
|
||||||
@ -51,7 +50,8 @@ public class ConsoleAdministration {
|
|||||||
LotteryAdministration administration = injector.getInstance(LotteryAdministration.class);
|
LotteryAdministration administration = injector.getInstance(LotteryAdministration.class);
|
||||||
LotteryService service = injector.getInstance(LotteryService.class);
|
LotteryService service = injector.getInstance(LotteryService.class);
|
||||||
SampleData.submitTickets(service, 20);
|
SampleData.submitTickets(service, 20);
|
||||||
ConsoleAdministrationSrv consoleAdministration = new ConsoleAdministrationSrvImpl(administration, LOGGER);
|
ConsoleAdministrationSrv consoleAdministration =
|
||||||
|
new ConsoleAdministrationSrvImpl(administration, LOGGER);
|
||||||
try (Scanner scanner = new Scanner(System.in)) {
|
try (Scanner scanner = new Scanner(System.in)) {
|
||||||
boolean exit = false;
|
boolean exit = false;
|
||||||
while (!exit) {
|
while (!exit) {
|
||||||
|
@ -24,22 +24,22 @@
|
|||||||
package com.iluwatar.hexagonal.administration;
|
package com.iluwatar.hexagonal.administration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console interface for lottery administration
|
* Console interface for lottery administration.
|
||||||
*/
|
*/
|
||||||
public interface ConsoleAdministrationSrv {
|
public interface ConsoleAdministrationSrv {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all submitted tickets
|
* Get all submitted tickets.
|
||||||
*/
|
*/
|
||||||
void getAllSubmittedTickets();
|
void getAllSubmittedTickets();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw lottery numbers
|
* Draw lottery numbers.
|
||||||
*/
|
*/
|
||||||
void performLottery();
|
void performLottery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin new lottery round
|
* Begin new lottery round.
|
||||||
*/
|
*/
|
||||||
void resetLottery();
|
void resetLottery();
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console implementation for lottery administration
|
* Console implementation for lottery administration.
|
||||||
*/
|
*/
|
||||||
public class ConsoleAdministrationSrvImpl implements ConsoleAdministrationSrv {
|
public class ConsoleAdministrationSrvImpl implements ConsoleAdministrationSrv {
|
||||||
private final LotteryAdministration administration;
|
private final LotteryAdministration administration;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public ConsoleAdministrationSrvImpl(LotteryAdministration administration, Logger logger) {
|
public ConsoleAdministrationSrvImpl(LotteryAdministration administration, Logger logger) {
|
||||||
this.administration = administration;
|
this.administration = administration;
|
||||||
@ -44,7 +44,8 @@ public class ConsoleAdministrationSrvImpl implements ConsoleAdministrationSrv {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getAllSubmittedTickets() {
|
public void getAllSubmittedTickets() {
|
||||||
administration.getAllSubmittedTickets().forEach((k, v) -> logger.info("Key: {}, Value: {}", k, v));
|
administration.getAllSubmittedTickets()
|
||||||
|
.forEach((k, v) -> logger.info("Key: {}, Value: {}", k, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,22 +23,20 @@
|
|||||||
|
|
||||||
package com.iluwatar.hexagonal.banking;
|
package com.iluwatar.hexagonal.banking;
|
||||||
|
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.iluwatar.hexagonal.domain.LotteryConstants;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Banking implementation.
|
||||||
* Banking implementation
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class InMemoryBank implements WireTransfers {
|
public class InMemoryBank implements WireTransfers {
|
||||||
|
|
||||||
private static Map<String, Integer> accounts = new HashMap<>();
|
private static Map<String, Integer> accounts = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
accounts.put(LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_BALANCE);
|
accounts
|
||||||
|
.put(LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -52,10 +50,10 @@ public class InMemoryBank implements WireTransfers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount) {
|
public boolean transferFunds(int amount, String sourceAccount, String destinationAccount) {
|
||||||
if (accounts.getOrDefault(sourceBackAccount, 0) >= amount) {
|
if (accounts.getOrDefault(sourceAccount, 0) >= amount) {
|
||||||
accounts.put(sourceBackAccount, accounts.get(sourceBackAccount) - amount);
|
accounts.put(sourceAccount, accounts.get(sourceAccount) - amount);
|
||||||
accounts.put(destinationBankAccount, accounts.get(destinationBankAccount) + amount);
|
accounts.put(destinationAccount, accounts.get(destinationAccount) + amount);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -27,13 +27,12 @@ import com.mongodb.MongoClient;
|
|||||||
import com.mongodb.client.MongoCollection;
|
import com.mongodb.client.MongoCollection;
|
||||||
import com.mongodb.client.MongoDatabase;
|
import com.mongodb.client.MongoDatabase;
|
||||||
import com.mongodb.client.model.UpdateOptions;
|
import com.mongodb.client.model.UpdateOptions;
|
||||||
import org.bson.Document;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo based banking adapter
|
* Mongo based banking adapter.
|
||||||
*/
|
*/
|
||||||
public class MongoBank implements WireTransfers {
|
public class MongoBank implements WireTransfers {
|
||||||
|
|
||||||
@ -45,28 +44,28 @@ public class MongoBank implements WireTransfers {
|
|||||||
private MongoCollection<Document> accountsCollection;
|
private MongoCollection<Document> accountsCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public MongoBank() {
|
public MongoBank() {
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor accepting parameters
|
* Constructor accepting parameters.
|
||||||
*/
|
*/
|
||||||
public MongoBank(String dbName, String accountsCollectionName) {
|
public MongoBank(String dbName, String accountsCollectionName) {
|
||||||
connect(dbName, accountsCollectionName);
|
connect(dbName, accountsCollectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with default parameters
|
* Connect to database with default parameters.
|
||||||
*/
|
*/
|
||||||
public void connect() {
|
public void connect() {
|
||||||
connect(DEFAULT_DB, DEFAULT_ACCOUNTS_COLLECTION);
|
connect(DEFAULT_DB, DEFAULT_ACCOUNTS_COLLECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with given parameters
|
* Connect to database with given parameters.
|
||||||
*/
|
*/
|
||||||
public void connect(String dbName, String accountsCollectionName) {
|
public void connect(String dbName, String accountsCollectionName) {
|
||||||
if (mongoClient != null) {
|
if (mongoClient != null) {
|
||||||
@ -79,6 +78,8 @@ public class MongoBank implements WireTransfers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get mongo client.
|
||||||
|
*
|
||||||
* @return mongo client
|
* @return mongo client
|
||||||
*/
|
*/
|
||||||
public MongoClient getMongoClient() {
|
public MongoClient getMongoClient() {
|
||||||
@ -86,6 +87,7 @@ public class MongoBank implements WireTransfers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get mongo database.
|
||||||
*
|
*
|
||||||
* @return mongo database
|
* @return mongo database
|
||||||
*/
|
*/
|
||||||
@ -94,6 +96,7 @@ public class MongoBank implements WireTransfers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get accounts collection.
|
||||||
*
|
*
|
||||||
* @return accounts collection
|
* @return accounts collection
|
||||||
*/
|
*/
|
||||||
@ -106,7 +109,8 @@ public class MongoBank implements WireTransfers {
|
|||||||
public void setFunds(String bankAccount, int amount) {
|
public void setFunds(String bankAccount, int amount) {
|
||||||
Document search = new Document("_id", bankAccount);
|
Document search = new Document("_id", bankAccount);
|
||||||
Document update = new Document("_id", bankAccount).append("funds", amount);
|
Document update = new Document("_id", bankAccount).append("funds", amount);
|
||||||
accountsCollection.updateOne(search, new Document("$set", update), new UpdateOptions().upsert(true));
|
accountsCollection
|
||||||
|
.updateOne(search, new Document("$set", update), new UpdateOptions().upsert(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,14 +125,14 @@ public class MongoBank implements WireTransfers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount) {
|
public boolean transferFunds(int amount, String sourceAccount, String destinationAccount) {
|
||||||
int sourceFunds = getFunds(sourceBackAccount);
|
int sourceFunds = getFunds(sourceAccount);
|
||||||
if (sourceFunds < amount) {
|
if (sourceFunds < amount) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
int destFunds = getFunds(destinationBankAccount);
|
int destFunds = getFunds(destinationAccount);
|
||||||
setFunds(sourceBackAccount, sourceFunds - amount);
|
setFunds(sourceAccount, sourceFunds - amount);
|
||||||
setFunds(destinationBankAccount, destFunds + amount);
|
setFunds(destinationAccount, destFunds + amount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,24 +24,22 @@
|
|||||||
package com.iluwatar.hexagonal.banking;
|
package com.iluwatar.hexagonal.banking;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Interface to bank accounts.
|
* Interface to bank accounts.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface WireTransfers {
|
public interface WireTransfers {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set amount of funds for bank account
|
* Set amount of funds for bank account.
|
||||||
*/
|
*/
|
||||||
void setFunds(String bankAccount, int amount);
|
void setFunds(String bankAccount, int amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get amount of funds for bank account
|
* Get amount of funds for bank account.
|
||||||
*/
|
*/
|
||||||
int getFunds(String bankAccount);
|
int getFunds(String bankAccount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer funds from one bank account to another
|
* Transfer funds from one bank account to another.
|
||||||
*/
|
*/
|
||||||
boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount);
|
boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount);
|
||||||
|
|
||||||
|
@ -23,17 +23,14 @@
|
|||||||
|
|
||||||
package com.iluwatar.hexagonal.database;
|
package com.iluwatar.hexagonal.database;
|
||||||
|
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
|
||||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Mock database for lottery tickets.
|
* Mock database for lottery tickets.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class InMemoryTicketRepository implements LotteryTicketRepository {
|
public class InMemoryTicketRepository implements LotteryTicketRepository {
|
||||||
|
|
||||||
|
@ -23,36 +23,33 @@
|
|||||||
|
|
||||||
package com.iluwatar.hexagonal.database;
|
package com.iluwatar.hexagonal.database;
|
||||||
|
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
|
||||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Interface for accessing lottery tickets in database.
|
* Interface for accessing lottery tickets in database.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface LotteryTicketRepository {
|
public interface LotteryTicketRepository {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find lottery ticket by id
|
* Find lottery ticket by id.
|
||||||
*/
|
*/
|
||||||
Optional<LotteryTicket> findById(LotteryTicketId id);
|
Optional<LotteryTicket> findById(LotteryTicketId id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save lottery ticket
|
* Save lottery ticket.
|
||||||
*/
|
*/
|
||||||
Optional<LotteryTicketId> save(LotteryTicket ticket);
|
Optional<LotteryTicketId> save(LotteryTicket ticket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all lottery tickets
|
* Get all lottery tickets.
|
||||||
*/
|
*/
|
||||||
Map<LotteryTicketId, LotteryTicket> findAll();
|
Map<LotteryTicketId, LotteryTicket> findAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all lottery tickets
|
* Delete all lottery tickets.
|
||||||
*/
|
*/
|
||||||
void deleteAll();
|
void deleteAll();
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@ import com.iluwatar.hexagonal.domain.PlayerDetails;
|
|||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.client.MongoCollection;
|
import com.mongodb.client.MongoCollection;
|
||||||
import com.mongodb.client.MongoDatabase;
|
import com.mongodb.client.MongoDatabase;
|
||||||
import org.bson.Document;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -40,9 +38,10 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo lottery ticket database
|
* Mongo lottery ticket database.
|
||||||
*/
|
*/
|
||||||
public class MongoTicketRepository implements LotteryTicketRepository {
|
public class MongoTicketRepository implements LotteryTicketRepository {
|
||||||
|
|
||||||
@ -56,14 +55,14 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
private MongoCollection<Document> countersCollection;
|
private MongoCollection<Document> countersCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public MongoTicketRepository() {
|
public MongoTicketRepository() {
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor accepting parameters
|
* Constructor accepting parameters.
|
||||||
*/
|
*/
|
||||||
public MongoTicketRepository(String dbName, String ticketsCollectionName,
|
public MongoTicketRepository(String dbName, String ticketsCollectionName,
|
||||||
String countersCollectionName) {
|
String countersCollectionName) {
|
||||||
@ -71,14 +70,14 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with default parameters
|
* Connect to database with default parameters.
|
||||||
*/
|
*/
|
||||||
public void connect() {
|
public void connect() {
|
||||||
connect(DEFAULT_DB, DEFAULT_TICKETS_COLLECTION, DEFAULT_COUNTERS_COLLECTION);
|
connect(DEFAULT_DB, DEFAULT_TICKETS_COLLECTION, DEFAULT_COUNTERS_COLLECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with given parameters
|
* Connect to database with given parameters.
|
||||||
*/
|
*/
|
||||||
public void connect(String dbName, String ticketsCollectionName,
|
public void connect(String dbName, String ticketsCollectionName,
|
||||||
String countersCollectionName) {
|
String countersCollectionName) {
|
||||||
@ -101,6 +100,8 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get next ticket id.
|
||||||
|
*
|
||||||
* @return next ticket id
|
* @return next ticket id
|
||||||
*/
|
*/
|
||||||
public int getNextId() {
|
public int getNextId() {
|
||||||
@ -112,6 +113,7 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get tickets collection.
|
||||||
*
|
*
|
||||||
* @return tickets collection
|
* @return tickets collection
|
||||||
*/
|
*/
|
||||||
@ -120,6 +122,7 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get counters collection.
|
||||||
*
|
*
|
||||||
* @return counters collection
|
* @return counters collection
|
||||||
*/
|
*/
|
||||||
@ -155,7 +158,7 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
public Map<LotteryTicketId, LotteryTicket> findAll() {
|
public Map<LotteryTicketId, LotteryTicket> findAll() {
|
||||||
Map<LotteryTicketId, LotteryTicket> map = new HashMap<>();
|
Map<LotteryTicketId, LotteryTicket> map = new HashMap<>();
|
||||||
List<Document> docs = ticketsCollection.find(new Document()).into(new ArrayList<>());
|
List<Document> docs = ticketsCollection.find(new Document()).into(new ArrayList<>());
|
||||||
for (Document doc: docs) {
|
for (Document doc : docs) {
|
||||||
LotteryTicket lotteryTicket = docToTicket(doc);
|
LotteryTicket lotteryTicket = docToTicket(doc);
|
||||||
map.put(lotteryTicket.getId(), lotteryTicket);
|
map.put(lotteryTicket.getId(), lotteryTicket);
|
||||||
}
|
}
|
||||||
@ -174,6 +177,7 @@ public class MongoTicketRepository implements LotteryTicketRepository {
|
|||||||
.map(Integer::parseInt)
|
.map(Integer::parseInt)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
LotteryNumbers lotteryNumbers = LotteryNumbers.create(numbers);
|
LotteryNumbers lotteryNumbers = LotteryNumbers.create(numbers);
|
||||||
return new LotteryTicket(new LotteryTicketId(doc.getInteger("ticketId")), playerDetails, lotteryNumbers);
|
return new LotteryTicket(new LotteryTicketId(doc
|
||||||
|
.getInteger("ticketId")), playerDetails, lotteryNumbers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,10 @@ import com.google.inject.Inject;
|
|||||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||||
import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Lottery administration implementation.
|
||||||
* Lottery administration implementation
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryAdministration {
|
public class LotteryAdministration {
|
||||||
|
|
||||||
@ -42,7 +39,7 @@ public class LotteryAdministration {
|
|||||||
private final WireTransfers wireTransfers;
|
private final WireTransfers wireTransfers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications,
|
public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications,
|
||||||
@ -53,14 +50,14 @@ public class LotteryAdministration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the lottery tickets submitted for lottery
|
* Get all the lottery tickets submitted for lottery.
|
||||||
*/
|
*/
|
||||||
public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {
|
public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {
|
||||||
return repository.findAll();
|
return repository.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw lottery numbers
|
* Draw lottery numbers.
|
||||||
*/
|
*/
|
||||||
public LotteryNumbers performLottery() {
|
public LotteryNumbers performLottery() {
|
||||||
LotteryNumbers numbers = LotteryNumbers.createRandom();
|
LotteryNumbers numbers = LotteryNumbers.createRandom();
|
||||||
@ -69,11 +66,14 @@ public class LotteryAdministration {
|
|||||||
LotteryTicketCheckResult result = LotteryUtils.checkTicketForPrize(repository, id, numbers);
|
LotteryTicketCheckResult result = LotteryUtils.checkTicketForPrize(repository, id, numbers);
|
||||||
if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) {
|
if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) {
|
||||||
boolean transferred = wireTransfers.transferFunds(LotteryConstants.PRIZE_AMOUNT,
|
boolean transferred = wireTransfers.transferFunds(LotteryConstants.PRIZE_AMOUNT,
|
||||||
LotteryConstants.SERVICE_BANK_ACCOUNT, tickets.get(id).getPlayerDetails().getBankAccount());
|
LotteryConstants.SERVICE_BANK_ACCOUNT, tickets.get(id).getPlayerDetails()
|
||||||
|
.getBankAccount());
|
||||||
if (transferred) {
|
if (transferred) {
|
||||||
notifications.ticketWon(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
notifications
|
||||||
|
.ticketWon(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
||||||
} else {
|
} else {
|
||||||
notifications.prizeError(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
notifications
|
||||||
|
.prizeError(tickets.get(id).getPlayerDetails(), LotteryConstants.PRIZE_AMOUNT);
|
||||||
}
|
}
|
||||||
} else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) {
|
} else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) {
|
||||||
notifications.ticketDidNotWin(tickets.get(id).getPlayerDetails());
|
notifications.ticketDidNotWin(tickets.get(id).getPlayerDetails());
|
||||||
@ -83,7 +83,7 @@ public class LotteryAdministration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin new lottery round
|
* Begin new lottery round.
|
||||||
*/
|
*/
|
||||||
public void resetLottery() {
|
public void resetLottery() {
|
||||||
repository.deleteAll();
|
repository.deleteAll();
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Lottery domain constants.
|
||||||
* Lottery domain constants
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryConstants {
|
public class LotteryConstants {
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.PrimitiveIterator;
|
import java.util.PrimitiveIterator;
|
||||||
@ -32,10 +31,8 @@ import java.util.Random;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must
|
||||||
* Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must be unique and
|
* be unique and between 1 and 20.
|
||||||
* between 1 and 20.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryNumbers {
|
public class LotteryNumbers {
|
||||||
|
|
||||||
@ -62,6 +59,8 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Creates a random lottery number.
|
||||||
|
*
|
||||||
* @return random LotteryNumbers
|
* @return random LotteryNumbers
|
||||||
*/
|
*/
|
||||||
public static LotteryNumbers createRandom() {
|
public static LotteryNumbers createRandom() {
|
||||||
@ -69,6 +68,8 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Creates lottery number from given set of numbers.
|
||||||
|
*
|
||||||
* @return given LotteryNumbers
|
* @return given LotteryNumbers
|
||||||
*/
|
*/
|
||||||
public static LotteryNumbers create(Set<Integer> givenNumbers) {
|
public static LotteryNumbers create(Set<Integer> givenNumbers) {
|
||||||
@ -76,6 +77,8 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get numbers.
|
||||||
|
*
|
||||||
* @return lottery numbers
|
* @return lottery numbers
|
||||||
*/
|
*/
|
||||||
public Set<Integer> getNumbers() {
|
public Set<Integer> getNumbers() {
|
||||||
@ -83,6 +86,8 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get numbers as string.
|
||||||
|
*
|
||||||
* @return numbers as comma separated string
|
* @return numbers as comma separated string
|
||||||
*/
|
*/
|
||||||
public String getNumbersAsString() {
|
public String getNumbersAsString() {
|
||||||
@ -107,16 +112,15 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Helper class for generating random numbers.
|
* Helper class for generating random numbers.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private static class RandomNumberGenerator {
|
private static class RandomNumberGenerator {
|
||||||
|
|
||||||
private PrimitiveIterator.OfInt randomIterator;
|
private PrimitiveIterator.OfInt randomIterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new random number generator that generates random numbers in the range [min, max]
|
* Initialize a new random number generator that generates random numbers in the range [min,
|
||||||
|
* max].
|
||||||
*
|
*
|
||||||
* @param min the min value (inclusive)
|
* @param min the min value (inclusive)
|
||||||
* @param max the max value (inclusive)
|
* @param max the max value (inclusive)
|
||||||
@ -126,6 +130,8 @@ public class LotteryNumbers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Gets next random integer in [min, max] range.
|
||||||
|
*
|
||||||
* @return a random number in the range (min, max)
|
* @return a random number in the range (min, max)
|
||||||
*/
|
*/
|
||||||
public int nextInt() {
|
public int nextInt() {
|
||||||
|
@ -27,13 +27,10 @@ import com.google.inject.Inject;
|
|||||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||||
import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Implementation for lottery service.
|
||||||
* Implementation for lottery service
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryService {
|
public class LotteryService {
|
||||||
|
|
||||||
@ -42,7 +39,7 @@ public class LotteryService {
|
|||||||
private final WireTransfers wireTransfers;
|
private final WireTransfers wireTransfers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications,
|
public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications,
|
||||||
@ -53,7 +50,7 @@ public class LotteryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit lottery ticket to participate in the lottery
|
* Submit lottery ticket to participate in the lottery.
|
||||||
*/
|
*/
|
||||||
public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {
|
public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {
|
||||||
boolean result = wireTransfers.transferFunds(LotteryConstants.TICKET_PRIZE,
|
boolean result = wireTransfers.transferFunds(LotteryConstants.TICKET_PRIZE,
|
||||||
@ -70,9 +67,12 @@ public class LotteryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if lottery ticket has won
|
* Check if lottery ticket has won.
|
||||||
*/
|
*/
|
||||||
public LotteryTicketCheckResult checkTicketForPrize(LotteryTicketId id, LotteryNumbers winningNumbers) {
|
public LotteryTicketCheckResult checkTicketForPrize(
|
||||||
|
LotteryTicketId id,
|
||||||
|
LotteryNumbers winningNumbers
|
||||||
|
) {
|
||||||
return LotteryUtils.checkTicketForPrize(repository, id, winningNumbers);
|
return LotteryUtils.checkTicketForPrize(repository, id, winningNumbers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Immutable value object representing lottery ticket.
|
* Immutable value object representing lottery ticket.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryTicket {
|
public class LotteryTicket {
|
||||||
|
|
||||||
@ -44,6 +42,8 @@ public class LotteryTicket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get player details.
|
||||||
|
*
|
||||||
* @return player details
|
* @return player details
|
||||||
*/
|
*/
|
||||||
public PlayerDetails getPlayerDetails() {
|
public PlayerDetails getPlayerDetails() {
|
||||||
@ -51,6 +51,8 @@ public class LotteryTicket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get lottery numbers.
|
||||||
|
*
|
||||||
* @return lottery numbers
|
* @return lottery numbers
|
||||||
*/
|
*/
|
||||||
public LotteryNumbers getNumbers() {
|
public LotteryNumbers getNumbers() {
|
||||||
@ -58,6 +60,8 @@ public class LotteryTicket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get ticket id.
|
||||||
|
*
|
||||||
* @return id
|
* @return id
|
||||||
*/
|
*/
|
||||||
public LotteryTicketId getId() {
|
public LotteryTicketId getId() {
|
||||||
@ -65,7 +69,7 @@ public class LotteryTicket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set id
|
* Set ticket id.
|
||||||
*/
|
*/
|
||||||
public void setId(LotteryTicketId id) {
|
public void setId(LotteryTicketId id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -24,16 +24,18 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Represents lottery ticket check result.
|
* Represents lottery ticket check result.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LotteryTicketCheckResult {
|
public class LotteryTicketCheckResult {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumeration of Type of Outcomes of a Lottery
|
* Enumeration of Type of Outcomes of a Lottery.
|
||||||
*/
|
*/
|
||||||
public enum CheckResult { WIN_PRIZE, NO_PRIZE, TICKET_NOT_SUBMITTED }
|
public enum CheckResult {
|
||||||
|
WIN_PRIZE,
|
||||||
|
NO_PRIZE,
|
||||||
|
TICKET_NOT_SUBMITTED
|
||||||
|
}
|
||||||
|
|
||||||
private final CheckResult checkResult;
|
private final CheckResult checkResult;
|
||||||
private final int prizeAmount;
|
private final int prizeAmount;
|
||||||
@ -55,6 +57,8 @@ public class LotteryTicketCheckResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get result.
|
||||||
|
*
|
||||||
* @return check result
|
* @return check result
|
||||||
*/
|
*/
|
||||||
public CheckResult getResult() {
|
public CheckResult getResult() {
|
||||||
@ -62,6 +66,8 @@ public class LotteryTicketCheckResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get prize amount.
|
||||||
|
*
|
||||||
* @return prize amount
|
* @return prize amount
|
||||||
*/
|
*/
|
||||||
public int getPrizeAmount() {
|
public int getPrizeAmount() {
|
||||||
|
@ -26,7 +26,7 @@ package com.iluwatar.hexagonal.domain;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lottery ticked id
|
* Lottery ticked id.
|
||||||
*/
|
*/
|
||||||
public class LotteryTicketId {
|
public class LotteryTicketId {
|
||||||
|
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lottery utilities
|
* Lottery utilities.
|
||||||
*/
|
*/
|
||||||
public class LotteryUtils {
|
public class LotteryUtils {
|
||||||
|
|
||||||
@ -36,19 +36,22 @@ public class LotteryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if lottery ticket has won
|
* Checks if lottery ticket has won.
|
||||||
*/
|
*/
|
||||||
public static LotteryTicketCheckResult checkTicketForPrize(LotteryTicketRepository repository, LotteryTicketId id,
|
public static LotteryTicketCheckResult checkTicketForPrize(
|
||||||
LotteryNumbers winningNumbers) {
|
LotteryTicketRepository repository,
|
||||||
|
LotteryTicketId id,
|
||||||
|
LotteryNumbers winningNumbers
|
||||||
|
) {
|
||||||
Optional<LotteryTicket> optional = repository.findById(id);
|
Optional<LotteryTicket> optional = repository.findById(id);
|
||||||
if (optional.isPresent()) {
|
if (optional.isPresent()) {
|
||||||
if (optional.get().getNumbers().equals(winningNumbers)) {
|
if (optional.get().getNumbers().equals(winningNumbers)) {
|
||||||
return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.WIN_PRIZE, 1000);
|
return new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 1000);
|
||||||
} else {
|
} else {
|
||||||
return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.NO_PRIZE);
|
return new LotteryTicketCheckResult(CheckResult.NO_PRIZE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new LotteryTicketCheckResult(LotteryTicketCheckResult.CheckResult.TICKET_NOT_SUBMITTED);
|
return new LotteryTicketCheckResult(CheckResult.TICKET_NOT_SUBMITTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.hexagonal.domain;
|
package com.iluwatar.hexagonal.domain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Immutable value object containing lottery player details.
|
* Immutable value object containing lottery player details.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class PlayerDetails {
|
public class PlayerDetails {
|
||||||
|
|
||||||
@ -44,6 +42,8 @@ public class PlayerDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get email.
|
||||||
|
*
|
||||||
* @return email
|
* @return email
|
||||||
*/
|
*/
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
@ -51,6 +51,8 @@ public class PlayerDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get back account number.
|
||||||
|
*
|
||||||
* @return bank account number
|
* @return bank account number
|
||||||
*/
|
*/
|
||||||
public String getBankAccount() {
|
public String getBankAccount() {
|
||||||
@ -58,6 +60,8 @@ public class PlayerDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get phone number.
|
||||||
|
*
|
||||||
* @return phone number
|
* @return phone number
|
||||||
*/
|
*/
|
||||||
public String getPhoneNumber() {
|
public String getPhoneNumber() {
|
||||||
|
@ -26,34 +26,32 @@ package com.iluwatar.hexagonal.eventlog;
|
|||||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Event log for lottery events.
|
||||||
* Event log for lottery events
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface LotteryEventLog {
|
public interface LotteryEventLog {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lottery ticket submitted
|
* lottery ticket submitted.
|
||||||
*/
|
*/
|
||||||
void ticketSubmitted(PlayerDetails details);
|
void ticketSubmitted(PlayerDetails details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* error submitting lottery ticket
|
* error submitting lottery ticket.
|
||||||
*/
|
*/
|
||||||
void ticketSubmitError(PlayerDetails details);
|
void ticketSubmitError(PlayerDetails details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lottery ticket did not win
|
* lottery ticket did not win.
|
||||||
*/
|
*/
|
||||||
void ticketDidNotWin(PlayerDetails details);
|
void ticketDidNotWin(PlayerDetails details);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lottery ticket won
|
* lottery ticket won.
|
||||||
*/
|
*/
|
||||||
void ticketWon(PlayerDetails details, int prizeAmount);
|
void ticketWon(PlayerDetails details, int prizeAmount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* error paying the prize
|
* error paying the prize.
|
||||||
*/
|
*/
|
||||||
void prizeError(PlayerDetails details, int prizeAmount);
|
void prizeError(PlayerDetails details, int prizeAmount);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import com.mongodb.client.MongoDatabase;
|
|||||||
import org.bson.Document;
|
import org.bson.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo based event log
|
* Mongo based event log.
|
||||||
*/
|
*/
|
||||||
public class MongoEventLog implements LotteryEventLog {
|
public class MongoEventLog implements LotteryEventLog {
|
||||||
|
|
||||||
@ -44,28 +44,28 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
private StdOutEventLog stdOutEventLog = new StdOutEventLog();
|
private StdOutEventLog stdOutEventLog = new StdOutEventLog();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public MongoEventLog() {
|
public MongoEventLog() {
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor accepting parameters
|
* Constructor accepting parameters.
|
||||||
*/
|
*/
|
||||||
public MongoEventLog(String dbName, String eventsCollectionName) {
|
public MongoEventLog(String dbName, String eventsCollectionName) {
|
||||||
connect(dbName, eventsCollectionName);
|
connect(dbName, eventsCollectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with default parameters
|
* Connect to database with default parameters.
|
||||||
*/
|
*/
|
||||||
public void connect() {
|
public void connect() {
|
||||||
connect(DEFAULT_DB, DEFAULT_EVENTS_COLLECTION);
|
connect(DEFAULT_DB, DEFAULT_EVENTS_COLLECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to database with given parameters
|
* Connect to database with given parameters.
|
||||||
*/
|
*/
|
||||||
public void connect(String dbName, String eventsCollectionName) {
|
public void connect(String dbName, String eventsCollectionName) {
|
||||||
if (mongoClient != null) {
|
if (mongoClient != null) {
|
||||||
@ -78,6 +78,8 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get mongo client.
|
||||||
|
*
|
||||||
* @return mongo client
|
* @return mongo client
|
||||||
*/
|
*/
|
||||||
public MongoClient getMongoClient() {
|
public MongoClient getMongoClient() {
|
||||||
@ -85,6 +87,7 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get mongo database.
|
||||||
*
|
*
|
||||||
* @return mongo database
|
* @return mongo database
|
||||||
*/
|
*/
|
||||||
@ -93,8 +96,9 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get events collection.
|
||||||
*
|
*
|
||||||
* @return accounts collection
|
* @return events collection
|
||||||
*/
|
*/
|
||||||
public MongoCollection<Document> getEventsCollection() {
|
public MongoCollection<Document> getEventsCollection() {
|
||||||
return eventsCollection;
|
return eventsCollection;
|
||||||
@ -106,7 +110,8 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
Document document = new Document("email", details.getEmail());
|
Document document = new Document("email", details.getEmail());
|
||||||
document.put("phone", details.getPhoneNumber());
|
document.put("phone", details.getPhoneNumber());
|
||||||
document.put("bank", details.getBankAccount());
|
document.put("bank", details.getBankAccount());
|
||||||
document.put("message", "Lottery ticket was submitted and bank account was charged for 3 credits.");
|
document
|
||||||
|
.put("message", "Lottery ticket was submitted and bank account was charged for 3 credits.");
|
||||||
eventsCollection.insertOne(document);
|
eventsCollection.insertOne(document);
|
||||||
stdOutEventLog.ticketSubmitted(details);
|
stdOutEventLog.ticketSubmitted(details);
|
||||||
}
|
}
|
||||||
@ -136,7 +141,8 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
Document document = new Document("email", details.getEmail());
|
Document document = new Document("email", details.getEmail());
|
||||||
document.put("phone", details.getPhoneNumber());
|
document.put("phone", details.getPhoneNumber());
|
||||||
document.put("bank", details.getBankAccount());
|
document.put("bank", details.getBankAccount());
|
||||||
document.put("message", String.format("Lottery ticket won! The bank account was deposited with %d credits.",
|
document.put("message", String
|
||||||
|
.format("Lottery ticket won! The bank account was deposited with %d credits.",
|
||||||
prizeAmount));
|
prizeAmount));
|
||||||
eventsCollection.insertOne(document);
|
eventsCollection.insertOne(document);
|
||||||
stdOutEventLog.ticketWon(details, prizeAmount);
|
stdOutEventLog.ticketWon(details, prizeAmount);
|
||||||
@ -147,7 +153,8 @@ public class MongoEventLog implements LotteryEventLog {
|
|||||||
Document document = new Document("email", details.getEmail());
|
Document document = new Document("email", details.getEmail());
|
||||||
document.put("phone", details.getPhoneNumber());
|
document.put("phone", details.getPhoneNumber());
|
||||||
document.put("bank", details.getBankAccount());
|
document.put("bank", details.getBankAccount());
|
||||||
document.put("message", String.format("Lottery ticket won! Unfortunately the bank credit transfer of %d failed.",
|
document.put("message", String
|
||||||
|
.format("Lottery ticket won! Unfortunately the bank credit transfer of %d failed.",
|
||||||
prizeAmount));
|
prizeAmount));
|
||||||
eventsCollection.insertOne(document);
|
eventsCollection.insertOne(document);
|
||||||
stdOutEventLog.prizeError(details, prizeAmount);
|
stdOutEventLog.prizeError(details, prizeAmount);
|
||||||
|
@ -28,7 +28,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard output event log
|
* Standard output event log.
|
||||||
*/
|
*/
|
||||||
public class StdOutEventLog implements LotteryEventLog {
|
public class StdOutEventLog implements LotteryEventLog {
|
||||||
|
|
||||||
@ -42,7 +42,9 @@ public class StdOutEventLog implements LotteryEventLog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ticketDidNotWin(PlayerDetails details) {
|
public void ticketDidNotWin(PlayerDetails details) {
|
||||||
LOGGER.info("Lottery ticket for {} was checked and unfortunately did not win this time.", details.getEmail());
|
LOGGER
|
||||||
|
.info("Lottery ticket for {} was checked and unfortunately did not win this time.", details
|
||||||
|
.getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,13 +55,14 @@ public class StdOutEventLog implements LotteryEventLog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prizeError(PlayerDetails details, int prizeAmount) {
|
public void prizeError(PlayerDetails details, int prizeAmount) {
|
||||||
LOGGER.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of {} failed.",
|
LOGGER
|
||||||
details.getEmail(), prizeAmount);
|
.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of"
|
||||||
|
+ " {} failed.", details.getEmail(), prizeAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ticketSubmitError(PlayerDetails details) {
|
public void ticketSubmitError(PlayerDetails details) {
|
||||||
LOGGER.error("Lottery ticket for {} could not be submitted because the credit transfer of 3 credits failed.",
|
LOGGER.error("Lottery ticket for {} could not be submitted because the credit transfer"
|
||||||
details.getEmail());
|
+ " of 3 credits failed.", details.getEmail());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
|||||||
import com.iluwatar.hexagonal.eventlog.MongoEventLog;
|
import com.iluwatar.hexagonal.eventlog.MongoEventLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module for binding production dependencies
|
* Guice module for binding production dependencies.
|
||||||
*/
|
*/
|
||||||
public class LotteryModule extends AbstractModule {
|
public class LotteryModule extends AbstractModule {
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,7 +32,7 @@ import com.iluwatar.hexagonal.eventlog.LotteryEventLog;
|
|||||||
import com.iluwatar.hexagonal.eventlog.StdOutEventLog;
|
import com.iluwatar.hexagonal.eventlog.StdOutEventLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module for testing dependencies
|
* Guice module for testing dependencies.
|
||||||
*/
|
*/
|
||||||
public class LotteryTestingModule extends AbstractModule {
|
public class LotteryTestingModule extends AbstractModule {
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,7 +27,7 @@ import java.io.FileInputStream;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo connection properties loader
|
* Mongo connection properties loader.
|
||||||
*/
|
*/
|
||||||
public class MongoConnectionPropertiesLoader {
|
public class MongoConnectionPropertiesLoader {
|
||||||
|
|
||||||
@ -35,8 +35,7 @@ public class MongoConnectionPropertiesLoader {
|
|||||||
private static final int DEFAULT_PORT = 27017;
|
private static final int DEFAULT_PORT = 27017;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to load connection properties from file.
|
* Try to load connection properties from file. Fall back to default connection properties.
|
||||||
* Fall back to default connection properties.
|
|
||||||
*/
|
*/
|
||||||
public static void load() {
|
public static void load() {
|
||||||
String host = DEFAULT_HOST;
|
String host = DEFAULT_HOST;
|
||||||
|
@ -30,12 +30,11 @@ import com.iluwatar.hexagonal.domain.LotteryService;
|
|||||||
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||||
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||||
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for creating sample lottery tickets
|
* Utilities for creating sample lottery tickets.
|
||||||
*/
|
*/
|
||||||
public class SampleData {
|
public class SampleData {
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ public class SampleData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts lottery tickets into the database based on the sample data
|
* Inserts lottery tickets into the database based on the sample data.
|
||||||
*/
|
*/
|
||||||
public static void submitTickets(LotteryService lotteryService, int numTickets) {
|
public static void submitTickets(LotteryService lotteryService, int numTickets) {
|
||||||
for (int i = 0; i < numTickets; i++) {
|
for (int i = 0; i < numTickets; i++) {
|
||||||
|
@ -29,25 +29,24 @@ import com.iluwatar.hexagonal.banking.WireTransfers;
|
|||||||
import com.iluwatar.hexagonal.domain.LotteryService;
|
import com.iluwatar.hexagonal.domain.LotteryService;
|
||||||
import com.iluwatar.hexagonal.module.LotteryModule;
|
import com.iluwatar.hexagonal.module.LotteryModule;
|
||||||
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;
|
||||||
|
import java.util.Scanner;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console interface for lottery players
|
* Console interface for lottery players.
|
||||||
*/
|
*/
|
||||||
public class ConsoleLottery {
|
public class ConsoleLottery {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleLottery.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleLottery.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point
|
* Program entry point.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
MongoConnectionPropertiesLoader.load();
|
MongoConnectionPropertiesLoader.load();
|
||||||
Injector injector = Guice.createInjector(new LotteryModule());
|
Injector injector = Guice.createInjector(new LotteryModule());
|
||||||
LotteryService service = injector.getInstance( LotteryService.class);
|
LotteryService service = injector.getInstance(LotteryService.class);
|
||||||
WireTransfers bank = injector.getInstance(WireTransfers.class);
|
WireTransfers bank = injector.getInstance(WireTransfers.class);
|
||||||
try (Scanner scanner = new Scanner(System.in)) {
|
try (Scanner scanner = new Scanner(System.in)) {
|
||||||
boolean exit = false;
|
boolean exit = false;
|
||||||
|
@ -25,30 +25,29 @@ package com.iluwatar.hexagonal.service;
|
|||||||
|
|
||||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||||
import com.iluwatar.hexagonal.domain.LotteryService;
|
import com.iluwatar.hexagonal.domain.LotteryService;
|
||||||
|
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console interface for lottery service
|
* Console interface for lottery service.
|
||||||
*/
|
*/
|
||||||
public interface LotteryConsoleService {
|
public interface LotteryConsoleService {
|
||||||
|
|
||||||
void checkTicket(LotteryService service, Scanner scanner);
|
void checkTicket(LotteryService service, Scanner scanner);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit lottery ticket to participate in the lottery
|
* Submit lottery ticket to participate in the lottery.
|
||||||
*/
|
*/
|
||||||
void submitTicket(LotteryService service, Scanner scanner);
|
void submitTicket(LotteryService service, Scanner scanner);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add funds to lottery account
|
* Add funds to lottery account.
|
||||||
*/
|
*/
|
||||||
void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner);
|
void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recovery funds from lottery account
|
* Recovery funds from lottery account.
|
||||||
*/
|
*/
|
||||||
void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner);
|
void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner);
|
||||||
|
|
||||||
|
@ -24,22 +24,29 @@
|
|||||||
package com.iluwatar.hexagonal.service;
|
package com.iluwatar.hexagonal.service;
|
||||||
|
|
||||||
import com.iluwatar.hexagonal.banking.WireTransfers;
|
import com.iluwatar.hexagonal.banking.WireTransfers;
|
||||||
import com.iluwatar.hexagonal.domain.*;
|
import com.iluwatar.hexagonal.domain.LotteryNumbers;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryService;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicket;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
|
||||||
|
import com.iluwatar.hexagonal.domain.LotteryTicketId;
|
||||||
|
import com.iluwatar.hexagonal.domain.PlayerDetails;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console implementation for lottery console service
|
* Console implementation for lottery console service.
|
||||||
*/
|
*/
|
||||||
public class LotteryConsoleServiceImpl implements LotteryConsoleService {
|
public class LotteryConsoleServiceImpl implements LotteryConsoleService {
|
||||||
|
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public LotteryConsoleServiceImpl(Logger logger) {
|
public LotteryConsoleServiceImpl(Logger logger) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@ -47,79 +54,81 @@ public class LotteryConsoleServiceImpl implements LotteryConsoleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkTicket(LotteryService service, Scanner scanner) {
|
public void checkTicket(LotteryService service, Scanner scanner) {
|
||||||
logger.info( "What is the ID of the lottery ticket?" );
|
logger.info("What is the ID of the lottery ticket?");
|
||||||
String id = readString( scanner );
|
String id = readString(scanner);
|
||||||
logger.info( "Give the 4 comma separated winning numbers?" );
|
logger.info("Give the 4 comma separated winning numbers?");
|
||||||
String numbers = readString( scanner );
|
String numbers = readString(scanner);
|
||||||
try {
|
try {
|
||||||
String[] parts = numbers.split( "," );
|
String[] parts = numbers.split(",");
|
||||||
Set<Integer> winningNumbers = new HashSet<>();
|
Set<Integer> winningNumbers = new HashSet<>();
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
winningNumbers.add( Integer.parseInt( parts[i] ) );
|
winningNumbers.add(Integer.parseInt(parts[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
final LotteryTicketId lotteryTicketId = new LotteryTicketId( Integer.parseInt( id ) );
|
final LotteryTicketId lotteryTicketId = new LotteryTicketId(Integer.parseInt(id));
|
||||||
final LotteryNumbers lotteryNumbers = LotteryNumbers.create( winningNumbers );
|
final LotteryNumbers lotteryNumbers = LotteryNumbers.create(winningNumbers);
|
||||||
LotteryTicketCheckResult result = service.checkTicketForPrize( lotteryTicketId, lotteryNumbers );
|
LotteryTicketCheckResult result =
|
||||||
|
service.checkTicketForPrize(lotteryTicketId, lotteryNumbers);
|
||||||
|
|
||||||
if (result.getResult().equals( LotteryTicketCheckResult.CheckResult.WIN_PRIZE )) {
|
if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) {
|
||||||
logger.info( "Congratulations! The lottery ticket has won!" );
|
logger.info("Congratulations! The lottery ticket has won!");
|
||||||
} else if (result.getResult().equals( LotteryTicketCheckResult.CheckResult.NO_PRIZE )) {
|
} else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) {
|
||||||
logger.info( "Unfortunately the lottery ticket did not win." );
|
logger.info("Unfortunately the lottery ticket did not win.");
|
||||||
} else {
|
} else {
|
||||||
logger.info( "Such lottery ticket has not been submitted." );
|
logger.info("Such lottery ticket has not been submitted.");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info( "Failed checking the lottery ticket - please try again." );
|
logger.info("Failed checking the lottery ticket - please try again.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void submitTicket(LotteryService service, Scanner scanner) {
|
public void submitTicket(LotteryService service, Scanner scanner) {
|
||||||
logger.info( "What is your email address?" );
|
logger.info("What is your email address?");
|
||||||
String email = readString( scanner );
|
String email = readString(scanner);
|
||||||
logger.info( "What is your bank account number?" );
|
logger.info("What is your bank account number?");
|
||||||
String account = readString( scanner );
|
String account = readString(scanner);
|
||||||
logger.info( "What is your phone number?" );
|
logger.info("What is your phone number?");
|
||||||
String phone = readString( scanner );
|
String phone = readString(scanner);
|
||||||
PlayerDetails details = new PlayerDetails( email, account, phone );
|
PlayerDetails details = new PlayerDetails(email, account, phone);
|
||||||
logger.info( "Give 4 comma separated lottery numbers?" );
|
logger.info("Give 4 comma separated lottery numbers?");
|
||||||
String numbers = readString( scanner );
|
String numbers = readString(scanner);
|
||||||
try {
|
try {
|
||||||
String[] parts = numbers.split( "," );
|
String[] parts = numbers.split(",");
|
||||||
Set<Integer> chosen = Arrays.stream(parts).map(Integer::parseInt).collect(Collectors.toSet());
|
Set<Integer> chosen = Arrays.stream(parts).map(Integer::parseInt).collect(Collectors.toSet());
|
||||||
LotteryNumbers lotteryNumbers = LotteryNumbers.create( chosen );
|
LotteryNumbers lotteryNumbers = LotteryNumbers.create(chosen);
|
||||||
LotteryTicket lotteryTicket = new LotteryTicket( new LotteryTicketId(), details, lotteryNumbers );
|
LotteryTicket lotteryTicket =
|
||||||
Optional<LotteryTicketId> id = service.submitTicket( lotteryTicket );
|
new LotteryTicket(new LotteryTicketId(), details, lotteryNumbers);
|
||||||
|
Optional<LotteryTicketId> id = service.submitTicket(lotteryTicket);
|
||||||
if (id.isPresent()) {
|
if (id.isPresent()) {
|
||||||
logger.info( "Submitted lottery ticket with id: {}", id.get() );
|
logger.info("Submitted lottery ticket with id: {}", id.get());
|
||||||
} else {
|
} else {
|
||||||
logger.info( "Failed submitting lottery ticket - please try again." );
|
logger.info("Failed submitting lottery ticket - please try again.");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info( "Failed submitting lottery ticket - please try again." );
|
logger.info("Failed submitting lottery ticket - please try again.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner) {
|
public void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner) {
|
||||||
logger.info( "What is the account number?" );
|
logger.info("What is the account number?");
|
||||||
String account = readString( scanner );
|
String account = readString(scanner);
|
||||||
logger.info( "How many credits do you want to deposit?" );
|
logger.info("How many credits do you want to deposit?");
|
||||||
String amount = readString( scanner );
|
String amount = readString(scanner);
|
||||||
bank.setFunds( account, Integer.parseInt( amount ) );
|
bank.setFunds(account, Integer.parseInt(amount));
|
||||||
logger.info( "The account {} now has {} credits.", account, bank.getFunds( account ) );
|
logger.info("The account {} now has {} credits.", account, bank.getFunds(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner) {
|
public void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner) {
|
||||||
logger.info( "What is the account number?" );
|
logger.info("What is the account number?");
|
||||||
String account = readString( scanner );
|
String account = readString(scanner);
|
||||||
logger.info( "The account {} has {} credits.", account, bank.getFunds( account ) );
|
logger.info("The account {} has {} credits.", account, bank.getFunds(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readString(Scanner scanner) {
|
private String readString(Scanner scanner) {
|
||||||
logger.info( "> " );
|
logger.info("> ");
|
||||||
return scanner.next();
|
return scanner.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user