Skip to content

Commit 626c567

Browse files
committed
Hexagonal pattern: Added Mongo based ticket repository and set production configuration to use that
1 parent a854634 commit 626c567

File tree

11 files changed

+339
-14
lines changed

11 files changed

+339
-14
lines changed

hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static void main(String[] args) {
5454
administartion.getAllSubmittedTickets().forEach((k,v)->System.out.println("Key: " + k + " Value: " + v));
5555
} else if (cmd.equals("2")) {
5656
LotteryNumbers numbers = administartion.performLottery();
57-
System.out.println("The winning numbers: " + numbers);
57+
System.out.println("The winning numbers: " + numbers.getNumbersAsString());
5858
System.out.println("Time to reset the database for next round, eh?");
5959
} else if (cmd.equals("3")) {
6060
administartion.resetLottery();
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.hexagonal.database;
24+
25+
import com.iluwatar.hexagonal.domain.LotteryNumbers;
26+
import com.iluwatar.hexagonal.domain.LotteryTicket;
27+
import com.iluwatar.hexagonal.domain.LotteryTicketId;
28+
import com.iluwatar.hexagonal.domain.PlayerDetails;
29+
import com.mongodb.MongoClient;
30+
import com.mongodb.client.MongoCollection;
31+
import com.mongodb.client.MongoDatabase;
32+
import org.bson.Document;
33+
34+
import java.util.ArrayList;
35+
import java.util.Arrays;
36+
import java.util.HashMap;
37+
import java.util.HashSet;
38+
import java.util.Map;
39+
import java.util.Optional;
40+
41+
/**
42+
* Mongo lottery ticket database
43+
*/
44+
public class MongoTicketRepository implements LotteryTicketRepository {
45+
46+
private static final String DEFAULT_HOST = "localhost";
47+
private static final int DEFAULT_PORT = 27017;
48+
private static final String DEFAULT_DB = "lotteryDB";
49+
private static final String DEFAULT_TICKETS_COLLECTION = "lotteryTickets";
50+
private static final String DEFAULT_COUNTERS_COLLECTION = "counters";
51+
52+
private MongoClient mongoClient;
53+
private MongoDatabase database;
54+
private MongoCollection<Document> ticketsCollection;
55+
private MongoCollection<Document> countersCollection;
56+
57+
/**
58+
* Constructor
59+
*/
60+
public MongoTicketRepository() {
61+
connect();
62+
}
63+
64+
/**
65+
* Constructor accepting parameters
66+
*/
67+
public MongoTicketRepository(String host, int port, String dbName, String ticketsCollectionName,
68+
String countersCollectionName) {
69+
connect(host, port, dbName, ticketsCollectionName, countersCollectionName);
70+
}
71+
72+
/**
73+
* Connect to database with default parameters
74+
*/
75+
public void connect() {
76+
connect(DEFAULT_HOST, DEFAULT_PORT, DEFAULT_DB, DEFAULT_TICKETS_COLLECTION, DEFAULT_COUNTERS_COLLECTION);
77+
}
78+
79+
/**
80+
* Connect to database with given parameters
81+
*/
82+
public void connect(String host, int port, String dbName, String ticketsCollectionName,
83+
String countersCollectionName) {
84+
if (mongoClient != null) {
85+
mongoClient.close();
86+
}
87+
mongoClient = new MongoClient(host , port);
88+
database = mongoClient.getDatabase(dbName);
89+
ticketsCollection = database.getCollection(ticketsCollectionName);
90+
countersCollection = database.getCollection(countersCollectionName);
91+
if (countersCollection.count() <= 0) {
92+
initCounters();
93+
}
94+
}
95+
96+
private void initCounters() {
97+
Document doc = new Document("_id", "ticketId").append("seq", 1);
98+
countersCollection.insertOne(doc);
99+
}
100+
101+
/**
102+
* @return next ticket id
103+
*/
104+
public int getNextId() {
105+
Document find = new Document("_id", "ticketId");
106+
Document increase = new Document("seq", 1);
107+
Document update = new Document("$inc", increase);
108+
Document result = countersCollection.findOneAndUpdate(find, update);
109+
return result.getInteger("seq");
110+
}
111+
112+
/**
113+
* @return mongo client
114+
*/
115+
public MongoClient getMongoClient() {
116+
return mongoClient;
117+
}
118+
119+
/**
120+
*
121+
* @return mongo database
122+
*/
123+
public MongoDatabase getMongoDatabase() {
124+
return database;
125+
}
126+
127+
/**
128+
*
129+
* @return tickets collection
130+
*/
131+
public MongoCollection<Document> getTicketsCollection() {
132+
return ticketsCollection;
133+
}
134+
135+
/**
136+
*
137+
* @return counters collection
138+
*/
139+
public MongoCollection<Document> getCountersCollection() {
140+
return countersCollection;
141+
}
142+
143+
@Override
144+
public Optional<LotteryTicket> findById(LotteryTicketId id) {
145+
Document find = new Document("ticketId", id.getId());
146+
ArrayList<Document> results = ticketsCollection.find(find).limit(1).into(new ArrayList<Document>());
147+
if (results.size() > 0) {
148+
LotteryTicket lotteryTicket = docToTicket(results.get(0));
149+
return Optional.of(lotteryTicket);
150+
} else {
151+
return Optional.empty();
152+
}
153+
}
154+
155+
@Override
156+
public Optional<LotteryTicketId> save(LotteryTicket ticket) {
157+
int ticketId = getNextId();
158+
Document doc = new Document("ticketId", ticketId);
159+
doc.put("email", ticket.getPlayerDetails().getEmail());
160+
doc.put("bank", ticket.getPlayerDetails().getBankAccount());
161+
doc.put("phone", ticket.getPlayerDetails().getPhoneNumber());
162+
doc.put("numbers", ticket.getNumbers().getNumbersAsString());
163+
ticketsCollection.insertOne(doc);
164+
return Optional.of(new LotteryTicketId(ticketId));
165+
}
166+
167+
@Override
168+
public Map<LotteryTicketId, LotteryTicket> findAll() {
169+
Map<LotteryTicketId, LotteryTicket> map = new HashMap<>();
170+
ArrayList<Document> docs = ticketsCollection.find(new Document()).into(new ArrayList<Document>());
171+
for (Document doc: docs) {
172+
LotteryTicket lotteryTicket = docToTicket(doc);
173+
map.put(lotteryTicket.getId(), lotteryTicket);
174+
}
175+
return map;
176+
}
177+
178+
@Override
179+
public void deleteAll() {
180+
ticketsCollection.deleteMany(new Document());
181+
}
182+
183+
private LotteryTicket docToTicket(Document doc) {
184+
PlayerDetails playerDetails = PlayerDetails.create(doc.getString("email"), doc.getString("bank"),
185+
doc.getString("phone"));
186+
int[] numArray = Arrays.asList(doc.getString("numbers").split(",")).stream().mapToInt(Integer::parseInt).toArray();
187+
HashSet<Integer> numbers = new HashSet<>();
188+
for (int num: numArray) {
189+
numbers.add(num);
190+
}
191+
LotteryNumbers lotteryNumbers = LotteryNumbers.create(numbers);
192+
return LotteryTicket.create(new LotteryTicketId(doc.getInteger("ticketId")), playerDetails, lotteryNumbers);
193+
}
194+
}

hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
*/
2323
package com.iluwatar.hexagonal.domain;
2424

25+
import java.util.ArrayList;
2526
import java.util.Collections;
2627
import java.util.HashSet;
28+
import java.util.List;
2729
import java.util.PrimitiveIterator;
2830
import java.util.Random;
2931
import java.util.Set;
@@ -78,6 +80,22 @@ public static LotteryNumbers create(Set<Integer> givenNumbers) {
7880
public Set<Integer> getNumbers() {
7981
return Collections.unmodifiableSet(numbers);
8082
}
83+
84+
/**
85+
* @return numbers as comma separated string
86+
*/
87+
public String getNumbersAsString() {
88+
List<Integer> list = new ArrayList<>();
89+
list.addAll(numbers);
90+
StringBuilder builder = new StringBuilder();
91+
for (int i = 0; i < NUM_NUMBERS; i++) {
92+
builder.append(list.get(i));
93+
if (i < NUM_NUMBERS - 1) {
94+
builder.append(",");
95+
}
96+
}
97+
return builder.toString();
98+
}
8199

82100
/**
83101
* Generates 4 unique random numbers between 1-20 into numbers set.

hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,24 @@
2929
*/
3030
public class LotteryTicket {
3131

32+
private LotteryTicketId id;
3233
private final PlayerDetails playerDetails;
3334
private final LotteryNumbers lotteryNumbers;
34-
35+
3536
/**
3637
* Constructor.
3738
*/
38-
private LotteryTicket(PlayerDetails details, LotteryNumbers numbers) {
39+
private LotteryTicket(LotteryTicketId id, PlayerDetails details, LotteryNumbers numbers) {
40+
this.id = id;
3941
playerDetails = details;
4042
lotteryNumbers = numbers;
4143
}
4244

4345
/**
4446
* Factory for creating lottery tickets;
4547
*/
46-
public static LotteryTicket create(PlayerDetails details, LotteryNumbers numbers) {
47-
return new LotteryTicket(details, numbers);
48+
public static LotteryTicket create(LotteryTicketId id, PlayerDetails details, LotteryNumbers numbers) {
49+
return new LotteryTicket(id, details, numbers);
4850
}
4951

5052
/**
@@ -61,6 +63,20 @@ public LotteryNumbers getNumbers() {
6163
return lotteryNumbers;
6264
}
6365

66+
/**
67+
* @return id
68+
*/
69+
public LotteryTicketId getId() {
70+
return id;
71+
}
72+
73+
/**
74+
* set id
75+
*/
76+
public void setId(LotteryTicketId id) {
77+
this.id = id;
78+
}
79+
6480
@Override
6581
public String toString() {
6682
return playerDetails.toString() + " " + lotteryNumbers.toString();

hexagonal/src/main/java/com/iluwatar/hexagonal/module/LotteryModule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
import com.google.inject.AbstractModule;
2626
import com.iluwatar.hexagonal.banking.InMemoryBank;
2727
import com.iluwatar.hexagonal.banking.WireTransfers;
28-
import com.iluwatar.hexagonal.database.InMemoryTicketRepository;
2928
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
29+
import com.iluwatar.hexagonal.database.MongoTicketRepository;
3030
import com.iluwatar.hexagonal.notifications.LotteryNotifications;
3131
import com.iluwatar.hexagonal.notifications.StdOutNotifications;
3232

@@ -36,7 +36,7 @@
3636
public class LotteryModule extends AbstractModule {
3737
@Override
3838
protected void configure() {
39-
bind(LotteryTicketRepository.class).to(InMemoryTicketRepository.class);
39+
bind(LotteryTicketRepository.class).to(MongoTicketRepository.class);
4040
bind(LotteryNotifications.class).to(StdOutNotifications.class);
4141
bind(WireTransfers.class).to(InMemoryBank.class);
4242
}

hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.iluwatar.hexagonal.domain.LotteryNumbers;
2828
import com.iluwatar.hexagonal.domain.LotteryService;
2929
import com.iluwatar.hexagonal.domain.LotteryTicket;
30+
import com.iluwatar.hexagonal.domain.LotteryTicketId;
3031
import com.iluwatar.hexagonal.domain.PlayerDetails;
3132

3233
import java.util.ArrayList;
@@ -94,7 +95,8 @@ public class SampleData {
9495
*/
9596
public static void submitTickets(LotteryService lotteryService, int numTickets) {
9697
for (int i = 0; i < numTickets; i++) {
97-
LotteryTicket ticket = LotteryTicket.create(getRandomPlayerDetails(), LotteryNumbers.createRandom());
98+
LotteryTicket ticket = LotteryTicket.create(new LotteryTicketId(),
99+
getRandomPlayerDetails(), LotteryNumbers.createRandom());
98100
lotteryService.submitTicket(ticket);
99101
}
100102
}

hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public static void main(String[] args) {
8383
chosen.add(Integer.parseInt(parts[i]));
8484
}
8585
LotteryNumbers lotteryNumbers = LotteryNumbers.create(chosen);
86-
LotteryTicket lotteryTicket = LotteryTicket.create(details, lotteryNumbers);
86+
LotteryTicket lotteryTicket = LotteryTicket.create(new LotteryTicketId(), details, lotteryNumbers);
8787
Optional<LotteryTicketId> id = service.submitTicket(lotteryTicket);
8888
if (id.isPresent()) {
8989
System.out.println("Submitted lottery ticket with id: " + id.get());

hexagonal/src/test/java/com/iluwatar/hexagonal/database/LotteryTicketRepositoryTest.java renamed to hexagonal/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* Tests for {@link LotteryTicketRepository}
4040
*
4141
*/
42-
public class LotteryTicketRepositoryTest {
42+
public class InMemoryTicketRepositoryTest {
4343

4444
private final LotteryTicketRepository repository = new InMemoryTicketRepository();
4545

0 commit comments

Comments
 (0)