Java 11 migrate all remaining s (#1120)

* Moves saga to Java 11

* Moves semaphore to Java 11

* Moves servant to Java 11

* Moves serverless to Java 11

* Moves service-layer to Java 11

* Moves service-locator to Java 11

* Moves sharding to Java 11

* Moves singleton to Java 11

* Moves spatial-partition to Java 11

* Moves specification to Java 11

* Moves state to Java 11

* Moves step-builder to Java 11

* Moves strategy to Java 11

* Moves subclass-sandbox to Java 11

* Fixes checkstyle issues
This commit is contained in:
Anurag Agarwal 2020-01-04 22:06:08 +05:30 committed by Ilkka Seppälä
parent 310ae50248
commit cd2a2e7711
98 changed files with 718 additions and 855 deletions

View File

@ -25,9 +25,9 @@ package com.iluwatar.saga.choreography;
/** /**
* ChoreographyChapter is an interface representing a contract for an external service. * ChoreographyChapter is an interface representing a contract for an external service. In that
* In that case, a service needs to make a decision what to do further * case, a service needs to make a decision what to do further hence the server needs to get all
* hence the server needs to get all context representing {@link Saga} * context representing {@link Saga}
*/ */
public interface ChoreographyChapter { public interface ChoreographyChapter {
@ -41,6 +41,7 @@ public interface ChoreographyChapter {
/** /**
* get name method. * get name method.
*
* @return service name. * @return service name.
*/ */
String getName(); String getName();

View File

@ -28,9 +28,8 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
* Saga representation. * Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed a certain
* Saga consists of chapters. * service.
* Every ChoreographyChapter is executed a certain service.
*/ */
public class Saga { public class Saga {
@ -61,6 +60,7 @@ public class Saga {
/** /**
* add chapter to saga. * add chapter to saga.
*
* @param name chapter name * @param name chapter name
* @return this * @return this
*/ */
@ -71,6 +71,7 @@ public class Saga {
/** /**
* set value to last chapter. * set value to last chapter.
*
* @param value invalue * @param value invalue
* @return this * @return this
*/ */
@ -84,6 +85,7 @@ public class Saga {
/** /**
* get value from current chapter. * get value from current chapter.
*
* @return value * @return value
*/ */
public Object getCurrentValue() { public Object getCurrentValue() {
@ -92,6 +94,7 @@ public class Saga {
/** /**
* set value to current chapter. * set value to current chapter.
*
* @param value to set * @param value to set
*/ */
public void setCurrentValue(Object value) { public void setCurrentValue(Object value) {
@ -100,6 +103,7 @@ public class Saga {
/** /**
* set status for current chapter. * set status for current chapter.
*
* @param result to set * @param result to set
*/ */
public void setCurrentStatus(ChapterResult result) { public void setCurrentStatus(ChapterResult result) {
@ -145,8 +149,8 @@ public class Saga {
} }
/** /**
* Class presents a chapter status and incoming * Class presents a chapter status and incoming parameters(incoming parameter transforms to
* parameters(incoming parameter transforms to outcoming parameter). * outcoming parameter).
*/ */
public static class Chapter { public static class Chapter {
private String name; private String name;
@ -173,6 +177,7 @@ public class Saga {
/** /**
* set result. * set result.
*
* @param result {@link ChapterResult} * @param result {@link ChapterResult}
*/ */
public void setResult(ChapterResult result) { public void setResult(ChapterResult result) {
@ -181,6 +186,7 @@ public class Saga {
/** /**
* the result for chapter is good. * the result for chapter is good.
*
* @return true if is good otherwise bad * @return true if is good otherwise bad
*/ */
public boolean isSuccess() { public boolean isSuccess() {

View File

@ -27,22 +27,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* This pattern is used in distributed services to perform a group of operations atomically. * This pattern is used in distributed services to perform a group of operations atomically. This is
* This is an analog of transaction in a database but in terms * an analog of transaction in a database but in terms of microservices architecture this is
* of microservices architecture this is executed * executed in a distributed environment
* in a distributed environment
* *
* <p>A saga is a sequence of local transactions in a certain context. * <p>A saga is a sequence of local transactions in a certain context.
* If one transaction fails for some reason, * If one transaction fails for some reason, the saga executes compensating transactions(rollbacks)
* the saga executes compensating transactions(rollbacks)
* to undo the impact of the preceding transactions. * to undo the impact of the preceding transactions.
* *
* <p>In this approach, there are no mediators or orchestrators services. * <p>In this approach, there are no mediators or orchestrators services.
* All chapters are handled and moved by services manually. * All chapters are handled and moved by services manually.
* *
* <p>The major difference with choreography saga is an ability to handle crashed services * <p>The major difference with choreography saga is an ability to handle crashed services
* (otherwise in choreography services very hard to prevent a saga * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed)
* if one of them has been crashed)
* *
* @see com.iluwatar.saga.choreography.Saga * @see com.iluwatar.saga.choreography.Saga
* @see Service * @see Service
@ -54,10 +51,10 @@ public class SagaApplication {
* main method. * main method.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
ServiceDiscoveryService sd = serviceDiscovery(); var sd = serviceDiscovery();
ChoreographyChapter service = sd.findAny(); var service = sd.findAny();
Saga goodOrderSaga = service.execute(newSaga("good_order")); var goodOrderSaga = service.execute(newSaga("good_order"));
Saga badOrderSaga = service.execute(newSaga("bad_order")); var badOrderSaga = service.execute(newSaga("bad_order"));
LOGGER.info("orders: goodOrder is {}, badOrder is {}", LOGGER.info("orders: goodOrder is {}, badOrder is {}",
goodOrderSaga.getResult(), badOrderSaga.getResult()); goodOrderSaga.getResult(), badOrderSaga.getResult());
@ -74,7 +71,7 @@ public class SagaApplication {
} }
private static ServiceDiscoveryService serviceDiscovery() { private static ServiceDiscoveryService serviceDiscovery() {
ServiceDiscoveryService sd = new ServiceDiscoveryService(); var sd = new ServiceDiscoveryService();
return sd return sd
.discover(new OrderService(sd)) .discover(new OrderService(sd))
.discover(new FlyBookingService(sd)) .discover(new FlyBookingService(sd))

View File

@ -29,8 +29,8 @@ import org.slf4j.LoggerFactory;
/** /**
* Common abstraction class representing services. * Common abstraction class representing services. implementing a general contract @see {@link
* implementing a general contract @see {@link ChoreographyChapter} * ChoreographyChapter}
*/ */
public abstract class Service implements ChoreographyChapter { public abstract class Service implements ChoreographyChapter {
protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class); protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class);
@ -43,9 +43,9 @@ public abstract class Service implements ChoreographyChapter {
@Override @Override
public Saga execute(Saga saga) { public Saga execute(Saga saga) {
Saga nextSaga = saga; var nextSaga = saga;
Object nextVal; Object nextVal;
String chapterName = saga.getCurrent().getName(); var chapterName = saga.getCurrent().getName();
if (chapterName.equals(getName())) { if (chapterName.equals(getName())) {
if (saga.isForward()) { if (saga.isForward()) {
nextSaga = process(saga); nextSaga = process(saga);
@ -67,7 +67,7 @@ public abstract class Service implements ChoreographyChapter {
nextSaga.setCurrentValue(nextVal); nextSaga.setCurrentValue(nextVal);
} }
Saga finalNextSaga = nextSaga; var finalNextSaga = nextSaga;
return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga))
.orElseThrow(serviceNotFoundException(chapterName)); .orElseThrow(serviceNotFoundException(chapterName));
@ -80,7 +80,7 @@ public abstract class Service implements ChoreographyChapter {
@Override @Override
public Saga process(Saga saga) { public Saga process(Saga saga) {
Object inValue = saga.getCurrentValue(); var inValue = saga.getCurrentValue();
LOGGER.info("The chapter '{}' has been started. " LOGGER.info("The chapter '{}' has been started. "
+ "The data {} has been stored or calculated successfully", + "The data {} has been stored or calculated successfully",
getName(), inValue); getName(), inValue);
@ -91,7 +91,7 @@ public abstract class Service implements ChoreographyChapter {
@Override @Override
public Saga rollback(Saga saga) { public Saga rollback(Saga saga) {
Object inValue = saga.getCurrentValue(); var inValue = saga.getCurrentValue();
LOGGER.info("The Rollback for a chapter '{}' has been started. " LOGGER.info("The Rollback for a chapter '{}' has been started. "
+ "The data {} has been rollbacked successfully", + "The data {} has been rollbacked successfully",
getName(), inValue); getName(), inValue);

View File

@ -39,7 +39,7 @@ public class WithdrawMoneyService extends Service {
@Override @Override
public Saga process(Saga saga) { public Saga process(Saga saga) {
Object inValue = saga.getCurrentValue(); var inValue = saga.getCurrentValue();
if (inValue.equals("bad_order")) { if (inValue.equals("bad_order")) {
LOGGER.info("The chapter '{}' has been started. But the exception has been raised." LOGGER.info("The chapter '{}' has been started. But the exception has been raised."

View File

@ -32,6 +32,7 @@ public interface OrchestrationChapter<K> {
/** /**
* method get name. * method get name.
*
* @return service name. * @return service name.
*/ */
String getName(); String getName();

View File

@ -27,9 +27,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Saga representation. * Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed by a
* Saga consists of chapters. * certain service.
* Every ChoreographyChapter is executed by a certain service.
*/ */
public class Saga { public class Saga {

View File

@ -27,23 +27,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* This pattern is used in distributed services to perform * This pattern is used in distributed services to perform a group of operations atomically. This is
* a group of operations atomically. * an analog of transaction in a database but in terms of microservices architecture this is
* This is an analog of transaction in a database but in terms * executed in a distributed environment
* of microservices architecture this is executed
* in a distributed environment
* *
* <p>A saga is a sequence of local transactions in a certain context. * <p>A saga is a sequence of local transactions in a certain context.
* If one transaction fails for some reason, * If one transaction fails for some reason, the saga executes compensating transactions(rollbacks)
* the saga executes compensating transactions(rollbacks)
* to undo the impact of the preceding transactions. * to undo the impact of the preceding transactions.
* *
* <p>In this approach, there is an orchestrator @see {@link SagaOrchestrator} * <p>In this approach, there is an orchestrator @see {@link SagaOrchestrator}
* that manages all the transactions and directs * that manages all the transactions and directs the participant services to execute local
* the participant services to execute local transactions based on events. * transactions based on events. The major difference with choreography saga is an ability to handle
* The major difference with choreography saga is an ability to handle crashed services * crashed services (otherwise in choreography services very hard to prevent a saga if one of them
* (otherwise in choreography services very hard to prevent a saga * has been crashed)
* if one of them has been crashed)
* *
* @see Saga * @see Saga
* @see SagaOrchestrator * @see SagaOrchestrator
@ -56,7 +52,7 @@ public class SagaApplication {
* method to show common saga logic. * method to show common saga logic.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); Saga.Result goodOrder = sagaOrchestrator.execute("good_order");
Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); Saga.Result badOrder = sagaOrchestrator.execute("bad_order");
@ -77,8 +73,7 @@ public class SagaApplication {
} }
private static ServiceDiscoveryService serviceDiscovery() { private static ServiceDiscoveryService serviceDiscovery() {
return return new ServiceDiscoveryService()
new ServiceDiscoveryService()
.discover(new OrderService()) .discover(new OrderService())
.discover(new FlyBookingService()) .discover(new FlyBookingService())
.discover(new HotelBookingService()) .discover(new HotelBookingService())

View File

@ -23,18 +23,18 @@
package com.iluwatar.saga.orchestration; package com.iluwatar.saga.orchestration;
import static com.iluwatar.saga.orchestration.Saga.Result;
import static com.iluwatar.saga.orchestration.Saga.Result.CRASHED; import static com.iluwatar.saga.orchestration.Saga.Result.CRASHED;
import static com.iluwatar.saga.orchestration.Saga.Result.FINISHED; import static com.iluwatar.saga.orchestration.Saga.Result.FINISHED;
import static com.iluwatar.saga.orchestration.Saga.Result.ROLLBACK; import static com.iluwatar.saga.orchestration.Saga.Result.ROLLBACK;
import java.util.Optional;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* The orchestrator that manages all the transactions and directs * The orchestrator that manages all the transactions and directs the participant services to
* the participant services to execute local transactions based on events. * execute local transactions based on events.
*/ */
public class SagaOrchestrator { public class SagaOrchestrator {
private static final Logger LOGGER = LoggerFactory.getLogger(SagaOrchestrator.class); private static final Logger LOGGER = LoggerFactory.getLogger(SagaOrchestrator.class);
@ -45,6 +45,7 @@ public class SagaOrchestrator {
/** /**
* Create a new service to orchetrate sagas. * Create a new service to orchetrate sagas.
*
* @param saga saga to process * @param saga saga to process
* @param sd service discovery @see {@link ServiceDiscoveryService} * @param sd service discovery @see {@link ServiceDiscoveryService}
*/ */
@ -59,30 +60,30 @@ public class SagaOrchestrator {
* *
* @param value incoming value * @param value incoming value
* @param <K> type for incoming value * @param <K> type for incoming value
* @return result @see {@link Saga.Result} * @return result @see {@link Result}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <K> Saga.Result execute(K value) { public <K> Result execute(K value) {
state.cleanUp(); state.cleanUp();
LOGGER.info(" The new saga is about to start"); LOGGER.info(" The new saga is about to start");
Saga.Result result = FINISHED; var result = FINISHED;
K tempVal = value; K tempVal = value;
while (true) { while (true) {
int next = state.current(); var next = state.current();
Saga.Chapter ch = saga.get(next); var ch = saga.get(next);
Optional<OrchestrationChapter> srvOpt = sd.find(ch.name); var srvOpt = sd.find(ch.name);
if (!srvOpt.isPresent()) { if (srvOpt.isEmpty()) {
state.directionToBack(); state.directionToBack();
state.back(); state.back();
continue; continue;
} }
OrchestrationChapter srv = srvOpt.get(); var srv = srvOpt.get();
if (state.isForward()) { if (state.isForward()) {
ChapterResult processRes = srv.process(tempVal); var processRes = srv.process(tempVal);
if (processRes.isSuccess()) { if (processRes.isSuccess()) {
next = state.forward(); next = state.forward();
tempVal = (K) processRes.getValue(); tempVal = (K) processRes.getValue();
@ -90,7 +91,7 @@ public class SagaOrchestrator {
state.directionToBack(); state.directionToBack();
} }
} else { } else {
ChapterResult rlRes = srv.rollback(tempVal); var rlRes = srv.rollback(tempVal);
if (rlRes.isSuccess()) { if (rlRes.isSuccess()) {
next = state.back(); next = state.back();
tempVal = (K) rlRes.getValue(); tempVal = (K) rlRes.getValue();

View File

@ -27,8 +27,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Common abstraction class representing services. * Common abstraction class representing services. implementing a general contract @see {@link
* implementing a general contract @see {@link OrchestrationChapter} * OrchestrationChapter}
* *
* @param <K> type of incoming param * @param <K> type of incoming param
*/ */

View File

@ -33,10 +33,10 @@ public class SagaChoreographyTest {
@Test @Test
public void executeTest() { public void executeTest() {
ServiceDiscoveryService sd = serviceDiscovery(); var sd = serviceDiscovery();
ChoreographyChapter service = sd.findAny(); var service = sd.findAny();
Saga badOrderSaga = service.execute(newSaga("bad_order")); var badOrderSaga = service.execute(newSaga("bad_order"));
Saga goodOrderSaga = service.execute(newSaga("good_order")); var goodOrderSaga = service.execute(newSaga("good_order"));
Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED);
Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED);
@ -52,7 +52,7 @@ public class SagaChoreographyTest {
} }
private static ServiceDiscoveryService serviceDiscovery() { private static ServiceDiscoveryService serviceDiscovery() {
ServiceDiscoveryService sd = new ServiceDiscoveryService(); var sd = new ServiceDiscoveryService();
return sd return sd
.discover(new OrderService(sd)) .discover(new OrderService(sd))
.discover(new FlyBookingService(sd)) .discover(new FlyBookingService(sd))

View File

@ -24,8 +24,6 @@ package com.iluwatar.saga.orchestration;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*;
/** /**
* empty test * empty test
*/ */

View File

@ -22,11 +22,12 @@
*/ */
package com.iluwatar.saga.orchestration; package com.iluwatar.saga.orchestration;
import org.junit.Assert; import static com.iluwatar.saga.orchestration.Saga.Result;
import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.Assert;
import org.junit.Test;
/** /**
* test to test orchestration logic * test to test orchestration logic
@ -37,17 +38,16 @@ public class SagaOrchestratorInternallyTest {
@Test @Test
public void executeTest() { public void executeTest() {
SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
Saga.Result result = sagaOrchestrator.execute(1); var result = sagaOrchestrator.execute(1);
Assert.assertEquals(result, Saga.Result.ROLLBACK); Assert.assertEquals(result, Result.ROLLBACK);
Assert.assertArrayEquals( Assert.assertArrayEquals(
records.toArray(new String[]{}), records.toArray(new String[]{}),
new String[]{"+1", "+2", "+3", "+4", "-4", "-3", "-2", "-1"}); new String[]{"+1", "+2", "+3", "+4", "-4", "-3", "-2", "-1"});
} }
private static Saga newSaga() { private static Saga newSaga() {
return Saga return Saga.create()
.create()
.chapter("1") .chapter("1")
.chapter("2") .chapter("2")
.chapter("3") .chapter("3")
@ -55,8 +55,7 @@ public class SagaOrchestratorInternallyTest {
} }
private ServiceDiscoveryService serviceDiscovery() { private ServiceDiscoveryService serviceDiscovery() {
return return new ServiceDiscoveryService()
new ServiceDiscoveryService()
.discover(new Service1()) .discover(new Service1())
.discover(new Service2()) .discover(new Service2())
.discover(new Service3()) .discover(new Service3())

View File

@ -38,7 +38,7 @@ public class App {
* main method. * main method.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
FruitShop shop = new FruitShop(); var shop = new FruitShop();
new Customer("Peter", shop).start(); new Customer("Peter", shop).start();
new Customer("Paul", shop).start(); new Customer("Paul", shop).start();
new Customer("Mary", shop).start(); new Customer("Mary", shop).start();

View File

@ -64,15 +64,16 @@ public class Customer extends Thread {
public void run() { public void run() {
while (fruitShop.countFruit() > 0) { while (fruitShop.countFruit() > 0) {
FruitBowl bowl = fruitShop.takeBowl(); var bowl = fruitShop.takeBowl();
Fruit fruit; if (bowl != null) {
var fruit = bowl.take();
if (bowl != null && (fruit = bowl.take()) != null) { if (fruit != null) {
LOGGER.info("{} took an {}", name, fruit); LOGGER.info("{} took an {}", name, fruit);
fruitBowl.put(fruit); fruitBowl.put(fruit);
fruitShop.returnBowl(bowl); fruitShop.returnBowl(bowl);
} }
} }
}
LOGGER.info("{} took {}", name, fruitBowl); LOGGER.info("{} took {}", name, fruitBowl);

View File

@ -68,11 +68,11 @@ public class FruitBowl {
* toString method. * toString method.
*/ */
public String toString() { public String toString() {
int apples = 0; var apples = 0;
int oranges = 0; var oranges = 0;
int lemons = 0; var lemons = 0;
for (Fruit f : fruit) { for (var f : fruit) {
switch (f.getType()) { switch (f.getType()) {
case APPLE: case APPLE:
apples++; apples++;

View File

@ -55,7 +55,7 @@ public class FruitShop {
* FruitShop constructor. * FruitShop constructor.
*/ */
public FruitShop() { public FruitShop() {
for (int i = 0; i < 100; i++) { for (var i = 0; i < 100; i++) {
bowls[0].put(new Fruit(Fruit.FruitType.APPLE)); bowls[0].put(new Fruit(Fruit.FruitType.APPLE));
bowls[1].put(new Fruit(Fruit.FruitType.ORANGE)); bowls[1].put(new Fruit(Fruit.FruitType.ORANGE));
bowls[2].put(new Fruit(Fruit.FruitType.LEMON)); bowls[2].put(new Fruit(Fruit.FruitType.LEMON));

View File

@ -25,15 +25,12 @@ package com.iluwatar.semaphore;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.IOException;
/** /**
* Application Test Entrypoint * Application Test Entrypoint
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -23,12 +23,12 @@
package com.iluwatar.semaphore; package com.iluwatar.semaphore;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
/** /**
* Test taking from and putting Fruit into a FruitBowl * Test taking from and putting Fruit into a FruitBowl
*/ */
@ -36,16 +36,16 @@ public class FruitBowlTest {
@Test @Test
public void fruitBowlTest() { public void fruitBowlTest() {
FruitBowl fbowl = new FruitBowl(); var fbowl = new FruitBowl();
assertEquals(0, fbowl.countFruit()); assertEquals(0, fbowl.countFruit());
for (int i = 1; i <= 10; i++) { for (var i = 1; i <= 10; i++) {
fbowl.put(new Fruit(Fruit.FruitType.LEMON)); fbowl.put(new Fruit(Fruit.FruitType.LEMON));
assertEquals(i, fbowl.countFruit()); assertEquals(i, fbowl.countFruit());
} }
for (int i = 9; i >= 0; i--) { for (var i = 9; i >= 0; i--) {
assertNotNull(fbowl.take()); assertNotNull(fbowl.take());
assertEquals(i, fbowl.countFruit()); assertEquals(i, fbowl.countFruit());
} }

View File

@ -23,11 +23,11 @@
package com.iluwatar.semaphore; package com.iluwatar.semaphore;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
/** /**
* Test case for acquiring and releasing a Semaphore * Test case for acquiring and releasing a Semaphore
*/ */
@ -35,11 +35,11 @@ public class SemaphoreTest {
@Test @Test
public void acquireReleaseTest() { public void acquireReleaseTest() {
Semaphore sphore = new Semaphore(3); var sphore = new Semaphore(3);
assertEquals(3, sphore.getAvailableLicenses()); assertEquals(3, sphore.getAvailableLicenses());
for (int i = 2; i >= 0; i--) { for (var i = 2; i >= 0; i--) {
try { try {
sphore.acquire(); sphore.acquire();
assertEquals(i, sphore.getAvailableLicenses()); assertEquals(i, sphore.getAvailableLicenses());
@ -48,7 +48,7 @@ public class SemaphoreTest {
} }
} }
for (int i = 1; i <= 3; i++) { for (var i = 1; i <= 3; i++) {
sphore.release(); sphore.release();
assertEquals(i, sphore.getAvailableLicenses()); assertEquals(i, sphore.getAvailableLicenses());
} }

View File

@ -54,10 +54,10 @@ public class App {
* Can add a List with enum Actions for variable scenarios. * Can add a List with enum Actions for variable scenarios.
*/ */
public static void scenario(Servant servant, int compliment) { public static void scenario(Servant servant, int compliment) {
King k = new King(); var k = new King();
Queen q = new Queen(); var q = new Queen();
List<Royalty> guests = List.of(k, q); var guests = List.of(k, q);
// feed // feed
servant.feed(k); servant.feed(k);
@ -69,9 +69,7 @@ public class App {
servant.giveCompliments(guests.get(compliment)); servant.giveCompliments(guests.get(compliment));
// outcome of the night // outcome of the night
for (Royalty r : guests) { guests.forEach(Royalty::changeMood);
r.changeMood();
}
// check your luck // check your luck
if (servant.checkIfYouWillBeHanged(guests)) { if (servant.checkIfYouWillBeHanged(guests)) {

View File

@ -55,13 +55,6 @@ public class Servant {
* Check if we will be hanged. * Check if we will be hanged.
*/ */
public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) { public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {
boolean anotherDay = true; return tableGuests.stream().allMatch(Royalty::getMood);
for (Royalty r : tableGuests) {
if (!r.getMood()) {
anotherDay = false;
}
}
return anotherDay;
} }
} }

View File

@ -26,15 +26,12 @@ package com.iluwatar.servant;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -23,11 +23,11 @@
package com.iluwatar.servant; package com.iluwatar.servant;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 9:40 PM * Date: 12/28/15 - 9:40 PM
* *
@ -37,14 +37,14 @@ public class KingTest {
@Test @Test
public void testHungrySoberUncomplimentedKing() { public void testHungrySoberUncomplimentedKing() {
final King king = new King(); final var king = new King();
king.changeMood(); king.changeMood();
assertFalse(king.getMood()); assertFalse(king.getMood());
} }
@Test @Test
public void testFedSoberUncomplimentedKing() { public void testFedSoberUncomplimentedKing() {
final King king = new King(); final var king = new King();
king.getFed(); king.getFed();
king.changeMood(); king.changeMood();
assertFalse(king.getMood()); assertFalse(king.getMood());
@ -52,7 +52,7 @@ public class KingTest {
@Test @Test
public void testHungryDrunkUncomplimentedKing() { public void testHungryDrunkUncomplimentedKing() {
final King king = new King(); final var king = new King();
king.getDrink(); king.getDrink();
king.changeMood(); king.changeMood();
assertFalse(king.getMood()); assertFalse(king.getMood());
@ -60,7 +60,7 @@ public class KingTest {
@Test @Test
public void testHungrySoberComplimentedKing() { public void testHungrySoberComplimentedKing() {
final King king = new King(); final var king = new King();
king.receiveCompliments(); king.receiveCompliments();
king.changeMood(); king.changeMood();
assertFalse(king.getMood()); assertFalse(king.getMood());
@ -68,7 +68,7 @@ public class KingTest {
@Test @Test
public void testFedDrunkUncomplimentedKing() { public void testFedDrunkUncomplimentedKing() {
final King king = new King(); final var king = new King();
king.getFed(); king.getFed();
king.getDrink(); king.getDrink();
king.changeMood(); king.changeMood();
@ -77,7 +77,7 @@ public class KingTest {
@Test @Test
public void testFedSoberComplimentedKing() { public void testFedSoberComplimentedKing() {
final King king = new King(); final var king = new King();
king.getFed(); king.getFed();
king.receiveCompliments(); king.receiveCompliments();
king.changeMood(); king.changeMood();
@ -86,7 +86,7 @@ public class KingTest {
@Test @Test
public void testFedDrunkComplimentedKing() { public void testFedDrunkComplimentedKing() {
final King king = new King(); final var king = new King();
king.getFed(); king.getFed();
king.getDrink(); king.getDrink();
king.receiveCompliments(); king.receiveCompliments();

View File

@ -24,11 +24,11 @@
package com.iluwatar.servant; package com.iluwatar.servant;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 9:52 PM * Date: 12/28/15 - 9:52 PM
* *
@ -38,7 +38,7 @@ public class QueenTest {
@Test @Test
public void testNotFlirtyUncomplemented() { public void testNotFlirtyUncomplemented() {
final Queen queen = new Queen(); final var queen = new Queen();
queen.setFlirtiness(false); queen.setFlirtiness(false);
queen.changeMood(); queen.changeMood();
assertFalse(queen.getMood()); assertFalse(queen.getMood());
@ -46,7 +46,7 @@ public class QueenTest {
@Test @Test
public void testNotFlirtyComplemented() { public void testNotFlirtyComplemented() {
final Queen queen = new Queen(); final var queen = new Queen();
queen.setFlirtiness(false); queen.setFlirtiness(false);
queen.receiveCompliments(); queen.receiveCompliments();
queen.changeMood(); queen.changeMood();
@ -55,14 +55,14 @@ public class QueenTest {
@Test @Test
public void testFlirtyUncomplemented() { public void testFlirtyUncomplemented() {
final Queen queen = new Queen(); final var queen = new Queen();
queen.changeMood(); queen.changeMood();
assertFalse(queen.getMood()); assertFalse(queen.getMood());
} }
@Test @Test
public void testFlirtyComplemented() { public void testFlirtyComplemented() {
final Queen queen = new Queen(); final var queen = new Queen();
queen.receiveCompliments(); queen.receiveCompliments();
queen.changeMood(); queen.changeMood();
assertTrue(queen.getMood()); assertTrue(queen.getMood());

View File

@ -23,16 +23,15 @@
package com.iluwatar.servant; package com.iluwatar.servant;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.List;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 10:02 PM * Date: 12/28/15 - 10:02 PM
* *
@ -42,8 +41,8 @@ public class ServantTest {
@Test @Test
public void testFeed() { public void testFeed() {
final Royalty royalty = mock(Royalty.class); final var royalty = mock(Royalty.class);
final Servant servant = new Servant("test"); final var servant = new Servant("test");
servant.feed(royalty); servant.feed(royalty);
verify(royalty).getFed(); verify(royalty).getFed();
verifyNoMoreInteractions(royalty); verifyNoMoreInteractions(royalty);
@ -51,8 +50,8 @@ public class ServantTest {
@Test @Test
public void testGiveWine() { public void testGiveWine() {
final Royalty royalty = mock(Royalty.class); final var royalty = mock(Royalty.class);
final Servant servant = new Servant("test"); final var servant = new Servant("test");
servant.giveWine(royalty); servant.giveWine(royalty);
verify(royalty).getDrink(); verify(royalty).getDrink();
verifyNoMoreInteractions(royalty); verifyNoMoreInteractions(royalty);
@ -60,8 +59,8 @@ public class ServantTest {
@Test @Test
public void testGiveCompliments() { public void testGiveCompliments() {
final Royalty royalty = mock(Royalty.class); final var royalty = mock(Royalty.class);
final Servant servant = new Servant("test"); final var servant = new Servant("test");
servant.giveCompliments(royalty); servant.giveCompliments(royalty);
verify(royalty).receiveCompliments(); verify(royalty).receiveCompliments();
verifyNoMoreInteractions(royalty); verifyNoMoreInteractions(royalty);
@ -69,15 +68,15 @@ public class ServantTest {
@Test @Test
public void testCheckIfYouWillBeHanged() { public void testCheckIfYouWillBeHanged() {
final Royalty goodMoodRoyalty = mock(Royalty.class); final var goodMoodRoyalty = mock(Royalty.class);
when(goodMoodRoyalty.getMood()).thenReturn(true); when(goodMoodRoyalty.getMood()).thenReturn(true);
final Royalty badMoodRoyalty = mock(Royalty.class); final var badMoodRoyalty = mock(Royalty.class);
when(badMoodRoyalty.getMood()).thenReturn(true); when(badMoodRoyalty.getMood()).thenReturn(true);
final List<Royalty> goodCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, goodMoodRoyalty); final var goodCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, goodMoodRoyalty);
final List<Royalty> badCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, badMoodRoyalty); final var badCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, badMoodRoyalty);
assertTrue(new Servant("test").checkIfYouWillBeHanged(goodCompany)); assertTrue(new Servant("test").checkIfYouWillBeHanged(goodCompany));
assertTrue(new Servant("test").checkIfYouWillBeHanged(badCompany)); assertTrue(new Servant("test").checkIfYouWillBeHanged(badCompany));

View File

@ -24,14 +24,12 @@
package com.iluwatar.serverless.baas.api; package com.iluwatar.serverless.baas.api;
import com.amazonaws.regions.Regions; import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -50,7 +48,7 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
} }
private void initAmazonDynamoDb() { private void initAmazonDynamoDb() {
AmazonDynamoDB amazonDynamoDb = AmazonDynamoDBClientBuilder var amazonDynamoDb = AmazonDynamoDBClientBuilder
.standard() .standard()
.withRegion(Regions.US_EAST_1) .withRegion(Regions.US_EAST_1)
.build(); .build();
@ -71,10 +69,7 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
} }
protected Map<String, String> headers() { protected Map<String, String> headers() {
Map<String, String> headers = new HashMap<>(); return Map.of("Content-Type", "application/json");
headers.put("Content-Type", "application/json");
return headers;
} }
/** /**
@ -85,14 +80,11 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
* @return - api gateway proxy response * @return - api gateway proxy response
*/ */
protected APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent(Integer statusCode, T body) { protected APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent(Integer statusCode, T body) {
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = var apiGatewayProxyResponseEvent = new APIGatewayProxyResponseEvent().withHeaders(headers());
new APIGatewayProxyResponseEvent().withHeaders(headers());
try { try {
apiGatewayProxyResponseEvent apiGatewayProxyResponseEvent
.withStatusCode(statusCode) .withStatusCode(statusCode)
.withBody(getObjectMapper() .withBody(getObjectMapper().writeValueAsString(body));
.writeValueAsString(body));
} catch (JsonProcessingException jsonProcessingException) { } catch (JsonProcessingException jsonProcessingException) {
throw new RuntimeException(jsonProcessingException); throw new RuntimeException(jsonProcessingException);
} }

View File

@ -28,7 +28,6 @@ import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.iluwatar.serverless.baas.model.Person; import com.iluwatar.serverless.baas.model.Person;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -42,15 +41,15 @@ public class FindPersonApiHandler extends AbstractDynamoDbHandler<Person>
private static final Integer SUCCESS_STATUS_CODE = 200; private static final Integer SUCCESS_STATUS_CODE = 200;
@Override @Override
public APIGatewayProxyResponseEvent handleRequest( public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent req, Context ctx) {
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) { req.getPathParameters().forEach(FindPersonApiHandler::logKeyValue);
Map<String, String> pathParameters = apiGatewayProxyRequestEvent.getPathParameters(); var id = req.getPathParameters().get("id");
pathParameters.keySet().stream().map(key -> key + "=" + pathParameters.get(key)) var person = this.getDynamoDbMapper().load(Person.class, id);
.forEach(LOG::info);
Person person = this.getDynamoDbMapper().load(Person.class, apiGatewayProxyRequestEvent
.getPathParameters().get("id"));
return apiGatewayProxyResponseEvent(SUCCESS_STATUS_CODE, person); return apiGatewayProxyResponseEvent(SUCCESS_STATUS_CODE, person);
} }
private static void logKeyValue(String key, String value) {
LOG.info(key + "=" + value);
}
} }

View File

@ -43,19 +43,15 @@ public class SavePersonApiHandler extends AbstractDynamoDbHandler<Person>
private static final Integer BAD_REQUEST_STATUS_CODE = 400; private static final Integer BAD_REQUEST_STATUS_CODE = 400;
@Override @Override
public APIGatewayProxyResponseEvent handleRequest( public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent req, Context ctx) {
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent;
Person person;
try { try {
person = getObjectMapper().readValue(apiGatewayProxyRequestEvent.getBody(), Person.class); var objectMapper = getObjectMapper();
var person = objectMapper.readValue(req.getBody(), Person.class);
getDynamoDbMapper().save(person); getDynamoDbMapper().save(person);
apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(CREATED_STATUS_CODE, person); return apiGatewayProxyResponseEvent(CREATED_STATUS_CODE, person);
} catch (IOException ioException) { } catch (IOException ioException) {
LOG.error("unable to parse body", ioException); LOG.error("unable to parse body", ioException);
apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(BAD_REQUEST_STATUS_CODE, null); return apiGatewayProxyResponseEvent(BAD_REQUEST_STATUS_CODE, null);
} }
return apiGatewayProxyResponseEvent;
} }
} }

View File

@ -26,6 +26,7 @@ package com.iluwatar.serverless.baas.model;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects;
/** /**
* Address class Created by dheeraj.mummarareddy on 3/4/18. * Address class Created by dheeraj.mummarareddy on 3/4/18.
@ -96,30 +97,30 @@ public class Address implements Serializable {
return false; return false;
} }
Address address = (Address) o; var address = (Address) o;
if (addressLineOne != null ? !addressLineOne.equals(address.addressLineOne) : if (!Objects.equals(addressLineOne, address.addressLineOne)) {
address.addressLineOne != null) {
return false; return false;
} }
if (addressLineTwo != null ? !addressLineTwo.equals(address.addressLineTwo) : if (!Objects.equals(addressLineTwo, address.addressLineTwo)) {
address.addressLineTwo != null) {
return false; return false;
} }
if (city != null ? !city.equals(address.city) : address.city != null) { if (!Objects.equals(city, address.city)) {
return false; return false;
} }
if (state != null ? !state.equals(address.state) : address.state != null) {
if (!Objects.equals(state, address.state)) {
return false; return false;
} }
return zipCode != null ? zipCode.equals(address.zipCode) : address.zipCode == null;
return Objects.equals(zipCode, address.zipCode);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = addressLineOne != null ? addressLineOne.hashCode() : 0; var result = addressLineOne != null ? addressLineOne.hashCode() : 0;
result = 31 * result + (addressLineTwo != null ? addressLineTwo.hashCode() : 0); result = 31 * result + (addressLineTwo != null ? addressLineTwo.hashCode() : 0);
result = 31 * result + (city != null ? city.hashCode() : 0); result = 31 * result + (city != null ? city.hashCode() : 0);
result = 31 * result + (state != null ? state.hashCode() : 0); result = 31 * result + (state != null ? state.hashCode() : 0);

View File

@ -29,6 +29,7 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects;
/** /**
* Person class Created by dheeraj.mummarareddy on 3/4/18. * Person class Created by dheeraj.mummarareddy on 3/4/18.
@ -92,15 +93,15 @@ public class Person implements Serializable {
Person person = (Person) o; Person person = (Person) o;
if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) { if (!Objects.equals(firstName, person.firstName)) {
return false; return false;
} }
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) { if (!Objects.equals(lastName, person.lastName)) {
return false; return false;
} }
return address != null ? address.equals(person.address) : person.address == null; return Objects.equals(address, person.address);
} }
@Override @Override

View File

@ -30,10 +30,8 @@ import java.util.Map;
/** /**
* Api gateway response. * Api gateway response.
*
* @param <T> serializable object
*/ */
public class ApiGatewayResponse<T extends Serializable> implements Serializable { public class ApiGatewayResponse implements Serializable {
private static final long serialVersionUID = 1181159426782844892L; private static final long serialVersionUID = 1181159426782844892L;
@ -50,8 +48,12 @@ public class ApiGatewayResponse<T extends Serializable> implements Serializable
* @param headers - response headers * @param headers - response headers
* @param isBase64Encoded - base64Encoded flag * @param isBase64Encoded - base64Encoded flag
*/ */
public ApiGatewayResponse(Integer statusCode, String body, Map<String, String> headers, public ApiGatewayResponse(
Boolean isBase64Encoded) { Integer statusCode,
String body,
Map<String, String> headers,
Boolean isBase64Encoded
) {
this.statusCode = statusCode; this.statusCode = statusCode;
this.body = body; this.body = body;
this.headers = headers; this.headers = headers;

View File

@ -24,6 +24,7 @@
package com.iluwatar.serverless.faas; package com.iluwatar.serverless.faas;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects;
/** /**
* Lambda context information. * Lambda context information.
@ -110,28 +111,22 @@ public class LambdaInfo implements Serializable {
LambdaInfo that = (LambdaInfo) o; LambdaInfo that = (LambdaInfo) o;
if (awsRequestId != null ? !awsRequestId if (!Objects.equals(awsRequestId, that.awsRequestId)) {
.equals(that.awsRequestId) : that.awsRequestId != null) {
return false; return false;
} }
if (logGroupName != null ? !logGroupName if (!Objects.equals(logGroupName, that.logGroupName)) {
.equals(that.logGroupName) : that.logGroupName != null) {
return false; return false;
} }
if (logStreamName != null ? !logStreamName if (!Objects.equals(logStreamName, that.logStreamName)) {
.equals(that.logStreamName) : that.logStreamName != null) {
return false; return false;
} }
if (functionName != null ? !functionName if (!Objects.equals(functionName, that.functionName)) {
.equals(that.functionName) : that.functionName != null) {
return false; return false;
} }
if (functionVersion != null ? !functionVersion if (!Objects.equals(functionVersion, that.functionVersion)) {
.equals(that.functionVersion) : that.functionVersion != null) {
return false; return false;
} }
return memoryLimitInMb != null ? memoryLimitInMb return Objects.equals(memoryLimitInMb, that.memoryLimitInMb);
.equals(that.memoryLimitInMb) : that.memoryLimitInMb == null;
} }
@Override @Override

View File

@ -27,7 +27,6 @@ import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.iluwatar.serverless.faas.ApiGatewayResponse; import com.iluwatar.serverless.faas.ApiGatewayResponse;
import com.iluwatar.serverless.faas.LambdaInfo; import com.iluwatar.serverless.faas.LambdaInfo;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -46,13 +45,11 @@ public class LambdaInfoApiHandler
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) { public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
LOG.info("received: " + input); LOG.info("received: " + input);
return new ApiGatewayResponse return new ApiGatewayResponse.ApiGatewayResponseBuilder<LambdaInfo>()
.ApiGatewayResponseBuilder<LambdaInfo>()
.headers(headers()) .headers(headers())
.statusCode(SUCCESS_STATUS_CODE) .statusCode(SUCCESS_STATUS_CODE)
.body(lambdaInfo(context)) .body(lambdaInfo(context))
.build(); .build();
} }
/** /**
@ -69,14 +66,10 @@ public class LambdaInfoApiHandler
lambdaInfo.setLogGroupName(context.getLogGroupName()); lambdaInfo.setLogGroupName(context.getLogGroupName());
lambdaInfo.setLogStreamName(context.getLogStreamName()); lambdaInfo.setLogStreamName(context.getLogStreamName());
lambdaInfo.setMemoryLimitInMb(context.getMemoryLimitInMB()); lambdaInfo.setMemoryLimitInMb(context.getMemoryLimitInMB());
return lambdaInfo; return lambdaInfo;
} }
private Map<String, String> headers() { private Map<String, String> headers() {
var headers = new HashMap<String, String>(); return Map.of("Content-Type", "application/json");
headers.put("Content-Type", "application/json");
return headers;
} }
} }

View File

@ -23,27 +23,23 @@
package com.iluwatar.serverless.baas.api; package com.iluwatar.serverless.baas.api;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.iluwatar.serverless.baas.api.FindPersonApiHandler;
import com.iluwatar.serverless.baas.api.SavePersonApiHandler;
import com.iluwatar.serverless.baas.model.Person; import com.iluwatar.serverless.baas.model.Person;
import java.util.Map;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import java.util.Collections;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/** /**
* Unit tests for FindPersonApiHandler * Unit tests for FindPersonApiHandler Created by dheeraj.mummar on 3/5/18.
* Created by dheeraj.mummar on 3/5/18.
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class FindPersonApiHandlerTest { public class FindPersonApiHandlerTest {
@ -66,8 +62,7 @@ public class FindPersonApiHandlerTest {
} }
private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent() { private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent() {
return new APIGatewayProxyRequestEvent() var request = new APIGatewayProxyRequestEvent();
.withPathParamters(Collections return request.withPathParamters(Map.of("id", "37e7a1fe-3544-473d-b764-18128f02d72d"));
.singletonMap("id", "37e7a1fe-3544-473d-b764-18128f02d72d"));
} }
} }

View File

@ -23,13 +23,15 @@
package com.iluwatar.serverless.baas.api; package com.iluwatar.serverless.baas.api;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.iluwatar.serverless.baas.api.SavePersonApiHandler;
import com.iluwatar.serverless.baas.model.Address; import com.iluwatar.serverless.baas.model.Address;
import com.iluwatar.serverless.baas.model.Person; import com.iluwatar.serverless.baas.model.Person;
import org.junit.Assert; import org.junit.Assert;
@ -39,11 +41,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
/** /**
* Unit tests for SavePersonApiHandler * Unit tests for SavePersonApiHandler Created by dheeraj.mummar on 3/4/18.
* Created by dheeraj.mummar on 3/4/18.
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class SavePersonApiHandlerTest { public class SavePersonApiHandlerTest {
@ -63,40 +62,40 @@ public class SavePersonApiHandlerTest {
@Test @Test
public void handleRequestSavePersonSuccessful() throws JsonProcessingException { public void handleRequestSavePersonSuccessful() throws JsonProcessingException {
Person person = newPerson(); var person = newPerson();
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = var body = objectMapper.writeValueAsString(person);
this.savePersonApiHandler var request = apiGatewayProxyRequestEvent(body);
.handleRequest(apiGatewayProxyRequestEvent(objectMapper.writeValueAsString(person)), mock(Context.class)); var ctx = mock(Context.class);
var apiGatewayProxyResponseEvent = this.savePersonApiHandler.handleRequest(request, ctx);
verify(dynamoDbMapper, times(1)).save(person); verify(dynamoDbMapper, times(1)).save(person);
Assert.assertNotNull(apiGatewayProxyResponseEvent); Assert.assertNotNull(apiGatewayProxyResponseEvent);
Assert.assertEquals(new Integer(201), apiGatewayProxyResponseEvent.getStatusCode()); Assert.assertEquals(Integer.valueOf(201), apiGatewayProxyResponseEvent.getStatusCode());
} }
@Test @Test
public void handleRequestSavePersonException() { public void handleRequestSavePersonException() {
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = var request = apiGatewayProxyRequestEvent("invalid sample request");
this.savePersonApiHandler var ctx = mock(Context.class);
.handleRequest(apiGatewayProxyRequestEvent("invalid sample request"), mock(Context.class)); var apiGatewayProxyResponseEvent = this.savePersonApiHandler.handleRequest(request, ctx);
Assert.assertNotNull(apiGatewayProxyResponseEvent); Assert.assertNotNull(apiGatewayProxyResponseEvent);
Assert.assertEquals(new Integer(400), apiGatewayProxyResponseEvent.getStatusCode()); Assert.assertEquals(Integer.valueOf(400), apiGatewayProxyResponseEvent.getStatusCode());
} }
private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent(String body) { private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent(String body) {
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent = new APIGatewayProxyRequestEvent(); var apiGatewayProxyRequestEvent = new APIGatewayProxyRequestEvent();
return apiGatewayProxyRequestEvent.withBody(body); return apiGatewayProxyRequestEvent.withBody(body);
} }
private Person newPerson() { private Person newPerson() {
Person person = new Person(); var person = new Person();
person.setFirstName("Thor"); person.setFirstName("Thor");
person.setLastName("Odinson"); person.setLastName("Odinson");
Address address = new Address(); var address = new Address();
address.setAddressLineOne("1 Odin ln"); address.setAddressLineOne("1 Odin ln");
address.setCity("Asgard"); address.setCity("Asgard");
address.setState("country of the Gods"); address.setState("country of the Gods");
address.setZipCode("00001"); address.setZipCode("00001");
person.setAddress(address); person.setAddress(address);
return person; return person;
} }
} }

View File

@ -23,16 +23,16 @@
package com.iluwatar.serverless.faas.api; package com.iluwatar.serverless.faas.api;
import com.amazonaws.services.lambda.runtime.Context;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.notNullValue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.amazonaws.services.lambda.runtime.Context;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
/** /**
* Unit tests for LambdaInfoApiHandler * Unit tests for LambdaInfoApiHandler
*/ */
@ -41,8 +41,8 @@ public class LambdaInfoApiHandlerTest {
@Test @Test
public void handleRequestWithMockContext() { public void handleRequestWithMockContext() {
LambdaInfoApiHandler lambdaInfoApiHandler = new LambdaInfoApiHandler(); var lambdaInfoApiHandler = new LambdaInfoApiHandler();
Context context = mock(Context.class); var context = mock(Context.class);
when(context.getAwsRequestId()).thenReturn("mock aws request id"); when(context.getAwsRequestId()).thenReturn("mock aws request id");
assertThat(lambdaInfoApiHandler.handleRequest(null, context), notNullValue()); assertThat(lambdaInfoApiHandler.handleRequest(null, context), notNullValue());

View File

@ -31,7 +31,6 @@ import com.iluwatar.servicelayer.spellbook.Spellbook;
import com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl; import com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl;
import com.iluwatar.servicelayer.wizard.Wizard; import com.iluwatar.servicelayer.wizard.Wizard;
import com.iluwatar.servicelayer.wizard.WizardDaoImpl; import com.iluwatar.servicelayer.wizard.WizardDaoImpl;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -178,29 +177,21 @@ public class App {
* Query the data. * Query the data.
*/ */
public static void queryData() { public static void queryData() {
var service = var wizardDao = new WizardDaoImpl();
new MagicServiceImpl(new WizardDaoImpl(), new SpellbookDaoImpl(), new SpellDaoImpl()); var spellbookDao = new SpellbookDaoImpl();
var spellDao = new SpellDaoImpl();
var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
LOGGER.info("Enumerating all wizards"); LOGGER.info("Enumerating all wizards");
for (Wizard w : service.findAllWizards()) { service.findAllWizards().stream().map(Wizard::getName).forEach(LOGGER::info);
LOGGER.info(w.getName());
}
LOGGER.info("Enumerating all spellbooks"); LOGGER.info("Enumerating all spellbooks");
for (Spellbook s : service.findAllSpellbooks()) { service.findAllSpellbooks().stream().map(Spellbook::getName).forEach(LOGGER::info);
LOGGER.info(s.getName());
}
LOGGER.info("Enumerating all spells"); LOGGER.info("Enumerating all spells");
for (Spell s : service.findAllSpells()) { service.findAllSpells().stream().map(Spell::getName).forEach(LOGGER::info);
LOGGER.info(s.getName());
}
LOGGER.info("Find wizards with spellbook 'Book of Idores'"); LOGGER.info("Find wizards with spellbook 'Book of Idores'");
List<Wizard> wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores"); var wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores");
for (Wizard w : wizardsWithSpellbook) { wizardsWithSpellbook.forEach(w -> LOGGER.info("{} has 'Book of Idores'", w.getName()));
LOGGER.info("{} has 'Book of Idores'", w.getName());
}
LOGGER.info("Find wizards with spell 'Fireball'"); LOGGER.info("Find wizards with spell 'Fireball'");
List<Wizard> wizardsWithSpell = service.findWizardsWithSpell("Fireball"); var wizardsWithSpell = service.findWizardsWithSpell("Fireball");
for (Wizard w : wizardsWithSpell) { wizardsWithSpell.forEach(w -> LOGGER.info("{} has 'Fireball'", w.getName()));
LOGGER.info("{} has 'Fireball'", w.getName());
}
} }
} }

View File

@ -52,10 +52,9 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
@Override @Override
public E find(Long id) { public E find(Long id) {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
E result = null; E result;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
var criteria = session.createCriteria(persistentClass); var criteria = session.createCriteria(persistentClass);
criteria.add(Restrictions.idEq(id)); criteria.add(Restrictions.idEq(id));
@ -66,17 +65,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
return result; return result;
} }
@Override @Override
public void persist(E entity) { public void persist(E entity) {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
session.persist(entity); session.persist(entity);
tx.commit(); tx.commit();
@ -85,17 +81,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
} }
@Override @Override
public E merge(E entity) { public E merge(E entity) {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
E result = null; E result = null;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
result = (E) session.merge(entity); result = (E) session.merge(entity);
tx.commit(); tx.commit();
@ -104,17 +97,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
return result; return result;
} }
@Override @Override
public void delete(E entity) { public void delete(E entity) {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
session.delete(entity); session.delete(entity);
tx.commit(); tx.commit();
@ -123,17 +113,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
} }
@Override @Override
public List<E> findAll() { public List<E> findAll() {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
List<E> result = null; List<E> result;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
Criteria criteria = session.createCriteria(persistentClass); Criteria criteria = session.createCriteria(persistentClass);
result = criteria.list(); result = criteria.list();
@ -142,8 +129,6 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
return result; return result;
} }

View File

@ -54,8 +54,9 @@ public final class HibernateUtil {
public static synchronized SessionFactory getSessionFactory() { public static synchronized SessionFactory getSessionFactory() {
if (sessionFactory == null) { if (sessionFactory == null) {
try { try {
sessionFactory = sessionFactory = new Configuration()
new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class) .addAnnotatedClass(Wizard.class)
.addAnnotatedClass(Spellbook.class)
.addAnnotatedClass(Spell.class) .addAnnotatedClass(Spell.class)
.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect") .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1") .setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")

View File

@ -35,7 +35,7 @@ public class SpellDaoImpl extends DaoBaseImpl<Spell> implements SpellDao {
@Override @Override
public Spell findByName(String name) { public Spell findByName(String name) {
Transaction tx = null; Transaction tx = null;
Spell result = null; Spell result;
try (var session = getSessionFactory().openSession()) { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
var criteria = session.createCriteria(persistentClass); var criteria = session.createCriteria(persistentClass);

View File

@ -34,24 +34,19 @@ public class SpellbookDaoImpl extends DaoBaseImpl<Spellbook> implements Spellboo
@Override @Override
public Spellbook findByName(String name) { public Spellbook findByName(String name) {
var session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
Spellbook result = null; Spellbook result;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
var criteria = session.createCriteria(persistentClass); var criteria = session.createCriteria(persistentClass);
criteria.add(Restrictions.eq("name", name)); criteria.add(Restrictions.eq("name", name));
result = (Spellbook) criteria.uniqueResult(); result = (Spellbook) criteria.uniqueResult();
result.getSpells().size();
result.getWizards().size();
tx.commit(); tx.commit();
} catch (Exception e) { } catch (Exception e) {
if (tx != null) { if (tx != null) {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
return result; return result;
} }

View File

@ -24,9 +24,6 @@
package com.iluwatar.servicelayer.wizard; package com.iluwatar.servicelayer.wizard;
import com.iluwatar.servicelayer.common.DaoBaseImpl; import com.iluwatar.servicelayer.common.DaoBaseImpl;
import com.iluwatar.servicelayer.spellbook.Spellbook;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
@ -37,25 +34,19 @@ public class WizardDaoImpl extends DaoBaseImpl<Wizard> implements WizardDao {
@Override @Override
public Wizard findByName(String name) { public Wizard findByName(String name) {
Session session = getSessionFactory().openSession();
Transaction tx = null; Transaction tx = null;
Wizard result = null; Wizard result;
try { try (var session = getSessionFactory().openSession()) {
tx = session.beginTransaction(); tx = session.beginTransaction();
Criteria criteria = session.createCriteria(persistentClass); var criteria = session.createCriteria(persistentClass);
criteria.add(Restrictions.eq("name", name)); criteria.add(Restrictions.eq("name", name));
result = (Wizard) criteria.uniqueResult(); result = (Wizard) criteria.uniqueResult();
for (Spellbook s : result.getSpellbooks()) {
s.getSpells().size();
}
tx.commit(); tx.commit();
} catch (Exception e) { } catch (Exception e) {
if (tx != null) { if (tx != null) {
tx.rollback(); tx.rollback();
} }
throw e; throw e;
} finally {
session.close();
} }
return result; return result;
} }

View File

@ -28,16 +28,13 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
@AfterEach @AfterEach

View File

@ -23,22 +23,20 @@
package com.iluwatar.servicelayer.common; package com.iluwatar.servicelayer.common;
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 10:53 PM * Date: 12/28/15 - 10:53 PM Test for Base Data Access Objects
* Test for Base Data Access Objects *
* @param <E> Type of Base Entity * @param <E> Type of Base Entity
* @param <D> Type of Dao Base Implementation * @param <D> Type of Dao Base Implementation
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
@ -79,8 +77,8 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
for (int i = 0; i < INITIAL_COUNT; i++) { for (int i = 0; i < INITIAL_COUNT; i++) {
final String className = dao.persistentClass.getSimpleName(); final var className = dao.persistentClass.getSimpleName();
final String entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet()); final var entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet());
this.dao.persist(this.factory.apply(entityName)); this.dao.persist(this.factory.apply(entityName));
} }
} }
@ -96,9 +94,9 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
@Test @Test
public void testFind() { public void testFind() {
final List<E> all = this.dao.findAll(); final var all = this.dao.findAll();
for (final E entity : all) { for (final var entity : all) {
final E byId = this.dao.find(entity.getId()); final var byId = this.dao.find(entity.getId());
assertNotNull(byId); assertNotNull(byId);
assertEquals(byId.getId(), byId.getId()); assertEquals(byId.getId(), byId.getId());
} }
@ -106,39 +104,39 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
@Test @Test
public void testDelete() { public void testDelete() {
final List<E> originalEntities = this.dao.findAll(); final var originalEntities = this.dao.findAll();
this.dao.delete(originalEntities.get(1)); this.dao.delete(originalEntities.get(1));
this.dao.delete(originalEntities.get(2)); this.dao.delete(originalEntities.get(2));
final List<E> entitiesLeft = this.dao.findAll(); final var entitiesLeft = this.dao.findAll();
assertNotNull(entitiesLeft); assertNotNull(entitiesLeft);
assertEquals(INITIAL_COUNT - 2, entitiesLeft.size()); assertEquals(INITIAL_COUNT - 2, entitiesLeft.size());
} }
@Test @Test
public void testFindAll() { public void testFindAll() {
final List<E> all = this.dao.findAll(); final var all = this.dao.findAll();
assertNotNull(all); assertNotNull(all);
assertEquals(INITIAL_COUNT, all.size()); assertEquals(INITIAL_COUNT, all.size());
} }
@Test @Test
public void testSetId() { public void testSetId() {
final E entity = this.factory.apply("name"); final var entity = this.factory.apply("name");
assertNull(entity.getId()); assertNull(entity.getId());
final Long expectedId = 1L; final var expectedId = 1L;
entity.setId(expectedId); entity.setId(expectedId);
assertEquals(expectedId, entity.getId()); assertEquals(expectedId, entity.getId());
} }
@Test @Test
public void testSetName() { public void testSetName() {
final E entity = this.factory.apply("name"); final var entity = this.factory.apply("name");
assertEquals("name", entity.getName()); assertEquals("name", entity.getName());
assertEquals("name", entity.toString()); assertEquals("name", entity.toString());
final String expectedName = "new name"; final var expectedName = "new name";
entity.setName(expectedName); entity.setName(expectedName);
assertEquals(expectedName, entity.getName()); assertEquals(expectedName, entity.getName());
assertEquals(expectedName, entity.toString()); assertEquals(expectedName, entity.toString());

View File

@ -23,18 +23,6 @@
package com.iluwatar.servicelayer.magic; package com.iluwatar.servicelayer.magic;
import com.iluwatar.servicelayer.spell.Spell;
import com.iluwatar.servicelayer.spell.SpellDao;
import com.iluwatar.servicelayer.spellbook.Spellbook;
import com.iluwatar.servicelayer.spellbook.SpellbookDao;
import com.iluwatar.servicelayer.wizard.Wizard;
import com.iluwatar.servicelayer.wizard.WizardDao;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
@ -44,6 +32,15 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.iluwatar.servicelayer.spell.Spell;
import com.iluwatar.servicelayer.spell.SpellDao;
import com.iluwatar.servicelayer.spellbook.Spellbook;
import com.iluwatar.servicelayer.spellbook.SpellbookDao;
import com.iluwatar.servicelayer.wizard.Wizard;
import com.iluwatar.servicelayer.wizard.WizardDao;
import java.util.Set;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/29/15 - 12:06 AM * Date: 12/29/15 - 12:06 AM
* *
@ -53,11 +50,11 @@ public class MagicServiceImplTest {
@Test @Test
public void testFindAllWizards() { public void testFindAllWizards() {
final WizardDao wizardDao = mock(WizardDao.class); final var wizardDao = mock(WizardDao.class);
final SpellbookDao spellbookDao = mock(SpellbookDao.class); final var spellbookDao = mock(SpellbookDao.class);
final SpellDao spellDao = mock(SpellDao.class); final var spellDao = mock(SpellDao.class);
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
verifyZeroInteractions(wizardDao, spellbookDao, spellDao); verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
service.findAllWizards(); service.findAllWizards();
@ -66,12 +63,12 @@ public class MagicServiceImplTest {
} }
@Test @Test
public void testFindAllSpellbooks() throws Exception { public void testFindAllSpellbooks() {
final WizardDao wizardDao = mock(WizardDao.class); final var wizardDao = mock(WizardDao.class);
final SpellbookDao spellbookDao = mock(SpellbookDao.class); final var spellbookDao = mock(SpellbookDao.class);
final SpellDao spellDao = mock(SpellDao.class); final var spellDao = mock(SpellDao.class);
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
verifyZeroInteractions(wizardDao, spellbookDao, spellDao); verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
service.findAllSpellbooks(); service.findAllSpellbooks();
@ -80,12 +77,12 @@ public class MagicServiceImplTest {
} }
@Test @Test
public void testFindAllSpells() throws Exception { public void testFindAllSpells() {
final WizardDao wizardDao = mock(WizardDao.class); final var wizardDao = mock(WizardDao.class);
final SpellbookDao spellbookDao = mock(SpellbookDao.class); final var spellbookDao = mock(SpellbookDao.class);
final SpellDao spellDao = mock(SpellDao.class); final var spellDao = mock(SpellDao.class);
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
verifyZeroInteractions(wizardDao, spellbookDao, spellDao); verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
service.findAllSpells(); service.findAllSpells();
@ -94,26 +91,27 @@ public class MagicServiceImplTest {
} }
@Test @Test
public void testFindWizardsWithSpellbook() throws Exception { public void testFindWizardsWithSpellbook() {
final String bookname = "bookname"; final var bookname = "bookname";
final Spellbook spellbook = mock(Spellbook.class); final var spellbook = mock(Spellbook.class);
final Set<Wizard> wizards = Set.of( final var wizards = Set.of(
mock(Wizard.class), mock(Wizard.class),
mock(Wizard.class), mock(Wizard.class),
mock(Wizard.class)); mock(Wizard.class)
);
when(spellbook.getWizards()).thenReturn(wizards); when(spellbook.getWizards()).thenReturn(wizards);
final SpellbookDao spellbookDao = mock(SpellbookDao.class); final var spellbookDao = mock(SpellbookDao.class);
when(spellbookDao.findByName(eq(bookname))).thenReturn(spellbook); when(spellbookDao.findByName(eq(bookname))).thenReturn(spellbook);
final WizardDao wizardDao = mock(WizardDao.class); final var wizardDao = mock(WizardDao.class);
final SpellDao spellDao = mock(SpellDao.class); final var spellDao = mock(SpellDao.class);
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook);
final List<Wizard> result = service.findWizardsWithSpellbook(bookname); final var result = service.findWizardsWithSpellbook(bookname);
verify(spellbookDao).findByName(eq(bookname)); verify(spellbookDao).findByName(eq(bookname));
verify(spellbook).getWizards(); verify(spellbook).getWizards();
@ -125,27 +123,28 @@ public class MagicServiceImplTest {
@Test @Test
public void testFindWizardsWithSpell() throws Exception { public void testFindWizardsWithSpell() throws Exception {
final Set<Wizard> wizards = Set.of( final var wizards = Set.of(
mock(Wizard.class), mock(Wizard.class),
mock(Wizard.class), mock(Wizard.class),
mock(Wizard.class)); mock(Wizard.class)
final Spellbook spellbook = mock(Spellbook.class); );
final var spellbook = mock(Spellbook.class);
when(spellbook.getWizards()).thenReturn(wizards); when(spellbook.getWizards()).thenReturn(wizards);
final SpellbookDao spellbookDao = mock(SpellbookDao.class); final var spellbookDao = mock(SpellbookDao.class);
final WizardDao wizardDao = mock(WizardDao.class); final var wizardDao = mock(WizardDao.class);
final Spell spell = mock(Spell.class); final var spell = mock(Spell.class);
when(spell.getSpellbook()).thenReturn(spellbook); when(spell.getSpellbook()).thenReturn(spellbook);
final String spellName = "spellname"; final var spellName = "spellname";
final SpellDao spellDao = mock(SpellDao.class); final var spellDao = mock(SpellDao.class);
when(spellDao.findByName(eq(spellName))).thenReturn(spell); when(spellDao.findByName(eq(spellName))).thenReturn(spell);
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook);
final List<Wizard> result = service.findWizardsWithSpell(spellName); final var result = service.findWizardsWithSpell(spellName);
verify(spellDao).findByName(eq(spellName)); verify(spellDao).findByName(eq(spellName));
verify(spellbook).getWizards(); verify(spellbook).getWizards();

View File

@ -23,14 +23,12 @@
package com.iluwatar.servicelayer.spell; package com.iluwatar.servicelayer.spell;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 11:02 PM * Date: 12/28/15 - 11:02 PM
* *
@ -44,10 +42,10 @@ public class SpellDaoImplTest extends BaseDaoTest<Spell, SpellDaoImpl> {
@Test @Test
public void testFindByName() { public void testFindByName() {
final SpellDaoImpl dao = getDao(); final var dao = getDao();
final List<Spell> allSpells = dao.findAll(); final var allSpells = dao.findAll();
for (final Spell spell : allSpells) { for (final var spell : allSpells) {
final Spell spellByName = dao.findByName(spell.getName()); final var spellByName = dao.findByName(spell.getName());
assertNotNull(spellByName); assertNotNull(spellByName);
assertEquals(spell.getId(), spellByName.getId()); assertEquals(spell.getId(), spellByName.getId());
assertEquals(spell.getName(), spellByName.getName()); assertEquals(spell.getName(), spellByName.getName());

View File

@ -23,14 +23,12 @@
package com.iluwatar.servicelayer.spellbook; package com.iluwatar.servicelayer.spellbook;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 11:44 PM * Date: 12/28/15 - 11:44 PM
* *
@ -44,10 +42,10 @@ public class SpellbookDaoImplTest extends BaseDaoTest<Spellbook, SpellbookDaoImp
@Test @Test
public void testFindByName() { public void testFindByName() {
final SpellbookDaoImpl dao = getDao(); final var dao = getDao();
final List<Spellbook> allBooks = dao.findAll(); final var allBooks = dao.findAll();
for (final Spellbook book : allBooks) { for (final var book : allBooks) {
final Spellbook spellByName = dao.findByName(book.getName()); final var spellByName = dao.findByName(book.getName());
assertNotNull(spellByName); assertNotNull(spellByName);
assertEquals(book.getId(), spellByName.getId()); assertEquals(book.getId(), spellByName.getId());
assertEquals(book.getName(), spellByName.getName()); assertEquals(book.getName(), spellByName.getName());

View File

@ -23,14 +23,12 @@
package com.iluwatar.servicelayer.wizard; package com.iluwatar.servicelayer.wizard;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.iluwatar.servicelayer.common.BaseDaoTest;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/28/15 - 11:46 PM * Date: 12/28/15 - 11:46 PM
* *
@ -44,10 +42,10 @@ public class WizardDaoImplTest extends BaseDaoTest<Wizard, WizardDaoImpl> {
@Test @Test
public void testFindByName() { public void testFindByName() {
final WizardDaoImpl dao = getDao(); final var dao = getDao();
final List<Wizard> allWizards = dao.findAll(); final var allWizards = dao.findAll();
for (final Wizard spell : allWizards) { for (final var spell : allWizards) {
final Wizard byName = dao.findByName(spell.getName()); final var byName = dao.findByName(spell.getName());
assertNotNull(byName); assertNotNull(byName);
assertEquals(spell.getId(), byName.getId()); assertEquals(spell.getId(), byName.getId());
assertEquals(spell.getName(), byName.getName()); assertEquals(spell.getName(), byName.getName());

View File

@ -53,16 +53,15 @@ public class ServiceCache {
* @return {@link Service} * @return {@link Service}
*/ */
public Service getService(String serviceName) { public Service getService(String serviceName) {
Service cachedService = null; if (serviceCache.containsKey(serviceName)) {
for (String serviceJndiName : serviceCache.keySet()) { var cachedService = serviceCache.get(serviceName);
if (serviceJndiName.equals(serviceName)) { var name = cachedService.getName();
cachedService = serviceCache.get(serviceJndiName); var id = cachedService.getId();
LOGGER.info("(cache call) Fetched service {}({}) from cache... !", LOGGER.info("(cache call) Fetched service {}({}) from cache... !", name, id);
cachedService.getName(), cachedService.getId());
}
}
return cachedService; return cachedService;
} }
return null;
}
/** /**
* Adds the service into the cache map. * Adds the service into the cache map.

View File

@ -26,15 +26,12 @@ package com.iluwatar.servicelocator;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -23,14 +23,15 @@
package com.iluwatar.servicelocator; package com.iluwatar.servicelocator;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/29/15 - 19:07 PM * Date: 12/29/15 - 19:07 PM
* *
@ -52,12 +53,10 @@ public class ServiceLocatorTest {
*/ */
@Test @Test
public void testServiceCache() { public void testServiceCache() {
final String[] serviceNames = new String[]{ final var serviceNames = List.of("jndi/serviceA", "jndi/serviceB");
"jndi/serviceA", "jndi/serviceB"
};
for (final String serviceName : serviceNames) { for (final var serviceName : serviceNames) {
final Service service = ServiceLocator.getService(serviceName); final var service = ServiceLocator.getService(serviceName);
assertNotNull(service); assertNotNull(service);
assertEquals(serviceName, service.getName()); assertEquals(serviceName, service.getName());
assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1' assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1'

View File

@ -24,14 +24,14 @@
package com.iluwatar.sharding; package com.iluwatar.sharding;
/** /**
* Sharding pattern means dividing a data store into a set of horizontal partitions * Sharding pattern means dividing a data store into a set of horizontal partitions or shards. This
* or shards. This pattern can improve scalability when storing and accessing large * pattern can improve scalability when storing and accessing large volumes of data.
* volumes of data.
*/ */
public class App { public class App {
/** /**
* Program main entry point. * Program main entry point.
*
* @param args program runtime arguments * @param args program runtime arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
@ -45,7 +45,7 @@ public class App {
var shard2 = new Shard(2); var shard2 = new Shard(2);
var shard3 = new Shard(3); var shard3 = new Shard(3);
ShardManager manager = new LookupShardManager(); var manager = new LookupShardManager();
manager.addNewShard(shard1); manager.addNewShard(shard1);
manager.addNewShard(shard2); manager.addNewShard(shard2);
manager.addNewShard(shard3); manager.addNewShard(shard3);
@ -58,27 +58,27 @@ public class App {
shard2.clearData(); shard2.clearData();
shard3.clearData(); shard3.clearData();
manager = new RangeShardManager(); var rangeShardManager = new RangeShardManager();
manager.addNewShard(shard1); rangeShardManager.addNewShard(shard1);
manager.addNewShard(shard2); rangeShardManager.addNewShard(shard2);
manager.addNewShard(shard3); rangeShardManager.addNewShard(shard3);
manager.storeData(data1); rangeShardManager.storeData(data1);
manager.storeData(data2); rangeShardManager.storeData(data2);
manager.storeData(data3); rangeShardManager.storeData(data3);
manager.storeData(data4); rangeShardManager.storeData(data4);
shard1.clearData(); shard1.clearData();
shard2.clearData(); shard2.clearData();
shard3.clearData(); shard3.clearData();
manager = new HashShardManager(); var hashShardManager = new HashShardManager();
manager.addNewShard(shard1); hashShardManager.addNewShard(shard1);
manager.addNewShard(shard2); hashShardManager.addNewShard(shard2);
manager.addNewShard(shard3); hashShardManager.addNewShard(shard3);
manager.storeData(data1); hashShardManager.storeData(data1);
manager.storeData(data2); hashShardManager.storeData(data2);
manager.storeData(data3); hashShardManager.storeData(data3);
manager.storeData(data4); hashShardManager.storeData(data4);
shard1.clearData(); shard1.clearData();
shard2.clearData(); shard2.clearData();

View File

@ -58,8 +58,7 @@ public class LookupShardManager extends ShardManager {
return lookupMap.get(key); return lookupMap.get(key);
} else { } else {
var shardCount = shardMap.size(); var shardCount = shardMap.size();
var allocatedShardId = new Random().nextInt(shardCount - 1) + 1; return new Random().nextInt(shardCount - 1) + 1;
return allocatedShardId;
} }
} }

View File

@ -27,8 +27,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* ShardManager with range strategy. This strategy groups related items together * ShardManager with range strategy. This strategy groups related items together in the same shard,
* in the same shard, and orders them by shard key. * and orders them by shard key.
*/ */
public class RangeShardManager extends ShardManager { public class RangeShardManager extends ShardManager {
@ -46,21 +46,16 @@ public class RangeShardManager extends ShardManager {
@Override @Override
protected int allocateShard(Data data) { protected int allocateShard(Data data) {
var type = data.getType(); var type = data.getType();
var shardId = -1;
switch (type) { switch (type) {
case type1: case type1:
shardId = 1; return 1;
break;
case type2: case type2:
shardId = 2; return 2;
break;
case type3: case type3:
shardId = 3; return 3;
break;
default: default:
break; return -1;
} }
return shardId;
} }
} }

View File

@ -32,8 +32,7 @@ public class AppTest {
@Test @Test
public void testMain() { public void testMain() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -24,7 +24,6 @@
package com.iluwatar.sharding; package com.iluwatar.sharding;
import java.util.Map; import java.util.Map;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -57,7 +56,7 @@ public class LookupShardManagerTest {
lookupShardManager.storeData(data); lookupShardManager.storeData(data);
var field = LookupShardManager.class.getDeclaredField("lookupMap"); var field = LookupShardManager.class.getDeclaredField("lookupMap");
field.setAccessible(true); field.setAccessible(true);
Map<Integer, Integer> lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager); var lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager);
var shardId = lookupMap.get(1); var shardId = lookupMap.get(1);
var shard = lookupShardManager.getShardById(shardId); var shard = lookupShardManager.getShardById(shardId);
Assert.assertEquals(data, shard.getDataById(1)); Assert.assertEquals(data, shard.getDataById(1));

View File

@ -24,7 +24,6 @@
package com.iluwatar.sharding; package com.iluwatar.sharding;
import java.util.Map; import java.util.Map;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -57,7 +56,7 @@ public class ShardManagerTest {
shardManager.addNewShard(shard); shardManager.addNewShard(shard);
var field = ShardManager.class.getDeclaredField("shardMap"); var field = ShardManager.class.getDeclaredField("shardMap");
field.setAccessible(true); field.setAccessible(true);
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager); var map = (Map<Integer, Shard>) field.get(shardManager);
Assert.assertEquals(1, map.size()); Assert.assertEquals(1, map.size());
Assert.assertEquals(shard, map.get(1)); Assert.assertEquals(shard, map.get(1));
} catch (NoSuchFieldException | IllegalAccessException e) { } catch (NoSuchFieldException | IllegalAccessException e) {
@ -73,7 +72,7 @@ public class ShardManagerTest {
boolean flag = shardManager.removeShardById(1); boolean flag = shardManager.removeShardById(1);
var field = ShardManager.class.getDeclaredField("shardMap"); var field = ShardManager.class.getDeclaredField("shardMap");
field.setAccessible(true); field.setAccessible(true);
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager); var map = (Map<Integer, Shard>) field.get(shardManager);
Assert.assertEquals(true, flag); Assert.assertEquals(true, flag);
Assert.assertEquals(0, map.size()); Assert.assertEquals(0, map.size());
} catch (IllegalAccessException | NoSuchFieldException e) { } catch (IllegalAccessException | NoSuchFieldException e) {
@ -83,9 +82,9 @@ public class ShardManagerTest {
@Test @Test
public void testGetShardById() { public void testGetShardById() {
Shard shard = new Shard(1); var shard = new Shard(1);
shardManager.addNewShard(shard); shardManager.addNewShard(shard);
Shard tmpShard = shardManager.getShardById(1); var tmpShard = shardManager.getShardById(1);
Assert.assertEquals(shard, tmpShard); Assert.assertEquals(shard, tmpShard);
} }

View File

@ -25,7 +25,6 @@ package com.iluwatar.sharding;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -48,7 +47,8 @@ public class ShardTest {
} }
@After @After
public void tearDown() {} public void tearDown() {
}
@Test @Test
public void testStoreData() { public void testStoreData() {
@ -56,7 +56,7 @@ public class ShardTest {
shard.storeData(data); shard.storeData(data);
var field = Shard.class.getDeclaredField("dataStore"); var field = Shard.class.getDeclaredField("dataStore");
field.setAccessible(true); field.setAccessible(true);
Map<Integer, Data> dataMap = (Map<Integer, Data>) field.get(shard); var dataMap = (Map<Integer, Data>) field.get(shard);
Assert.assertEquals(1, dataMap.size()); Assert.assertEquals(1, dataMap.size());
Assert.assertEquals(data, dataMap.get(1)); Assert.assertEquals(data, dataMap.get(1));
} catch (NoSuchFieldException | IllegalAccessException e) { } catch (NoSuchFieldException | IllegalAccessException e) {
@ -68,13 +68,13 @@ public class ShardTest {
@Test @Test
public void testClearData() { public void testClearData() {
try { try {
Map<Integer, Data> dataMap = new HashMap<>(); var dataMap = new HashMap<Integer, Data>();
dataMap.put(1, data); dataMap.put(1, data);
var field = Shard.class.getDeclaredField("dataStore"); var field = Shard.class.getDeclaredField("dataStore");
field.setAccessible(true); field.setAccessible(true);
field.set(shard, dataMap); field.set(shard, dataMap);
shard.clearData(); shard.clearData();
dataMap = (Map<Integer, Data>) field.get(shard); dataMap = (HashMap<Integer, Data>) field.get(shard);
Assert.assertEquals(0, dataMap.size()); Assert.assertEquals(0, dataMap.size());
} catch (NoSuchFieldException | IllegalAccessException e) { } catch (NoSuchFieldException | IllegalAccessException e) {
Assert.fail("Fail to modify field access."); Assert.fail("Fail to modify field access.");

View File

@ -41,8 +41,8 @@ public enum EnumIvoryTower {
Then in order to use Then in order to use
```java ```java
EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE; var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE; var enumIvoryTower2 = EnumIvoryTower.INSTANCE;
assertEquals(enumIvoryTower1, enumIvoryTower2); // true assertEquals(enumIvoryTower1, enumIvoryTower2); // true
``` ```

View File

@ -45,8 +45,7 @@ import org.slf4j.LoggerFactory;
* example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple. * example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple.
* However, you should be aware of the downsides including committing to implementation strategy, * However, you should be aware of the downsides including committing to implementation strategy,
* extending the enum class, serializability and restrictions to coding. These are extensively * extending the enum class, serializability and restrictions to coding. These are extensively
* discussed in Stack Overflow: * discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* -a-singleton-with-javas-enum</p> * -a-singleton-with-javas-enum</p>
* *
* <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on * <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
@ -54,9 +53,9 @@ import org.slf4j.LoggerFactory;
* synchronized.</p> * synchronized.</p>
* *
* <p>Another Singleton implementation that is initialized on demand is found in * <p>Another Singleton implementation that is initialized on demand is found in
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than * {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link
* {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but * ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the
* only the method internals on specific conditions.</p> * method internals on specific conditions.</p>
* *
* <p>Yet another way to implement thread safe lazily initialized Singleton can be found in * <p>Yet another way to implement thread safe lazily initialized Singleton can be found in
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8 * {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
@ -80,10 +79,8 @@ public class App {
LOGGER.info("ivoryTower2={}", ivoryTower2); LOGGER.info("ivoryTower2={}", ivoryTower2);
// lazily initialized singleton // lazily initialized singleton
var threadSafeIvoryTower1 = var threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower.getInstance();
ThreadSafeLazyLoadedIvoryTower.getInstance(); var threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower.getInstance();
var threadSafeIvoryTower2 =
ThreadSafeLazyLoadedIvoryTower.getInstance();
LOGGER.info("threadSafeIvoryTower1={}", threadSafeIvoryTower1); LOGGER.info("threadSafeIvoryTower1={}", threadSafeIvoryTower1);
LOGGER.info("threadSafeIvoryTower2={}", threadSafeIvoryTower2); LOGGER.info("threadSafeIvoryTower2={}", threadSafeIvoryTower2);
@ -100,11 +97,9 @@ public class App {
LOGGER.info(dcl2.toString()); LOGGER.info(dcl2.toString());
// initialize on demand holder idiom // initialize on demand holder idiom
var demandHolderIdiom = var demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance();
InitializingOnDemandHolderIdiom.getInstance();
LOGGER.info(demandHolderIdiom.toString()); LOGGER.info(demandHolderIdiom.toString());
var demandHolderIdiom2 = var demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance();
InitializingOnDemandHolderIdiom.getInstance();
LOGGER.info(demandHolderIdiom2.toString()); LOGGER.info(demandHolderIdiom2.toString());
} }
} }

View File

@ -32,7 +32,6 @@ public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -29,13 +29,11 @@ import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout; import static org.junit.jupiter.api.Assertions.assertTimeout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@ -73,9 +71,9 @@ public abstract class SingletonTest<S> {
@Test @Test
public void testMultipleCallsReturnTheSameObjectInSameThread() { public void testMultipleCallsReturnTheSameObjectInSameThread() {
// Create several instances in the same calling thread // Create several instances in the same calling thread
S instance1 = this.singletonInstanceMethod.get(); var instance1 = this.singletonInstanceMethod.get();
S instance2 = this.singletonInstanceMethod.get(); var instance2 = this.singletonInstanceMethod.get();
S instance3 = this.singletonInstanceMethod.get(); var instance3 = this.singletonInstanceMethod.get();
// now check they are equal // now check they are equal
assertSame(instance1, instance2); assertSame(instance1, instance2);
assertSame(instance1, instance3); assertSame(instance1, instance3);
@ -89,19 +87,18 @@ public abstract class SingletonTest<S> {
public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception { public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception {
assertTimeout(ofMillis(10000), () -> { assertTimeout(ofMillis(10000), () -> {
// Create 10000 tasks and inside each callable instantiate the singleton class // Create 10000 tasks and inside each callable instantiate the singleton class
final List<Callable<S>> tasks = new ArrayList<>(); final var tasks = IntStream.range(0, 10000)
for (int i = 0; i < 10000; i++) { .<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
tasks.add(this.singletonInstanceMethod::get); .collect(Collectors.toCollection(ArrayList::new));
}
// Use up to 8 concurrent threads to handle the tasks // Use up to 8 concurrent threads to handle the tasks
final ExecutorService executorService = Executors.newFixedThreadPool(8); final var executorService = Executors.newFixedThreadPool(8);
final List<Future<S>> results = executorService.invokeAll(tasks); final var results = executorService.invokeAll(tasks);
// wait for all of the threads to complete // wait for all of the threads to complete
final S expectedInstance = this.singletonInstanceMethod.get(); final var expectedInstance = this.singletonInstanceMethod.get();
for (Future<S> res : results) { for (var res : results) {
final S instance = res.get(); final var instance = res.get();
assertNotNull(instance); assertNotNull(instance);
assertSame(expectedInstance, instance); assertSame(expectedInstance, instance);
} }

View File

@ -23,9 +23,7 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import org.junit.Test; import org.junit.Test;
/** /**
@ -47,11 +45,10 @@ public class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDo
*/ */
@Test(expected = InvocationTargetException.class) @Test(expected = InvocationTargetException.class)
public void testCreatingNewInstanceByRefection() throws Exception { public void testCreatingNewInstanceByRefection() throws Exception {
ThreadSafeDoubleCheckLocking instance1 = ThreadSafeDoubleCheckLocking.getInstance(); ThreadSafeDoubleCheckLocking.getInstance();
Constructor constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor(); var constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
constructor.setAccessible(true); constructor.setAccessible(true);
ThreadSafeDoubleCheckLocking instance2 = constructor.newInstance((Object[]) null);
(ThreadSafeDoubleCheckLocking) constructor.newInstance(null);
} }
} }

View File

@ -19,9 +19,9 @@ Say, you are building a war game with hundreds, or maybe even thousands of playe
```java ```java
public void handleMeLee(Unit units[], int numUnits) { public void handleMeLee(Unit units[], int numUnits) {
for (int a = 0; a < numUnits - 1; a++) for (var a = 0; a < numUnits - 1; a++)
{ {
for (int b = a + 1; b < numUnits; b++) for (var b = a + 1; b < numUnits; b++)
{ {
if (units[a].position() == units[b].position()) if (units[a].position() == units[b].position())
{ {

View File

@ -23,8 +23,6 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Random; import java.util.Random;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -62,58 +60,46 @@ import org.slf4j.LoggerFactory;
public class App { public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
static void noSpatialPartition(int height, int width, static void noSpatialPartition(int numOfMovements, Hashtable<Integer, Bubble> bubbles) {
int numOfMovements, Hashtable<Integer, Bubble> bubbles) { //all bubbles have to be checked for collision for all bubbles
ArrayList<Point> bubblesToCheck = new ArrayList<Point>(); var bubblesToCheck = bubbles.values();
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
bubblesToCheck.add(bubbles
.get(e.nextElement())); //all bubbles have to be checked for collision for all bubbles
}
//will run numOfMovement times or till all bubbles have popped //will run numOfMovement times or till all bubbles have popped
while (numOfMovements > 0 && !bubbles.isEmpty()) { while (numOfMovements > 0 && !bubbles.isEmpty()) {
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) { bubbles.forEach((i, bubble) -> {
Integer i = e.nextElement();
// bubble moves, new position gets updated // bubble moves, new position gets updated
// and collisions are checked with all bubbles in bubblesToCheck // and collisions are checked with all bubbles in bubblesToCheck
bubbles.get(i).move(); bubble.move();
bubbles.replace(i, bubbles.get(i)); bubbles.replace(i, bubble);
bubbles.get(i).handleCollision(bubblesToCheck, bubbles); bubble.handleCollision(bubblesToCheck, bubbles);
} });
numOfMovements--; numOfMovements--;
} }
for (Integer key : bubbles.keySet()) {
//bubbles not popped //bubbles not popped
LOGGER.info("Bubble " + key + " not popped"); bubbles.keySet().stream().map(key -> "Bubble " + key + " not popped").forEach(LOGGER::info);
}
} }
static void withSpatialPartition( static void withSpatialPartition(
int height, int width, int numOfMovements, Hashtable<Integer, Bubble> bubbles) { int height, int width, int numOfMovements, Hashtable<Integer, Bubble> bubbles) {
//creating quadtree //creating quadtree
Rect rect = new Rect(width / 2, height / 2, width, height); var rect = new Rect(width / 2, height / 2, width, height);
QuadTree quadTree = new QuadTree(rect, 4); var quadTree = new QuadTree(rect, 4);
//will run numOfMovement times or till all bubbles have popped //will run numOfMovement times or till all bubbles have popped
while (numOfMovements > 0 && !bubbles.isEmpty()) { while (numOfMovements > 0 && !bubbles.isEmpty()) {
//quadtree updated each time //quadtree updated each time
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) { bubbles.values().forEach(quadTree::insert);
quadTree.insert(bubbles.get(e.nextElement())); bubbles.forEach((i, bubble) -> {
}
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
Integer i = e.nextElement();
//bubble moves, new position gets updated, quadtree used to reduce computations //bubble moves, new position gets updated, quadtree used to reduce computations
bubbles.get(i).move(); bubble.move();
bubbles.replace(i, bubbles.get(i)); bubbles.replace(i, bubble);
SpatialPartitionBubbles sp = new SpatialPartitionBubbles(bubbles, quadTree); var sp = new SpatialPartitionBubbles(bubbles, quadTree);
sp.handleCollisionsUsingQt(bubbles.get(i)); sp.handleCollisionsUsingQt(bubble);
} });
numOfMovements--; numOfMovements--;
} }
for (Integer key : bubbles.keySet()) {
//bubbles not popped //bubbles not popped
LOGGER.info("Bubble " + key + " not popped"); bubbles.keySet().stream().map(key -> "Bubble " + key + " not popped").forEach(LOGGER::info);
}
} }
/** /**
@ -123,23 +109,23 @@ public class App {
*/ */
public static void main(String[] args) { public static void main(String[] args) {
Hashtable<Integer, Bubble> bubbles1 = new Hashtable<Integer, Bubble>(); var bubbles1 = new Hashtable<Integer, Bubble>();
Hashtable<Integer, Bubble> bubbles2 = new Hashtable<Integer, Bubble>(); var bubbles2 = new Hashtable<Integer, Bubble>();
Random rand = new Random(); var rand = new Random();
for (int i = 0; i < 10000; i++) { for (int i = 0; i < 10000; i++) {
Bubble b = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1); var b = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
bubbles1.put(i, b); bubbles1.put(i, b);
bubbles2.put(i, b); bubbles2.put(i, b);
LOGGER.info("Bubble " + i + " with radius " + b.radius LOGGER.info("Bubble " + i + " with radius " + b.radius
+ " added at (" + b.coordinateX + "," + b.coordinateY + ")"); + " added at (" + b.coordinateX + "," + b.coordinateY + ")");
} }
long start1 = System.currentTimeMillis(); var start1 = System.currentTimeMillis();
App.noSpatialPartition(300, 300, 20, bubbles1); App.noSpatialPartition(20, bubbles1);
long end1 = System.currentTimeMillis(); var end1 = System.currentTimeMillis();
long start2 = System.currentTimeMillis(); var start2 = System.currentTimeMillis();
App.withSpatialPartition(300, 300, 20, bubbles2); App.withSpatialPartition(300, 300, 20, bubbles2);
long end2 = System.currentTimeMillis(); var end2 = System.currentTimeMillis();
LOGGER.info("Without spatial partition takes " + (end1 - start1) + "ms"); LOGGER.info("Without spatial partition takes " + (end1 - start1) + "ms");
LOGGER.info("With spatial partition takes " + (end2 - start2) + "ms"); LOGGER.info("With spatial partition takes " + (end2 - start2) + "ms");
} }

View File

@ -23,7 +23,7 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import java.util.ArrayList; import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Random; import java.util.Random;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -64,10 +64,10 @@ public class Bubble extends Point<Bubble> {
allBubbles.remove(this.id); allBubbles.remove(this.id);
} }
void handleCollision(ArrayList<Point> bubblesToCheck, Hashtable<Integer, Bubble> allBubbles) { void handleCollision(Collection<? extends Point> toCheck, Hashtable<Integer, Bubble> allBubbles) {
boolean toBePopped = false; //if any other bubble collides with it, made true var toBePopped = false; //if any other bubble collides with it, made true
for (int i = 0; i < bubblesToCheck.size(); i++) { for (var point : toCheck) {
Integer otherId = bubblesToCheck.get(i).id; var otherId = point.id;
if (allBubbles.get(otherId) != null && //the bubble hasn't been popped yet if (allBubbles.get(otherId) != null && //the bubble hasn't been popped yet
this.id != otherId && //the two bubbles are not the same this.id != otherId && //the two bubbles are not the same
this.touches(allBubbles.get(otherId))) { //the bubbles touch this.touches(allBubbles.get(otherId))) { //the bubbles touch

View File

@ -23,7 +23,7 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import java.util.ArrayList; import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
/** /**
@ -61,8 +61,8 @@ public abstract class Point<T> {
/** /**
* handling interactions/collisions with other objects. * handling interactions/collisions with other objects.
* *
* @param pointsToCheck contains the objects which need to be checked * @param toCheck contains the objects which need to be checked
* @param allPoints contains hashtable of all points on field at this time * @param all contains hashtable of all points on field at this time
*/ */
abstract void handleCollision(ArrayList<Point> pointsToCheck, Hashtable<Integer, T> allPoints); abstract void handleCollision(Collection<? extends Point> toCheck, Hashtable<Integer, T> all);
} }

View File

@ -23,8 +23,7 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import java.util.ArrayList; import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
/** /**
@ -47,7 +46,7 @@ public class QuadTree {
this.boundary = boundary; this.boundary = boundary;
this.capacity = capacity; this.capacity = capacity;
this.divided = false; this.divided = false;
this.points = new Hashtable<Integer, Point>(); this.points = new Hashtable<>();
this.northwest = null; this.northwest = null;
this.northeast = null; this.northeast = null;
this.southwest = null; this.southwest = null;
@ -76,30 +75,29 @@ public class QuadTree {
} }
void divide() { void divide() {
double x = this.boundary.coordinateX; var x = this.boundary.coordinateX;
double y = this.boundary.coordinateY; var y = this.boundary.coordinateY;
double width = this.boundary.width; var width = this.boundary.width;
double height = this.boundary.height; var height = this.boundary.height;
Rect nw = new Rect(x - width / 4, y + height / 4, width / 2, height / 2); var nw = new Rect(x - width / 4, y + height / 4, width / 2, height / 2);
this.northwest = new QuadTree(nw, this.capacity); this.northwest = new QuadTree(nw, this.capacity);
Rect ne = new Rect(x + width / 4, y + height / 4, width / 2, height / 2); var ne = new Rect(x + width / 4, y + height / 4, width / 2, height / 2);
this.northeast = new QuadTree(ne, this.capacity); this.northeast = new QuadTree(ne, this.capacity);
Rect sw = new Rect(x - width / 4, y - height / 4, width / 2, height / 2); var sw = new Rect(x - width / 4, y - height / 4, width / 2, height / 2);
this.southwest = new QuadTree(sw, this.capacity); this.southwest = new QuadTree(sw, this.capacity);
Rect se = new Rect(x + width / 4, y - height / 4, width / 2, height / 2); var se = new Rect(x + width / 4, y - height / 4, width / 2, height / 2);
this.southeast = new QuadTree(se, this.capacity); this.southeast = new QuadTree(se, this.capacity);
this.divided = true; this.divided = true;
} }
ArrayList<Point> query(Rect r, ArrayList<Point> relevantPoints) { Collection<Point> query(Rect r, Collection<Point> relevantPoints) {
//could also be a circle instead of a rectangle //could also be a circle instead of a rectangle
if (this.boundary.intersects(r)) { if (this.boundary.intersects(r)) {
for (Enumeration<Integer> e = this.points.keys(); e.hasMoreElements(); ) { this.points
Integer i = e.nextElement(); .values()
if (r.contains(this.points.get(i))) { .stream()
relevantPoints.add(this.points.get(i)); .filter(r::contains)
} .forEach(relevantPoints::add);
}
if (this.divided) { if (this.divided) {
this.northwest.query(r, relevantPoints); this.northwest.query(r, relevantPoints);
this.northeast.query(r, relevantPoints); this.northeast.query(r, relevantPoints);

View File

@ -24,6 +24,7 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
/** /**
@ -44,8 +45,8 @@ public class SpatialPartitionBubbles extends SpatialPartitionGeneric<Bubble> {
void handleCollisionsUsingQt(Bubble b) { void handleCollisionsUsingQt(Bubble b) {
// finding points within area of a square drawn with centre same as // finding points within area of a square drawn with centre same as
// centre of bubble and length = radius of bubble // centre of bubble and length = radius of bubble
Rect rect = new Rect(b.coordinateX, b.coordinateY, 2 * b.radius, 2 * b.radius); var rect = new Rect(b.coordinateX, b.coordinateY, 2 * b.radius, 2 * b.radius);
ArrayList<Point> quadTreeQueryResult = new ArrayList<Point>(); var quadTreeQueryResult = new ArrayList<Point>();
this.quadTree.query(rect, quadTreeQueryResult); this.quadTree.query(rect, quadTreeQueryResult);
//handling these collisions //handling these collisions
b.handleCollision(quadTreeQueryResult, this.bubbles); b.handleCollision(quadTreeQueryResult, this.bubbles);

View File

@ -23,62 +23,71 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Hashtable; import java.util.Hashtable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
* Testing methods in Bubble class. * Testing methods in Bubble class.
*/ */
class BubbleTest { class BubbleTest {
@Test @Test
void moveTest() { void moveTest() {
Bubble b = new Bubble(10,10,1,2); var b = new Bubble(10, 10, 1, 2);
int initialX = b.coordinateX; var initialX = b.coordinateX;
int initialY = b.coordinateY; var initialY = b.coordinateY;
b.move(); b.move();
//change in x and y < |2| //change in x and y < |2|
assertTrue((b.coordinateX - initialX < 2 && b.coordinateX - initialX > -2) && (b.coordinateY - initialY < 2 && b.coordinateY - initialY > -2)); assertTrue(b.coordinateX - initialX < 2 && b.coordinateX - initialX > -2);
assertTrue(b.coordinateY - initialY < 2 && b.coordinateY - initialY > -2);
} }
@Test @Test
void touchesTest() { void touchesTest() {
Bubble b1 = new Bubble(0,0,1,2); var b1 = new Bubble(0, 0, 1, 2);
Bubble b2 = new Bubble(1,1,2,1); var b2 = new Bubble(1, 1, 2, 1);
Bubble b3 = new Bubble(10,10,3,1); var b3 = new Bubble(10, 10, 3, 1);
//b1 touches b2 but not b3 //b1 touches b2 but not b3
assertTrue(b1.touches(b2) && !b1.touches(b3)); assertTrue(b1.touches(b2));
assertFalse(b1.touches(b3));
} }
@Test @Test
void popTest() { void popTest() {
Bubble b1 = new Bubble(10,10,1,2); var b1 = new Bubble(10, 10, 1, 2);
Bubble b2 = new Bubble(0,0,2,2); var b2 = new Bubble(0, 0, 2, 2);
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>(); var bubbles = new Hashtable<Integer, Bubble>();
bubbles.put(1, b1); bubbles.put(1, b1);
bubbles.put(2, b2); bubbles.put(2, b2);
b1.pop(bubbles); b1.pop(bubbles);
//after popping, bubble no longer in hashtable containing all bubbles //after popping, bubble no longer in hashtable containing all bubbles
assertTrue(bubbles.get(1) == null && bubbles.get(2) != null); assertNull(bubbles.get(1));
assertNotNull(bubbles.get(2));
} }
@Test @Test
void handleCollisionTest() { void handleCollisionTest() {
Bubble b1 = new Bubble(0,0,1,2); var b1 = new Bubble(0, 0, 1, 2);
Bubble b2 = new Bubble(1,1,2,1); var b2 = new Bubble(1, 1, 2, 1);
Bubble b3 = new Bubble(10,10,3,1); var b3 = new Bubble(10, 10, 3, 1);
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>(); var bubbles = new Hashtable<Integer, Bubble>();
bubbles.put(1, b1); bubbles.put(1, b1);
bubbles.put(2, b2); bubbles.put(2, b2);
bubbles.put(3, b3); bubbles.put(3, b3);
ArrayList<Point> bubblesToCheck = new ArrayList<Point>(); var bubblesToCheck = new ArrayList<Point>();
bubblesToCheck.add(b2); bubblesToCheck.add(b2);
bubblesToCheck.add(b3); bubblesToCheck.add(b3);
b1.handleCollision(bubblesToCheck, bubbles); b1.handleCollision(bubblesToCheck, bubbles);
//b1 touches b2 and not b3, so b1, b2 will be popped //b1 touches b2 and not b3, so b1, b2 will be popped
assertTrue(bubbles.get(1) == null && bubbles.get(2) == null && bubbles.get(3) != null); assertNull(bubbles.get(1));
assertNull(bubbles.get(2));
assertNotNull(bubbles.get(3));
} }
} }

View File

@ -23,12 +23,13 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@ -39,41 +40,34 @@ class QuadTreeTest {
@Test @Test
void queryTest() { void queryTest() {
ArrayList<Point> points = new ArrayList<Point>(); var points = new ArrayList<Point>();
Random rand = new Random(); var rand = new Random();
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
Bubble p = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1); var p = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
points.add(p); points.add(p);
} }
Rect field = new Rect(150,150,300,300); //size of field var field = new Rect(150, 150, 300, 300); //size of field
Rect queryRange = new Rect(70,130,100,100); //result = all points lying in this rectangle var queryRange = new Rect(70, 130, 100, 100); //result = all points lying in this rectangle
//points found in the query range using quadtree and normal method is same //points found in the query range using quadtree and normal method is same
assertTrue(QuadTreeTest.quadTreeTest(points, field, queryRange).equals(QuadTreeTest.verify(points, queryRange))); var points1 = QuadTreeTest.quadTreeTest(points, field, queryRange);
var points2 = QuadTreeTest.verify(points, queryRange);
assertEquals(points1, points2);
} }
static Hashtable<Integer, Point> quadTreeTest(ArrayList<Point> points, Rect field, Rect queryRange) { static Hashtable<Integer, Point> quadTreeTest(Collection<Point> points, Rect field, Rect queryRange) {
//creating quadtree and inserting all points //creating quadtree and inserting all points
QuadTree qTree = new QuadTree(queryRange, 4); var qTree = new QuadTree(queryRange, 4);
for (int i = 0; i < points.size(); i++) { points.forEach(qTree::insert);
qTree.insert(points.get(i));
return qTree
.query(field, new ArrayList<>())
.stream()
.collect(Collectors.toMap(p -> p.id, p -> p, (a, b) -> b, Hashtable::new));
} }
ArrayList<Point> queryResult = qTree.query(field, new ArrayList<Point>()); static Hashtable<Integer, Point> verify(Collection<Point> points, Rect queryRange) {
Hashtable<Integer, Point> result = new Hashtable<Integer, Point>(); return points.stream()
for (int i = 0; i < queryResult.size(); i++) { .filter(queryRange::contains)
Point p = queryResult.get(i); .collect(Collectors.toMap(point -> point.id, point -> point, (a, b) -> b, Hashtable::new));
result.put(p.id, p);
}
return result;
}
static Hashtable<Integer, Point> verify(ArrayList<Point> points, Rect queryRange) {
Hashtable<Integer, Point> result = new Hashtable<Integer, Point>();
for (int i = 0; i < points.size(); i++) {
if (queryRange.contains(points.get(i))) {
result.put(points.get(i).id, points.get(i));
}
}
return result;
} }
} }

View File

@ -23,7 +23,9 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@ -34,19 +36,21 @@ class RectTest {
@Test @Test
void containsTest() { void containsTest() {
Rect r = new Rect(10,10,20,20); var r = new Rect(10, 10, 20, 20);
Bubble b1 = new Bubble(2,2,1,1); var b1 = new Bubble(2, 2, 1, 1);
Bubble b2 = new Bubble(30,30,2,1); var b2 = new Bubble(30, 30, 2, 1);
//r contains b1 and not b2 //r contains b1 and not b2
assertTrue(r.contains(b1) && !r.contains(b2)); assertTrue(r.contains(b1));
assertFalse(r.contains(b2));
} }
@Test @Test
void intersectsTest() { void intersectsTest() {
Rect r1 = new Rect(10,10,20,20); var r1 = new Rect(10, 10, 20, 20);
Rect r2 = new Rect(15,15,20,20); var r2 = new Rect(15, 15, 20, 20);
Rect r3 = new Rect(50,50,20,20); var r3 = new Rect(50, 50, 20, 20);
//r1 intersects r2 and not r3 //r1 intersects r2 and not r3
assertTrue(r1.intersects(r2) && !r1.intersects(r3)); assertTrue(r1.intersects(r2));
assertFalse(r1.intersects(r3));
} }
} }

View File

@ -23,7 +23,9 @@
package com.iluwatar.spatialpartition; package com.iluwatar.spatialpartition;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.Hashtable; import java.util.Hashtable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,24 +37,27 @@ class SpatialPartitionBubblesTest {
@Test @Test
void handleCollisionsUsingQtTest() { void handleCollisionsUsingQtTest() {
Bubble b1 = new Bubble(10,10,1,3); var b1 = new Bubble(10, 10, 1, 3);
Bubble b2 = new Bubble(5,5,2,1); var b2 = new Bubble(5, 5, 2, 1);
Bubble b3 = new Bubble(9,9,3,1); var b3 = new Bubble(9, 9, 3, 1);
Bubble b4 = new Bubble(8,8,4,2); var b4 = new Bubble(8, 8, 4, 2);
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>(); var bubbles = new Hashtable<Integer, Bubble>();
bubbles.put(1, b1); bubbles.put(1, b1);
bubbles.put(2, b2); bubbles.put(2, b2);
bubbles.put(3, b3); bubbles.put(3, b3);
bubbles.put(4, b4); bubbles.put(4, b4);
Rect r = new Rect(10,10,20,20); var r = new Rect(10, 10, 20, 20);
QuadTree qt = new QuadTree(r,4); var qt = new QuadTree(r, 4);
qt.insert(b1); qt.insert(b1);
qt.insert(b2); qt.insert(b2);
qt.insert(b3); qt.insert(b3);
qt.insert(b4); qt.insert(b4);
SpatialPartitionBubbles sp = new SpatialPartitionBubbles(bubbles, qt); var sp = new SpatialPartitionBubbles(bubbles, qt);
sp.handleCollisionsUsingQt(b1); sp.handleCollisionsUsingQt(b1);
//b1 touches b3 and b4 but not b2 - so b1,b3,b4 get popped //b1 touches b3 and b4 but not b2 - so b1,b3,b4 get popped
assertTrue(bubbles.get(1) == null && bubbles.get(2) != null && bubbles.get(3) == null && bubbles.get(4) == null); assertNull(bubbles.get(1));
assertNotNull(bubbles.get(2));
assertNull(bubbles.get(3));
assertNull(bubbles.get(4));
} }
} }

View File

@ -100,24 +100,24 @@ public class MassGreaterThanSelector extends AbstractSelector<Creature> {
With these building blocks in place, we can perform a search for red creatures as follows: With these building blocks in place, we can perform a search for red creatures as follows:
```java ```java
List<Creature> redCreatures = creatures.stream().filter(new ColorSelector(Color.RED)) var redCreatures = creatures.stream().filter(new ColorSelector(Color.RED))
.collect(Collectors.toList()); .collect(Collectors.toList());
``` ```
But we could also use our parameterized selector like this: But we could also use our parameterized selector like this:
```java ```java
List<Creature> heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0) var heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0)
.collect(Collectors.toList()); .collect(Collectors.toList());
``` ```
Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows: Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows:
```java ```java
AbstractSelector specialCreaturesSelector = var specialCreaturesSelector =
new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not()); new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not());
List<Creature> specialCreatures = creatures.stream().filter(specialCreaturesSelector) var specialCreatures = creatures.stream().filter(specialCreaturesSelector)
.collect(Collectors.toList()); .collect(Collectors.toList());
``` ```

View File

@ -32,14 +32,14 @@ import com.iluwatar.specification.creature.Shark;
import com.iluwatar.specification.creature.Troll; import com.iluwatar.specification.creature.Troll;
import com.iluwatar.specification.property.Color; import com.iluwatar.specification.property.Color;
import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Movement;
import com.iluwatar.specification.selector.AbstractSelector;
import com.iluwatar.specification.selector.ColorSelector; import com.iluwatar.specification.selector.ColorSelector;
import com.iluwatar.specification.selector.MassEqualSelector; import com.iluwatar.specification.selector.MassEqualSelector;
import com.iluwatar.specification.selector.MassGreaterThanSelector; import com.iluwatar.specification.selector.MassGreaterThanSelector;
import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector; import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector;
import com.iluwatar.specification.selector.MovementSelector; import com.iluwatar.specification.selector.MovementSelector;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.Objects;
import java.util.function.Predicate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -63,57 +63,47 @@ public class App {
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// initialize creatures list // initialize creatures list
List<Creature> creatures = List.of(new Goblin(), new Octopus(), new Dragon(), new Shark(), var creatures = List.of(
new Troll(), new KillerBee()); new Goblin(),
new Octopus(),
new Dragon(),
new Shark(),
new Troll(),
new KillerBee()
);
// so-called "hard-coded" specification // so-called "hard-coded" specification
LOGGER.info("Demonstrating hard-coded specification :"); LOGGER.info("Demonstrating hard-coded specification :");
// find all walking creatures // find all walking creatures
LOGGER.info("Find all walking creatures"); LOGGER.info("Find all walking creatures");
List<Creature> walkingCreatures = print(creatures, new MovementSelector(Movement.WALKING));
creatures.stream().filter(new MovementSelector(Movement.WALKING))
.collect(Collectors.toList());
walkingCreatures.forEach(c -> LOGGER.info(c.toString()));
// find all dark creatures // find all dark creatures
LOGGER.info("Find all dark creatures"); LOGGER.info("Find all dark creatures");
List<Creature> darkCreatures = print(creatures, new ColorSelector(Color.DARK));
creatures.stream().filter(new ColorSelector(Color.DARK)).collect(Collectors.toList());
darkCreatures.forEach(c -> LOGGER.info(c.toString()));
LOGGER.info("\n"); LOGGER.info("\n");
// so-called "parameterized" specification // so-called "parameterized" specification
LOGGER.info("Demonstrating parameterized specification :"); LOGGER.info("Demonstrating parameterized specification :");
// find all creatures heavier than 500kg // find all creatures heavier than 500kg
LOGGER.info("Find all creatures heavier than 600kg"); LOGGER.info("Find all creatures heavier than 600kg");
List<Creature> heavyCreatures = print(creatures, new MassGreaterThanSelector(600.0));
creatures.stream().filter(new MassGreaterThanSelector(600.0))
.collect(Collectors.toList());
heavyCreatures.forEach(c -> LOGGER.info(c.toString()));
// find all creatures heavier than 500kg // find all creatures heavier than 500kg
LOGGER.info("Find all creatures lighter than or weighing exactly 500kg"); LOGGER.info("Find all creatures lighter than or weighing exactly 500kg");
List<Creature> lightCreatures = print(creatures, new MassSmallerThanOrEqSelector(500.0));
creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0))
.collect(Collectors.toList());
lightCreatures.forEach(c -> LOGGER.info(c.toString()));
LOGGER.info("\n"); LOGGER.info("\n");
// so-called "composite" specification // so-called "composite" specification
LOGGER.info("Demonstrating composite specification :"); LOGGER.info("Demonstrating composite specification :");
// find all red and flying creatures // find all red and flying creatures
LOGGER.info("Find all red and flying creatures"); LOGGER.info("Find all red and flying creatures");
List<Creature> redAndFlyingCreatures = var redAndFlying = new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING));
creatures.stream() print(creatures, redAndFlying);
.filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)))
.collect(Collectors.toList());
redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString()));
// find all creatures dark or red, non-swimming, and heavier than or equal to 400kg // find all creatures dark or red, non-swimming, and heavier than or equal to 400kg
LOGGER.info("Find all scary creatures"); LOGGER.info("Find all scary creatures");
AbstractSelector<Creature> scaryCreaturesSelector = new ColorSelector(Color.DARK) var scaryCreaturesSelector = new ColorSelector(Color.DARK)
.or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not()) .or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not())
.and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0))); .and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0)));
List<Creature> scaryCreatures = print(creatures, scaryCreaturesSelector);
creatures.stream() }
.filter(scaryCreaturesSelector)
.collect(Collectors.toList()); private static void print(List<? extends Creature> creatures, Predicate<Creature> selector) {
scaryCreatures.forEach(c -> LOGGER.info(c.toString())); creatures.stream().filter(selector).map(Objects::toString).forEach(LOGGER::info);
} }
} }

View File

@ -32,7 +32,6 @@ public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -98,12 +98,9 @@ public class CreatureTest {
@MethodSource("dataProvider") @MethodSource("dataProvider")
public void testToString(Creature testedCreature, String name, Size size, Movement movement, public void testToString(Creature testedCreature, String name, Size size, Movement movement,
Color color, Mass mass) { Color color, Mass mass) {
final String toString = testedCreature.toString(); final var toString = testedCreature.toString();
assertNotNull(toString); assertNotNull(toString);
assertEquals( assertEquals(String
String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, .format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, mass), toString);
mass),
toString
);
} }
} }

View File

@ -44,13 +44,13 @@ public class ColorSelectorTest {
*/ */
@Test @Test
public void testColor() { public void testColor() {
final Creature greenCreature = mock(Creature.class); final var greenCreature = mock(Creature.class);
when(greenCreature.getColor()).thenReturn(Color.GREEN); when(greenCreature.getColor()).thenReturn(Color.GREEN);
final Creature redCreature = mock(Creature.class); final var redCreature = mock(Creature.class);
when(redCreature.getColor()).thenReturn(Color.RED); when(redCreature.getColor()).thenReturn(Color.RED);
final ColorSelector greenSelector = new ColorSelector(Color.GREEN); final var greenSelector = new ColorSelector(Color.GREEN);
assertTrue(greenSelector.test(greenCreature)); assertTrue(greenSelector.test(greenCreature));
assertFalse(greenSelector.test(redCreature)); assertFalse(greenSelector.test(redCreature));

View File

@ -40,16 +40,16 @@ public class CompositeSelectorsTest {
*/ */
@Test @Test
public void testAndComposition() { public void testAndComposition() {
final Creature swimmingHeavyCreature = mock(Creature.class); final var swimmingHeavyCreature = mock(Creature.class);
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
final Creature swimmingLightCreature = mock(Creature.class); final var swimmingLightCreature = mock(Creature.class);
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
final AbstractSelector<Creature> lightAndSwimmingSelector = new MassSmallerThanOrEqSelector( final var lightAndSwimmingSelector = new MassSmallerThanOrEqSelector(50.0)
50.0).and(new MovementSelector(Movement.SWIMMING)); .and(new MovementSelector(Movement.SWIMMING));
assertFalse(lightAndSwimmingSelector.test(swimmingHeavyCreature)); assertFalse(lightAndSwimmingSelector.test(swimmingHeavyCreature));
assertTrue(lightAndSwimmingSelector.test(swimmingLightCreature)); assertTrue(lightAndSwimmingSelector.test(swimmingLightCreature));
} }
@ -59,15 +59,15 @@ public class CompositeSelectorsTest {
*/ */
@Test @Test
public void testOrComposition() { public void testOrComposition() {
final Creature swimmingHeavyCreature = mock(Creature.class); final var swimmingHeavyCreature = mock(Creature.class);
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
final Creature swimmingLightCreature = mock(Creature.class); final var swimmingLightCreature = mock(Creature.class);
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
final AbstractSelector<Creature> lightOrSwimmingSelector = new MassSmallerThanOrEqSelector(50.0) final var lightOrSwimmingSelector = new MassSmallerThanOrEqSelector(50.0)
.or(new MovementSelector(Movement.SWIMMING)); .or(new MovementSelector(Movement.SWIMMING));
assertTrue(lightOrSwimmingSelector.test(swimmingHeavyCreature)); assertTrue(lightOrSwimmingSelector.test(swimmingHeavyCreature));
assertTrue(lightOrSwimmingSelector.test(swimmingLightCreature)); assertTrue(lightOrSwimmingSelector.test(swimmingLightCreature));
@ -78,15 +78,15 @@ public class CompositeSelectorsTest {
*/ */
@Test @Test
public void testNotComposition() { public void testNotComposition() {
final Creature swimmingHeavyCreature = mock(Creature.class); final var swimmingHeavyCreature = mock(Creature.class);
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
final Creature swimmingLightCreature = mock(Creature.class); final var swimmingLightCreature = mock(Creature.class);
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
final AbstractSelector<Creature> heavySelector = new MassSmallerThanOrEqSelector(50.0).not(); final var heavySelector = new MassSmallerThanOrEqSelector(50.0).not();
assertTrue(heavySelector.test(swimmingHeavyCreature)); assertTrue(heavySelector.test(swimmingHeavyCreature));
assertFalse(heavySelector.test(swimmingLightCreature)); assertFalse(heavySelector.test(swimmingLightCreature));
} }

View File

@ -39,13 +39,13 @@ public class MassSelectorTest {
*/ */
@Test @Test
public void testMass() { public void testMass() {
final Creature lightCreature = mock(Creature.class); final var lightCreature = mock(Creature.class);
when(lightCreature.getMass()).thenReturn(new Mass(50.0)); when(lightCreature.getMass()).thenReturn(new Mass(50.0));
final Creature heavyCreature = mock(Creature.class); final var heavyCreature = mock(Creature.class);
when(heavyCreature.getMass()).thenReturn(new Mass(2500.0)); when(heavyCreature.getMass()).thenReturn(new Mass(2500.0));
final MassSmallerThanOrEqSelector lightSelector = new MassSmallerThanOrEqSelector(500.0); final var lightSelector = new MassSmallerThanOrEqSelector(500.0);
assertTrue(lightSelector.test(lightCreature)); assertTrue(lightSelector.test(lightCreature));
assertFalse(lightSelector.test(heavyCreature)); assertFalse(lightSelector.test(heavyCreature));
} }

View File

@ -44,13 +44,13 @@ public class MovementSelectorTest {
*/ */
@Test @Test
public void testMovement() { public void testMovement() {
final Creature swimmingCreature = mock(Creature.class); final var swimmingCreature = mock(Creature.class);
when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING); when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING);
final Creature flyingCreature = mock(Creature.class); final var flyingCreature = mock(Creature.class);
when(flyingCreature.getMovement()).thenReturn(Movement.FLYING); when(flyingCreature.getMovement()).thenReturn(Movement.FLYING);
final MovementSelector swimmingSelector = new MovementSelector(Movement.SWIMMING); final var swimmingSelector = new MovementSelector(Movement.SWIMMING);
assertTrue(swimmingSelector.test(swimmingCreature)); assertTrue(swimmingSelector.test(swimmingCreature));
assertFalse(swimmingSelector.test(flyingCreature)); assertFalse(swimmingSelector.test(flyingCreature));

View File

@ -44,13 +44,13 @@ public class SizeSelectorTest {
*/ */
@Test @Test
public void testMovement() { public void testMovement() {
final Creature normalCreature = mock(Creature.class); final var normalCreature = mock(Creature.class);
when(normalCreature.getSize()).thenReturn(Size.NORMAL); when(normalCreature.getSize()).thenReturn(Size.NORMAL);
final Creature smallCreature = mock(Creature.class); final var smallCreature = mock(Creature.class);
when(smallCreature.getSize()).thenReturn(Size.SMALL); when(smallCreature.getSize()).thenReturn(Size.SMALL);
final SizeSelector normalSelector = new SizeSelector(Size.NORMAL); final var normalSelector = new SizeSelector(Size.NORMAL);
assertTrue(normalSelector.test(normalCreature)); assertTrue(normalSelector.test(normalCreature));
assertFalse(normalSelector.test(smallCreature)); assertFalse(normalSelector.test(smallCreature));
} }

View File

@ -26,15 +26,12 @@ package com.iluwatar.state;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -23,20 +23,19 @@
package com.iluwatar.state; package com.iluwatar.state;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase; import ch.qos.logback.core.AppenderBase;
import java.util.LinkedList;
import java.util.List;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* Date: 12/29/15 - 8:27 PM * Date: 12/29/15 - 8:27 PM
* *
@ -62,27 +61,27 @@ public class MammothTest {
*/ */
@Test @Test
public void testTimePasses() { public void testTimePasses() {
final Mammoth mammoth = new Mammoth(); final var mammoth = new Mammoth();
mammoth.observe(); mammoth.observe();
assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage());
assertEquals(1 , appender.getLogSize()); assertEquals(1, appender.getLogSize());
mammoth.timePasses(); mammoth.timePasses();
assertEquals("The mammoth gets angry!", appender.getLastMessage()); assertEquals("The mammoth gets angry!", appender.getLastMessage());
assertEquals(2 , appender.getLogSize()); assertEquals(2, appender.getLogSize());
mammoth.observe(); mammoth.observe();
assertEquals("The mammoth is furious!", appender.getLastMessage()); assertEquals("The mammoth is furious!", appender.getLastMessage());
assertEquals(3 , appender.getLogSize()); assertEquals(3, appender.getLogSize());
mammoth.timePasses(); mammoth.timePasses();
assertEquals("The mammoth calms down.", appender.getLastMessage()); assertEquals("The mammoth calms down.", appender.getLastMessage());
assertEquals(4 , appender.getLogSize()); assertEquals(4, appender.getLogSize());
mammoth.observe(); mammoth.observe();
assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage());
assertEquals(5 , appender.getLogSize()); assertEquals(5, appender.getLogSize());
} }
@ -91,7 +90,7 @@ public class MammothTest {
*/ */
@Test @Test
public void testToString() { public void testToString() {
final String toString = new Mammoth().toString(); final var toString = new Mammoth().toString();
assertNotNull(toString); assertNotNull(toString);
assertEquals("The mammoth", toString); assertEquals("The mammoth", toString);
} }

View File

@ -67,21 +67,34 @@ public class App {
*/ */
public static void main(String[] args) { public static void main(String[] args) {
var warrior = var warrior = CharacterStepBuilder
CharacterStepBuilder.newBuilder().name("Amberjill").fighterClass("Paladin") .newBuilder()
.withWeapon("Sword").noAbilities().build(); .name("Amberjill")
.fighterClass("Paladin")
.withWeapon("Sword")
.noAbilities()
.build();
LOGGER.info(warrior.toString()); LOGGER.info(warrior.toString());
var mage = var mage = CharacterStepBuilder
CharacterStepBuilder.newBuilder().name("Riobard").wizardClass("Sorcerer") .newBuilder()
.withSpell("Fireball").withAbility("Fire Aura").withAbility("Teleport") .name("Riobard")
.noMoreAbilities().build(); .wizardClass("Sorcerer")
.withSpell("Fireball")
.withAbility("Fire Aura")
.withAbility("Teleport")
.noMoreAbilities()
.build();
LOGGER.info(mage.toString()); LOGGER.info(mage.toString());
var thief = var thief = CharacterStepBuilder
CharacterStepBuilder.newBuilder().name("Desmond").fighterClass("Rogue").noWeapon().build(); .newBuilder()
.name("Desmond")
.fighterClass("Rogue")
.noWeapon()
.build();
LOGGER.info(thief.toString()); LOGGER.info(thief.toString());
} }

View File

@ -91,15 +91,15 @@ public class Character {
@Override @Override
public String toString() { public String toString() {
var sb = new StringBuilder(); return new StringBuilder()
sb.append("This is a ") .append("This is a ")
.append(fighterClass != null ? fighterClass : wizardClass) .append(fighterClass != null ? fighterClass : wizardClass)
.append(" named ") .append(" named ")
.append(name) .append(name)
.append(" armed with a ") .append(" armed with a ")
.append(weapon != null ? weapon : spell != null ? spell : "with nothing") .append(weapon != null ? weapon : spell != null ? spell : "with nothing")
.append(abilities != null ? " and wielding " + abilities + " abilities" : "") .append(abilities != null ? " and wielding " + abilities + " abilities" : "")
.append('.'); .append('.')
return sb.toString(); .toString();
} }
} }

View File

@ -165,7 +165,7 @@ public final class CharacterStepBuilder {
@Override @Override
public Character build() { public Character build() {
Character character = new Character(name); var character = new Character(name);
if (fighterClass != null) { if (fighterClass != null) {
character.setFighterClass(fighterClass); character.setFighterClass(fighterClass);

View File

@ -26,15 +26,12 @@ package com.iluwatar.stepbuilder;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -23,15 +23,13 @@
package com.iluwatar.stepbuilder; package com.iluwatar.stepbuilder;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/29/15 - 9:21 PM * Date: 12/29/15 - 9:21 PM
* *
@ -44,7 +42,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildWizard() { public void testBuildWizard() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Merlin") .name("Merlin")
.wizardClass("alchemist") .wizardClass("alchemist")
.withSpell("poison") .withSpell("poison")
@ -58,7 +56,7 @@ public class CharacterStepBuilderTest {
assertEquals("poison", character.getSpell()); assertEquals("poison", character.getSpell());
assertNotNull(character.toString()); assertNotNull(character.toString());
final List<String> abilities = character.getAbilities(); final var abilities = character.getAbilities();
assertNotNull(abilities); assertNotNull(abilities);
assertEquals(2, abilities.size()); assertEquals(2, abilities.size());
assertTrue(abilities.contains("invisibility")); assertTrue(abilities.contains("invisibility"));
@ -72,7 +70,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildPoorWizard() { public void testBuildPoorWizard() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Merlin") .name("Merlin")
.wizardClass("alchemist") .wizardClass("alchemist")
.noSpell() .noSpell()
@ -91,7 +89,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildWeakWizard() { public void testBuildWeakWizard() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Merlin") .name("Merlin")
.wizardClass("alchemist") .wizardClass("alchemist")
.withSpell("poison") .withSpell("poison")
@ -112,7 +110,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildWarrior() { public void testBuildWarrior() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Cuauhtemoc") .name("Cuauhtemoc")
.fighterClass("aztec") .fighterClass("aztec")
.withWeapon("spear") .withWeapon("spear")
@ -126,7 +124,7 @@ public class CharacterStepBuilderTest {
assertEquals("spear", character.getWeapon()); assertEquals("spear", character.getWeapon());
assertNotNull(character.toString()); assertNotNull(character.toString());
final List<String> abilities = character.getAbilities(); final var abilities = character.getAbilities();
assertNotNull(abilities); assertNotNull(abilities);
assertEquals(2, abilities.size()); assertEquals(2, abilities.size());
assertTrue(abilities.contains("speed")); assertTrue(abilities.contains("speed"));
@ -140,7 +138,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildPoorWarrior() { public void testBuildPoorWarrior() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Poor warrior") .name("Poor warrior")
.fighterClass("none") .fighterClass("none")
.noWeapon() .noWeapon()
@ -160,7 +158,7 @@ public class CharacterStepBuilderTest {
*/ */
@Test @Test
public void testBuildWeakWarrior() { public void testBuildWeakWarrior() {
final Character character = CharacterStepBuilder.newBuilder() final var character = CharacterStepBuilder.newBuilder()
.name("Weak warrior") .name("Weak warrior")
.fighterClass("none") .fighterClass("none")
.withWeapon("Slingshot") .withWeapon("Slingshot")

View File

@ -32,7 +32,6 @@ public class AppTest {
@Test @Test
public void test() { public void test() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -41,8 +41,8 @@ public class DragonSlayerTest {
*/ */
@Test @Test
public void testGoToBattle() { public void testGoToBattle() {
final DragonSlayingStrategy strategy = mock(DragonSlayingStrategy.class); final var strategy = mock(DragonSlayingStrategy.class);
final DragonSlayer dragonSlayer = new DragonSlayer(strategy); final var dragonSlayer = new DragonSlayer(strategy);
dragonSlayer.goToBattle(); dragonSlayer.goToBattle();
verify(strategy).execute(); verify(strategy).execute();
@ -54,13 +54,13 @@ public class DragonSlayerTest {
*/ */
@Test @Test
public void testChangeStrategy() { public void testChangeStrategy() {
final DragonSlayingStrategy initialStrategy = mock(DragonSlayingStrategy.class); final var initialStrategy = mock(DragonSlayingStrategy.class);
final DragonSlayer dragonSlayer = new DragonSlayer(initialStrategy); final var dragonSlayer = new DragonSlayer(initialStrategy);
dragonSlayer.goToBattle(); dragonSlayer.goToBattle();
verify(initialStrategy).execute(); verify(initialStrategy).execute();
final DragonSlayingStrategy newStrategy = mock(DragonSlayingStrategy.class); final var newStrategy = mock(DragonSlayingStrategy.class);
dragonSlayer.changeStrategy(newStrategy); dragonSlayer.changeStrategy(newStrategy);
dragonSlayer.goToBattle(); dragonSlayer.goToBattle();

View File

@ -28,11 +28,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase; import ch.qos.logback.core.AppenderBase;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;

View File

@ -32,7 +32,6 @@ public class AppTest {
@Test @Test
public void testMain() { public void testMain() {
String[] args = {}; App.main(new String[]{});
App.main(args);
} }
} }

View File

@ -70,8 +70,8 @@ public class GroundDiveTest {
public void testActivate() { public void testActivate() {
log.clearLog(); log.clearLog();
var groundDive = new GroundDive(); var groundDive = new GroundDive();
groundDive.activate();; groundDive.activate();
String[] logs = log.getLog().split("\n"); var logs = log.getLog().split("\n");
final var expectedSize = 3; final var expectedSize = 3;
final var log1 = logs[0].split("-")[1].trim() + " -" + logs[0].split("-")[2].trim(); final var log1 = logs[0].split("-")[1].trim() + " -" + logs[0].split("-")[2].trim();
final var expectedLog1 = "Move to ( 0.0, 0.0, -20.0 )"; final var expectedLog1 = "Move to ( 0.0, 0.0, -20.0 )";

View File

@ -70,8 +70,8 @@ public class SkyLaunchTest {
public void testActivate() { public void testActivate() {
log.clearLog(); log.clearLog();
var skyLaunch = new SkyLaunch(); var skyLaunch = new SkyLaunch();
skyLaunch.activate();; skyLaunch.activate();
String[] logs = log.getLog().split("\n"); var logs = log.getLog().split("\n");
final var expectedSize = 3; final var expectedSize = 3;
final var log1 = getLogContent(logs[0]); final var log1 = getLogContent(logs[0]);
final var expectedLog1 = "Move to ( 0.0, 0.0, 20.0 )"; final var expectedLog1 = "Move to ( 0.0, 0.0, 20.0 )";