Adjust checkstyle rules. Make checkstyle fail the build when violations are found. Correct all current checkstyle violations.

This commit is contained in:
Ilkka Seppala 2015-12-25 23:49:28 +02:00
parent 9fbb085985
commit cec9a99410
167 changed files with 1242 additions and 969 deletions

View File

@ -1,20 +1,18 @@
package com.iluwatar.abstractfactory;
/**
*
* The Abstract Factory pattern provides a way to encapsulate a group of individual factories that
* have a common theme without specifying their concrete classes. In normal usage, the client
* software creates a concrete implementation of the abstract factory and then uses the generic
* interface of the factory to create the concrete objects that are part of the theme. The client
* does not know (or care) which concrete objects it gets from each of these internal factories,
* since it uses only the generic interfaces of their products. This pattern separates the details
* of implementation of a set of objects from their general usage and relies on object composition,
* as object creation is implemented in methods exposed in the factory interface.
* The Abstract Factory pattern provides a way to encapsulate a group of individual factories that have a common theme
* without specifying their concrete classes. In normal usage, the client software creates a concrete implementation of
* the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part
* of the theme. The client does not know (or care) which concrete objects it gets from each of these internal
* factories, since it uses only the generic interfaces of their products. This pattern separates the details of
* implementation of a set of objects from their general usage and relies on object composition, as object creation is
* implemented in methods exposed in the factory interface.
* <p>
* The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and
* its implementations ({@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both
* concrete implementations to create a king, a castle and an army.
* The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and its implementations (
* {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both concrete implementations to create a
* king, a castle and an army.
*
*/
public class App {
@ -23,11 +21,8 @@ public class App {
private Castle castle;
private Army army;
/**
* Creates kingdom
*
* @param factory
*/
public void createKingdom(final KingdomFactory factory) {
setKing(factory.createKing());
@ -47,14 +42,6 @@ public class App {
return factory.createKing();
}
Castle getCastle(final KingdomFactory factory) {
return factory.createCastle();
}
Army getArmy(final KingdomFactory factory) {
return factory.createArmy();
}
public King getKing() {
return king;
}
@ -62,6 +49,10 @@ public class App {
private void setKing(final King king) {
this.king = king;
}
Castle getCastle(final KingdomFactory factory) {
return factory.createCastle();
}
public Castle getCastle() {
return castle;
@ -70,6 +61,10 @@ public class App {
private void setCastle(final Castle castle) {
this.castle = castle;
}
Army getArmy(final KingdomFactory factory) {
return factory.createArmy();
}
public Army getArmy() {
return army;
@ -79,32 +74,32 @@ public class App {
this.army = army;
}
/**
* Program entry point
*
* @param args command line args
* @param args
* command line args
*/
public static void main(String[] args) {
App app = new App();
System.out.println("Elf Kingdom");
KingdomFactory elfKingdomFactory;
elfKingdomFactory = app.getElfKingdomFactory();
app.createKingdom(elfKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
System.out.println("\nOrc Kingdom");
KingdomFactory orcKingdomFactory;
orcKingdomFactory = app.getOrcKingdomFactory();
app.createKingdom(orcKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
App app = new App();
System.out.println("Elf Kingdom");
KingdomFactory elfKingdomFactory;
elfKingdomFactory = app.getElfKingdomFactory();
app.createKingdom(elfKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
System.out.println("\nOrc Kingdom");
KingdomFactory orcKingdomFactory;
orcKingdomFactory = app.getOrcKingdomFactory();
app.createKingdom(orcKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
}
}

View File

@ -4,24 +4,23 @@ import java.util.concurrent.Callable;
/**
* This application demonstrates the async method invocation pattern. Key parts of the pattern are
* <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated
* value, <code>AsyncCallback</code> which can be provided to be executed on task completion and
* <code>AsyncExecutor</code> that manages the execution of the async tasks.
* <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated value,
* <code>AsyncCallback</code> which can be provided to be executed on task completion and <code>AsyncExecutor</code>
* that manages the execution of the async tasks.
* <p>
* The main method shows example flow of async invocations. The main thread starts multiple tasks
* with variable durations and then continues its own work. When the main thread has done it's job
* it collects the results of the async tasks. Two of the tasks are handled with callbacks, meaning
* the callbacks are executed immediately when the tasks complete.
* The main method shows example flow of async invocations. The main thread starts multiple tasks with variable
* durations and then continues its own work. When the main thread has done it's job it collects the results of the
* async tasks. Two of the tasks are handled with callbacks, meaning the callbacks are executed immediately when the
* tasks complete.
* <p>
* Noteworthy difference of thread usage between the async results and callbacks is that the async
* results are collected in the main thread but the callbacks are executed within the worker
* threads. This should be noted when working with thread pools.
* Noteworthy difference of thread usage between the async results and callbacks is that the async results are collected
* in the main thread but the callbacks are executed within the worker threads. This should be noted when working with
* thread pools.
* <p>
* Java provides its own implementations of async method invocation pattern. FutureTask,
* CompletableFuture and ExecutorService are the real world implementations of this pattern. But due
* to the nature of parallel programming, the implementations are not trivial. This example does not
* take all possible scenarios into account but rather provides a simple version that helps to
* understand the pattern.
* Java provides its own implementations of async method invocation pattern. FutureTask, CompletableFuture and
* ExecutorService are the real world implementations of this pattern. But due to the nature of parallel programming,
* the implementations are not trivial. This example does not take all possible scenarios into account but rather
* provides a simple version that helps to understand the pattern.
*
* @see AsyncResult
* @see AsyncCallback
@ -33,6 +32,9 @@ import java.util.concurrent.Callable;
*/
public class App {
/**
* Program entry point
*/
public static void main(String[] args) throws Exception {
// construct a new executor that will run async tasks
AsyncExecutor executor = new ThreadAsyncExecutor();
@ -41,10 +43,8 @@ public class App {
AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500));
AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300));
AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700));
AsyncResult<Integer> asyncResult4 =
executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
AsyncResult<String> asyncResult5 =
executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));
AsyncResult<Integer> asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
AsyncResult<String> asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));
// emulate processing in the current thread while async tasks are running in their own threads
Thread.sleep(350); // Oh boy I'm working hard here
@ -66,8 +66,10 @@ public class App {
/**
* Creates a callable that lazily evaluates to given value with artificial delay.
*
* @param value value to evaluate
* @param delayMillis artificial delay in milliseconds
* @param value
* value to evaluate
* @param delayMillis
* artificial delay in milliseconds
* @return new callable for lazy evaluation
*/
private static <T> Callable<T> lazyval(T value, long delayMillis) {
@ -81,7 +83,8 @@ public class App {
/**
* Creates a simple callback that logs the complete status of the async result.
*
* @param name callback name
* @param name
* callback name
* @return new async callback
*/
private static <T> AsyncCallback<T> callback(String name) {

View File

@ -5,8 +5,6 @@ import java.util.concurrent.ExecutionException;
/**
*
* AsyncResult interface
*
* @param <T>
*/
public interface AsyncResult<T> {

View File

@ -29,13 +29,12 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} catch (Exception ex) {
result.setException(ex);
}
}, "executor-" + idx.incrementAndGet()).start();
} , "executor-" + idx.incrementAndGet()).start();
return result;
}
@Override
public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException,
InterruptedException {
public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException {
if (asyncResult.isCompleted()) {
return asyncResult.getValue();
} else {
@ -45,9 +44,8 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
}
/**
* Simple implementation of async result that allows completing it successfully with a value or
* exceptionally with an exception. A really simplified version from its real life cousins
* FutureTask and CompletableFuture.
* Simple implementation of async result that allows completing it successfully with a value or exceptionally with an
* exception. A really simplified version from its real life cousins FutureTask and CompletableFuture.
*
* @see java.util.concurrent.FutureTask
* @see java.util.concurrent.CompletableFuture
@ -71,10 +69,11 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
}
/**
* Sets the value from successful execution and executes callback if available. Notifies any
* thread waiting for completion.
* Sets the value from successful execution and executes callback if available. Notifies any thread waiting for
* completion.
*
* @param value value of the evaluated task
* @param value
* value of the evaluated task
*/
void setValue(T value) {
this.value = value;
@ -86,10 +85,11 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
}
/**
* Sets the exception from failed execution and executes callback if available. Notifies any
* thread waiting for completion.
* Sets the exception from failed execution and executes callback if available. Notifies any thread waiting for
* completion.
*
* @param exception exception of the failed task
* @param exception
* exception of the failed task
*/
void setException(Exception exception) {
this.exception = exception;

View File

@ -55,8 +55,7 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the happy path of
* {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)}
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)}
*/
@Test(timeout = 3000)
public void testSuccessfulTaskWithCallback() throws Exception {
@ -77,8 +76,7 @@ public class ThreadAsyncExecutorTest {
verify(task, times(1)).call();
// ... same for the callback, we expect our object
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor
.forClass((Class) Optional.class);
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -90,8 +88,8 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a
* task takes a while to execute
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while
* to execute
*/
@Test(timeout = 5000)
public void testLongRunningTaskWithoutCallback() throws Exception {
@ -101,9 +99,9 @@ public class ThreadAsyncExecutorTest {
final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});
Thread.sleep(1500);
return result;
});
final AsyncResult<Object> asyncResult = executor.startProcess(task);
assertNotNull(asyncResult);
@ -111,8 +109,7 @@ public class ThreadAsyncExecutorTest {
try {
asyncResult.getValue();
fail(
"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
} catch (IllegalStateException e) {
assertNotNull(e.getMessage());
}
@ -130,9 +127,8 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the happy path of
* {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task takes a while to
* execute
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task
* takes a while to execute
*/
@Test(timeout = 5000)
public void testLongRunningTaskWithCallback() throws Exception {
@ -142,9 +138,9 @@ public class ThreadAsyncExecutorTest {
final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});
Thread.sleep(1500);
return result;
});
final AsyncCallback<Object> callback = mock(AsyncCallback.class);
final AsyncResult<Object> asyncResult = executor.startProcess(task, callback);
@ -155,8 +151,7 @@ public class ThreadAsyncExecutorTest {
try {
asyncResult.getValue();
fail(
"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
} catch (IllegalStateException e) {
assertNotNull(e.getMessage());
}
@ -164,8 +159,7 @@ public class ThreadAsyncExecutorTest {
// Our task should only execute once, but it can take a while ...
verify(task, timeout(3000).times(1)).call();
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor
.forClass((Class) Optional.class);
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -182,9 +176,8 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a
* task takes a while to execute, while waiting on the result using
* {@link ThreadAsyncExecutor#endProcess(AsyncResult)}
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while
* to execute, while waiting on the result using {@link ThreadAsyncExecutor#endProcess(AsyncResult)}
*/
@Test(timeout = 5000)
public void testEndProcess() throws Exception {
@ -194,9 +187,9 @@ public class ThreadAsyncExecutorTest {
final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});
Thread.sleep(1500);
return result;
});
final AsyncResult<Object> asyncResult = executor.startProcess(task);
assertNotNull(asyncResult);
@ -204,8 +197,7 @@ public class ThreadAsyncExecutorTest {
try {
asyncResult.getValue();
fail(
"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task");
} catch (IllegalStateException e) {
assertNotNull(e.getMessage());
}
@ -220,8 +212,7 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when
* the callable is 'null'
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when the callable is 'null'
*/
@Test(timeout = 3000)
public void testNullTask() throws Exception {
@ -229,8 +220,7 @@ public class ThreadAsyncExecutorTest {
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final AsyncResult<Object> asyncResult = executor.startProcess(null);
assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.",
asyncResult);
assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.", asyncResult);
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());
@ -246,9 +236,8 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the behaviour of
* {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when the callable is 'null',
* but the asynchronous callback is provided
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when the
* callable is 'null', but the asynchronous callback is provided
*/
@Test(timeout = 3000)
public void testNullTaskWithCallback() throws Exception {
@ -257,13 +246,11 @@ public class ThreadAsyncExecutorTest {
final AsyncCallback<Object> callback = mock(AsyncCallback.class);
final AsyncResult<Object> asyncResult = executor.startProcess(null, callback);
assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.",
asyncResult);
assertNotNull("The AsyncResult should not be 'null', even though the task was 'null'.", asyncResult);
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor
.forClass((Class) Optional.class);
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -286,9 +273,8 @@ public class ThreadAsyncExecutorTest {
}
/**
* Test used to verify the behaviour of
* {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when both the callable and
* the asynchronous callback are 'null'
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when both
* the callable and the asynchronous callback are 'null'
*/
@Test(timeout = 3000)
public void testNullTaskWithNullCallback() throws Exception {
@ -296,9 +282,7 @@ public class ThreadAsyncExecutorTest {
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final AsyncResult<Object> asyncResult = executor.startProcess(null, null);
assertNotNull(
"The AsyncResult should not be 'null', even though the task and callback were 'null'.",
asyncResult);
assertNotNull("The AsyncResult should not be 'null', even though the task and callback were 'null'.", asyncResult);
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());

View File

@ -93,6 +93,9 @@ public class Hero {
private Armor armor;
private Weapon weapon;
/**
* Constructor
*/
public HeroBuilder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");

View File

@ -5,20 +5,20 @@ package com.iluwatar.business.delegate;
*/
public class BusinessDelegate {
private BusinessLookup lookupService;
private BusinessService businessService;
private ServiceType serviceType;
private BusinessLookup lookupService;
private BusinessService businessService;
private ServiceType serviceType;
public void setLookupService(BusinessLookup businessLookup) {
this.lookupService = businessLookup;
}
public void setLookupService(BusinessLookup businessLookup) {
this.lookupService = businessLookup;
}
public void setServiceType(ServiceType serviceType) {
this.serviceType = serviceType;
}
public void setServiceType(ServiceType serviceType) {
this.serviceType = serviceType;
}
public void doTask() {
businessService = lookupService.getBusinessService(serviceType);
businessService.doProcessing();
}
public void doTask() {
businessService = lookupService.getBusinessService(serviceType);
businessService.doProcessing();
}
}

View File

@ -21,7 +21,7 @@ package com.iluwatar.caching;
* application data. The cache itself is implemented as an internal (Java) data structure. It adopts
* a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The three
* strategies are individually tested. The testing of the cache is restricted towards saving and
* querying of user accounts from the underlying data store ( {@link DBManager}). The main class (
* querying of user accounts from the underlying data store ( {@link DbManager}). The main class (
* {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and
* whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager
* ({@link AppManager}) handles the transaction of data to-and-from the underlying data store
@ -43,7 +43,7 @@ public class App {
* @param args command line args
*/
public static void main(String[] args) {
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
// and the App class to avoid Maven compilation errors. Set flag to
// true to run the tests with MongoDB (provided that MongoDB is
// installed and socket connection is open).

View File

@ -21,18 +21,21 @@ public class AppManager {
* data storage or a simple Java data structure to (temporarily) store the data/objects during
* runtime.
*/
public static void initDB(boolean useMongoDB) {
if (useMongoDB) {
public static void initDb(boolean useMongoDb) {
if (useMongoDb) {
try {
DBManager.connect();
DbManager.connect();
} catch (ParseException e) {
e.printStackTrace();
}
} else {
DBManager.createVirtualDB();
DbManager.createVirtualDb();
}
}
/**
* Initialize caching policy
*/
public static void initCachingPolicy(CachingPolicy policy) {
cachingPolicy = policy;
if (cachingPolicy == CachingPolicy.BEHIND) {
@ -50,15 +53,21 @@ public class AppManager {
CacheStore.initCapacity(capacity);
}
public static UserAccount find(String userID) {
/**
* Find user account
*/
public static UserAccount find(String userId) {
if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {
return CacheStore.readThrough(userID);
return CacheStore.readThrough(userId);
} else if (cachingPolicy == CachingPolicy.BEHIND) {
return CacheStore.readThroughWithWriteBackPolicy(userID);
return CacheStore.readThroughWithWriteBackPolicy(userId);
}
return null;
}
/**
* Save user account
*/
public static void save(UserAccount userAccount) {
if (cachingPolicy == CachingPolicy.THROUGH) {
CacheStore.writeThrough(userAccount);

View File

@ -9,73 +9,96 @@ import java.util.ArrayList;
*/
public class CacheStore {
static LRUCache cache = null;
static LruCache cache = null;
/**
* Init cache capacity
*/
public static void initCapacity(int capacity) {
if (null == cache)
cache = new LRUCache(capacity);
else
if (null == cache) {
cache = new LruCache(capacity);
} else {
cache.setCapacity(capacity);
}
}
public static UserAccount readThrough(String userID) {
if (cache.contains(userID)) {
/**
* Get user account using read-through cache
*/
public static UserAccount readThrough(String userId) {
if (cache.contains(userId)) {
System.out.println("# Cache Hit!");
return cache.get(userID);
return cache.get(userId);
}
System.out.println("# Cache Miss!");
UserAccount userAccount = DBManager.readFromDB(userID);
cache.set(userID, userAccount);
UserAccount userAccount = DbManager.readFromDb(userId);
cache.set(userId, userAccount);
return userAccount;
}
/**
* Get user account using write-through cache
*/
public static void writeThrough(UserAccount userAccount) {
if (cache.contains(userAccount.getUserID())) {
DBManager.updateDB(userAccount);
if (cache.contains(userAccount.getUserId())) {
DbManager.updateDb(userAccount);
} else {
DBManager.writeToDB(userAccount);
DbManager.writeToDb(userAccount);
}
cache.set(userAccount.getUserID(), userAccount);
cache.set(userAccount.getUserId(), userAccount);
}
/**
* Get user account using write-around cache
*/
public static void writeAround(UserAccount userAccount) {
if (cache.contains(userAccount.getUserID())) {
DBManager.updateDB(userAccount);
cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older
if (cache.contains(userAccount.getUserId())) {
DbManager.updateDb(userAccount);
cache.invalidate(userAccount.getUserId()); // Cache data has been updated -- remove older
// version from cache.
} else {
DBManager.writeToDB(userAccount);
DbManager.writeToDb(userAccount);
}
}
public static UserAccount readThroughWithWriteBackPolicy(String userID) {
if (cache.contains(userID)) {
/**
* Get user account using read-through cache with write-back policy
*/
public static UserAccount readThroughWithWriteBackPolicy(String userId) {
if (cache.contains(userId)) {
System.out.println("# Cache Hit!");
return cache.get(userID);
return cache.get(userId);
}
System.out.println("# Cache Miss!");
UserAccount userAccount = DBManager.readFromDB(userID);
UserAccount userAccount = DbManager.readFromDb(userId);
if (cache.isFull()) {
System.out.println("# Cache is FULL! Writing LRU data to DB...");
UserAccount toBeWrittenToDB = cache.getLRUData();
DBManager.upsertDB(toBeWrittenToDB);
UserAccount toBeWrittenToDb = cache.getLruData();
DbManager.upsertDb(toBeWrittenToDb);
}
cache.set(userID, userAccount);
cache.set(userId, userAccount);
return userAccount;
}
/**
* Set user account
*/
public static void writeBehind(UserAccount userAccount) {
if (cache.isFull() && !cache.contains(userAccount.getUserID())) {
if (cache.isFull() && !cache.contains(userAccount.getUserId())) {
System.out.println("# Cache is FULL! Writing LRU data to DB...");
UserAccount toBeWrittenToDB = cache.getLRUData();
DBManager.upsertDB(toBeWrittenToDB);
UserAccount toBeWrittenToDb = cache.getLruData();
DbManager.upsertDb(toBeWrittenToDb);
}
cache.set(userAccount.getUserID(), userAccount);
cache.set(userAccount.getUserId(), userAccount);
}
/**
* Clears cache
*/
public static void clearCache() {
if (null != cache)
if (null != cache) {
cache.clear();
}
}
/**
@ -83,14 +106,18 @@ public class CacheStore {
*/
public static void flushCache() {
System.out.println("# flushCache...");
if (null == cache)
if (null == cache) {
return;
}
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
for (UserAccount userAccount : listOfUserAccounts) {
DBManager.upsertDB(userAccount);
DbManager.upsertDb(userAccount);
}
}
/**
* Print user accounts
*/
public static String print() {
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
StringBuilder sb = new StringBuilder();

View File

@ -21,7 +21,7 @@ import com.mongodb.client.model.UpdateOptions;
* during runtime (createVirtualDB()).</p>
*
*/
public class DBManager {
public class DbManager {
private static MongoClient mongoClient;
private static MongoDatabase db;
@ -29,21 +29,31 @@ public class DBManager {
private static HashMap<String, UserAccount> virtualDB;
public static void createVirtualDB() {
/**
* Create DB
*/
public static void createVirtualDb() {
useMongoDB = false;
virtualDB = new HashMap<String, UserAccount>();
}
/**
* Connect to DB
*/
public static void connect() throws ParseException {
useMongoDB = true;
mongoClient = new MongoClient();
db = mongoClient.getDatabase("test");
}
public static UserAccount readFromDB(String userID) {
/**
* Read user account from DB
*/
public static UserAccount readFromDb(String userId) {
if (!useMongoDB) {
if (virtualDB.containsKey(userID))
return virtualDB.get(userID);
if (virtualDB.containsKey(userId)) {
return virtualDB.get(userId);
}
return null;
}
if (null == db) {
@ -54,18 +64,22 @@ public class DBManager {
}
}
FindIterable<Document> iterable =
db.getCollection("user_accounts").find(new Document("userID", userID));
if (iterable == null)
db.getCollection("user_accounts").find(new Document("userID", userId));
if (iterable == null) {
return null;
}
Document doc = iterable.first();
UserAccount userAccount =
new UserAccount(userID, doc.getString("userName"), doc.getString("additionalInfo"));
new UserAccount(userId, doc.getString("userName"), doc.getString("additionalInfo"));
return userAccount;
}
public static void writeToDB(UserAccount userAccount) {
/**
* Write user account to DB
*/
public static void writeToDb(UserAccount userAccount) {
if (!useMongoDB) {
virtualDB.put(userAccount.getUserID(), userAccount);
virtualDB.put(userAccount.getUserId(), userAccount);
return;
}
if (null == db) {
@ -76,13 +90,16 @@ public class DBManager {
}
}
db.getCollection("user_accounts").insertOne(
new Document("userID", userAccount.getUserID()).append("userName",
new Document("userID", userAccount.getUserId()).append("userName",
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo()));
}
public static void updateDB(UserAccount userAccount) {
/**
* Update DB
*/
public static void updateDb(UserAccount userAccount) {
if (!useMongoDB) {
virtualDB.put(userAccount.getUserID(), userAccount);
virtualDB.put(userAccount.getUserId(), userAccount);
return;
}
if (null == db) {
@ -93,7 +110,7 @@ public class DBManager {
}
}
db.getCollection("user_accounts").updateOne(
new Document("userID", userAccount.getUserID()),
new Document("userID", userAccount.getUserId()),
new Document("$set", new Document("userName", userAccount.getUserName()).append(
"additionalInfo", userAccount.getAdditionalInfo())));
}
@ -102,9 +119,9 @@ public class DBManager {
*
* Insert data into DB if it does not exist. Else, update it.
*/
public static void upsertDB(UserAccount userAccount) {
public static void upsertDb(UserAccount userAccount) {
if (!useMongoDB) {
virtualDB.put(userAccount.getUserID(), userAccount);
virtualDB.put(userAccount.getUserId(), userAccount);
return;
}
if (null == db) {
@ -115,8 +132,8 @@ public class DBManager {
}
}
db.getCollection("user_accounts").updateOne(
new Document("userID", userAccount.getUserID()),
new Document("$set", new Document("userID", userAccount.getUserID()).append("userName",
new Document("userID", userAccount.getUserId()),
new Document("$set", new Document("userID", userAccount.getUserId()).append("userName",
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())),
new UpdateOptions().upsert(true));
}

View File

@ -12,16 +12,16 @@ import java.util.HashMap;
* LRU data is always at the end of the list.
*
*/
public class LRUCache {
public class LruCache {
class Node {
String userID;
String userId;
UserAccount userAccount;
Node previous;
Node next;
public Node(String userID, UserAccount userAccount) {
this.userID = userID;
public Node(String userId, UserAccount userAccount) {
this.userId = userId;
this.userAccount = userAccount;
}
}
@ -31,13 +31,16 @@ public class LRUCache {
Node head = null;
Node end = null;
public LRUCache(int capacity) {
public LruCache(int capacity) {
this.capacity = capacity;
}
public UserAccount get(String userID) {
if (cache.containsKey(userID)) {
Node node = cache.get(userID);
/**
* Get user account
*/
public UserAccount get(String userId) {
if (cache.containsKey(userId)) {
Node node = cache.get(userId);
remove(node);
setHead(node);
return node.userAccount;
@ -69,52 +72,63 @@ public class LRUCache {
public void setHead(Node node) {
node.next = head;
node.previous = null;
if (head != null)
if (head != null) {
head.previous = node;
}
head = node;
if (end == null)
if (end == null) {
end = head;
}
}
public void set(String userID, UserAccount userAccount) {
if (cache.containsKey(userID)) {
Node old = cache.get(userID);
/**
* Set user account
*/
public void set(String userId, UserAccount userAccount) {
if (cache.containsKey(userId)) {
Node old = cache.get(userId);
old.userAccount = userAccount;
remove(old);
setHead(old);
} else {
Node newNode = new Node(userID, userAccount);
Node newNode = new Node(userId, userAccount);
if (cache.size() >= capacity) {
System.out.println("# Cache is FULL! Removing " + end.userID + " from cache...");
cache.remove(end.userID); // remove LRU data from cache.
System.out.println("# Cache is FULL! Removing " + end.userId + " from cache...");
cache.remove(end.userId); // remove LRU data from cache.
remove(end);
setHead(newNode);
} else {
setHead(newNode);
}
cache.put(userID, newNode);
cache.put(userId, newNode);
}
}
public boolean contains(String userID) {
return cache.containsKey(userID);
public boolean contains(String userId) {
return cache.containsKey(userId);
}
public void invalidate(String userID) {
System.out.println("# " + userID + " has been updated! Removing older version from cache...");
Node toBeRemoved = cache.get(userID);
/**
* Invalidate cache for user
*/
public void invalidate(String userId) {
System.out.println("# " + userId + " has been updated! Removing older version from cache...");
Node toBeRemoved = cache.get(userId);
remove(toBeRemoved);
cache.remove(userID);
cache.remove(userId);
}
public boolean isFull() {
return cache.size() >= capacity;
}
public UserAccount getLRUData() {
public UserAccount getLruData() {
return end.userAccount;
}
/**
* Clear cache
*/
public void clear() {
head = null;
end = null;
@ -135,6 +149,9 @@ public class LRUCache {
return listOfCacheData;
}
/**
* Set cache capacity
*/
public void setCapacity(int newCapacity) {
if (capacity > newCapacity) {
clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll

View File

@ -6,22 +6,25 @@ package com.iluwatar.caching;
*
*/
public class UserAccount {
private String userID;
private String userId;
private String userName;
private String additionalInfo;
public UserAccount(String userID, String userName, String additionalInfo) {
this.userID = userID;
/**
* Constructor
*/
public UserAccount(String userId, String userName, String additionalInfo) {
this.userId = userId;
this.userName = userName;
this.additionalInfo = additionalInfo;
}
public String getUserID() {
return userID;
public String getUserId() {
return userId;
}
public void setUserID(String userID) {
this.userID = userID;
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
@ -42,6 +45,6 @@ public class UserAccount {
@Override
public String toString() {
return userID + ", " + userName + ", " + additionalInfo;
return userId + ", " + userName + ", " + additionalInfo;
}
}

View File

@ -16,7 +16,7 @@ public class AppTest {
*/
@Before
public void setUp() {
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
// to avoid Maven compilation errors. Set flag to true to run the
// tests with MongoDB (provided that MongoDB is installed and socket
// connection is open).

View File

@ -9,6 +9,9 @@ package com.iluwatar.callback;
*/
public class App {
/**
* Program entry point
*/
public static void main(String[] args) {
Task task = new SimpleTask();
Callback callback = new Callback() {

View File

@ -7,6 +7,9 @@ package com.iluwatar.callback;
*/
public abstract class Task {
/**
* Execute with callback
*/
public final void executeWith(Callback callback) {
execute();
if (callback != null) {

View File

@ -13,6 +13,9 @@ public abstract class RequestHandler {
this.next = next;
}
/**
* Request handler
*/
public void handleRequest(Request req) {
if (next != null) {
next.handleRequest(req);

View File

@ -25,8 +25,10 @@
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java, xml, properties"/>
<property name="severity" value="warning"/>
<property name="severity" value="error"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
@ -48,7 +50,7 @@
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
@ -61,7 +63,7 @@
</module>
<module name="NeedBraces"/>
<module name="LeftCurly">
<property name="maxLineLength" value="100"/>
<property name="maxLineLength" value="120"/>
</module>
<module name="RightCurly"/>
<module name="RightCurly">
@ -86,9 +88,6 @@
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
@ -97,42 +96,19 @@
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<property name="allowOneCharVarInForLoop" value="true"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<!-- Checks for Naming Conventions. -->
<!-- See http://checkstyle.sf.net/config_naming.html -->
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
@ -157,14 +133,6 @@
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="thirdPartyPackageRegExp" value=".*"/>
<property name="specialImportsRegExp" value="com.google"/>
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="customImportOrderRules"
value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
@ -180,11 +148,6 @@
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadocCheck">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
@ -195,7 +158,7 @@
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowedAnnotations" value="Override, Test, Before, After, Parameters, Given, When, BeforeClass, AfterClass"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="MethodName">

View File

@ -30,6 +30,9 @@ public abstract class Target {
@Override
public abstract String toString();
/**
* Print status
*/
public void printStatus() {
System.out.println(String.format("%s, [size=%s] [visibility=%s]", this, getSize(),
getVisibility()));

View File

@ -15,12 +15,18 @@ public class Wizard {
public Wizard() {}
/**
* Cast spell
*/
public void castSpell(Command command, Target target) {
System.out.println(this + " casts " + command + " at " + target);
command.execute(target);
undoStack.offerLast(command);
}
/**
* Undo last spell
*/
public void undoLastSpell() {
if (!undoStack.isEmpty()) {
Command previousSpell = undoStack.pollLast();
@ -30,6 +36,9 @@ public class Wizard {
}
}
/**
* Redo last spell
*/
public void redoLastSpell() {
if (!redoStack.isEmpty()) {
Command previousSpell = redoStack.pollLast();

View File

@ -24,6 +24,9 @@ public abstract class LetterComposite {
protected abstract void printThisAfter();
/**
* Print
*/
public void print() {
printThisBefore();
for (LetterComposite letter : children) {

View File

@ -9,6 +9,9 @@ import java.util.List;
*/
public class Sentence extends LetterComposite {
/**
* Constructor
*/
public Sentence(List<Word> words) {
for (Word w : words) {
this.add(w);

View File

@ -9,6 +9,9 @@ import java.util.List;
*/
public class Word extends LetterComposite {
/**
* Constructor
*/
public Word(List<Letter> letters) {
for (Letter l : letters) {
this.add(l);

View File

@ -21,7 +21,7 @@ import org.apache.log4j.Logger;
*/
public class App {
private static Logger LOGGER = Logger.getLogger(App.class);
private static Logger log = Logger.getLogger(App.class);
/**
* Program entry point.
@ -30,17 +30,17 @@ public class App {
*/
public static void main(final String[] args) {
final CustomerDaoImpl customerDao = new CustomerDaoImpl(generateSampleCustomers());
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
LOGGER.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
final Customer customer = new Customer(4, "Dan", "Danson");
customerDao.addCustomer(customer);
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
customer.setFirstName("Daniel");
customer.setLastName("Danielson");
customerDao.updateCustomer(customer);
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
customerDao.deleteCustomer(customer);
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
}
/**

View File

@ -11,6 +11,9 @@ public class Customer {
private String firstName;
private String lastName;
/**
* Constructor
*/
public Customer(final int id, final String firstName, final String lastName) {
this.id = id;
this.firstName = firstName;
@ -54,8 +57,9 @@ public class Customer {
isEqual = true;
} else if (o != null && (getClass() == o.getClass())) {
final Customer customer = (Customer) o;
if (getId() == customer.getId())
if (getId() == customer.getId()) {
isEqual = true;
}
}
return isEqual;
}

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true"
xmlns:log4j='http://jakarta.apache.org/log4j/'>
xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="console" />
</root>
<root>
<level value="INFO" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

View File

@ -28,7 +28,7 @@ public class App {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executorService.execute(() -> {
while (inventory.addItem(new Item()));
while (inventory.addItem(new Item())) {};
});
}

View File

@ -17,12 +17,18 @@ public class Inventory {
private final List<Item> items;
private final Lock lock;
/**
* Constructor
*/
public Inventory(int inventorySize) {
this.inventorySize = inventorySize;
this.items = new ArrayList<>(inventorySize);
this.lock = new ReentrantLock();
}
/**
* Add item
*/
public boolean addItem(Item item) {
if (items.size() < inventorySize) {
lock.lock();

View File

@ -77,8 +77,8 @@ public class InventoryTest {
final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
executorService.execute(() -> {
while (inventory.addItem(new Item())) ;
});
while (inventory.addItem(new Item())) {};
});
}
// Wait until all threads have finished

View File

@ -5,22 +5,20 @@ import java.util.List;
/**
*
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the
* implementation of that method in the receiver. Sometimes the behaviour must also be determined by
* the type of the parameter.
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the implementation of
* that method in the receiver. Sometimes the behaviour must also be determined by the type of the parameter.
* <p>
* One way to implement this would be to create multiple instanceof-checks for the methods
* parameter. However, this creates a maintenance issue. When new types are added we would also need
* to change the method's implementation and add a new instanceof-check. This violates the single
* responsibility principle - a class should have only one reason to change.
* One way to implement this would be to create multiple instanceof-checks for the methods parameter. However, this
* creates a maintenance issue. When new types are added we would also need to change the method's implementation and
* add a new instanceof-check. This violates the single responsibility principle - a class should have only one reason
* to change.
* <p>
* Instead of the instanceof-checks a better way is to make another virtual call on the parameter
* object. This way new functionality can be easily added without the need to modify existing
* implementation (open-closed principle).
* Instead of the instanceof-checks a better way is to make another virtual call on the parameter object. This way new
* functionality can be easily added without the need to modify existing implementation (open-closed principle).
* <p>
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other.
* Each object has its own coordinates which are checked against the other objects' coordinates. If
* there is an overlap, then the objects collide utilizing the Double Dispatch pattern.
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other. Each object has its
* own coordinates which are checked against the other objects' coordinates. If there is an overlap, then the objects
* collide utilizing the Double Dispatch pattern.
*
*/
public class App {
@ -28,7 +26,8 @@ public class App {
/**
* Program entry point
*
* @param args command line args
* @param args
* command line args
*/
public static void main(String[] args) {
// initialize game objects and print their status
@ -42,8 +41,9 @@ public class App {
// collision check
objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> {
if (o1 != o2 && o1.intersectsWith(o2))
if (o1 != o2 && o1.intersectsWith(o2)) {
o1.collision(o2);
}
}));
System.out.println("");

View File

@ -12,6 +12,9 @@ public class Rectangle {
private int right;
private int bottom;
/**
* Constructor
*/
public Rectangle(int left, int top, int right, int bottom) {
this.left = left;
this.top = top;

View File

@ -107,9 +107,9 @@ public abstract class CollisionTest<O extends GameObject> {
final String targetName = target.getClass().getSimpleName();
final String otherName = other.getClass().getSimpleName();
final String errorMessage = expectTargetOnFire ?
"Expected [" + targetName + "] to be on fire after colliding with [" + otherName + "] but it was not!" :
"Expected [" + targetName + "] not to be on fire after colliding with [" + otherName + "] but it was!";
final String errorMessage = expectTargetOnFire
? "Expected [" + targetName + "] to be on fire after colliding with [" + otherName + "] but it was not!"
: "Expected [" + targetName + "] not to be on fire after colliding with [" + otherName + "] but it was!";
assertEquals(errorMessage, expectTargetOnFire, target.isOnFire());
}
@ -126,9 +126,9 @@ public abstract class CollisionTest<O extends GameObject> {
final String targetName = target.getClass().getSimpleName();
final String otherName = other.getClass().getSimpleName();
final String errorMessage = expectedDamage ?
"Expected [" + targetName + "] to be damaged after colliding with [" + otherName + "] but it was not!" :
"Expected [" + targetName + "] not to be damaged after colliding with [" + otherName + "] but it was!";
final String errorMessage = expectedDamage
? "Expected [" + targetName + "] to be damaged after colliding with [" + otherName + "] but it was not!"
: "Expected [" + targetName + "] not to be damaged after colliding with [" + otherName + "] but it was!";
assertEquals(errorMessage, expectedDamage, target.isDamaged());
}

View File

@ -63,6 +63,37 @@ public abstract class EventEmitterTest<E extends EventEmitter> {
testAllDaysWithDefaultObserver(specialDay, event);
}
/**
* Pass each week of the day, day by day to the event emitter and verify of the given observers
* received the correct event on the special day.
*
* @param specialDay The special day on which an event is emitted
* @param event The expected event emitted by the test object
* @param emitter The event emitter
* @param observers The registered observer mocks
*/
private void testAllDays(final Weekday specialDay, final Event event, final E emitter,
final EventObserver... observers) {
for (final Weekday weekday : Weekday.values()) {
// Pass each week of the day, day by day to the event emitter
emitter.timePasses(weekday);
if (weekday == specialDay) {
// On a special day, every observer should have received the event
for (final EventObserver observer : observers) {
verify(observer, times(1)).onEvent(eq(event));
}
} else {
// On any other normal day, the observers should have received nothing at all
verifyZeroInteractions(observers);
}
}
// The observers should not have received any additional events after the week
verifyNoMoreInteractions(observers);
}
/**
* Go over every day of the month, and check if the event is emitted on the given day. Use an
* event emitter without a default observer
@ -99,35 +130,4 @@ public abstract class EventEmitterTest<E extends EventEmitter> {
testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2);
}
/**
* Pass each week of the day, day by day to the event emitter and verify of the given observers
* received the correct event on the special day.
*
* @param specialDay The special day on which an event is emitted
* @param event The expected event emitted by the test object
* @param emitter The event emitter
* @param observers The registered observer mocks
*/
private void testAllDays(final Weekday specialDay, final Event event, final E emitter,
final EventObserver... observers) {
for (final Weekday weekday : Weekday.values()) {
// Pass each week of the day, day by day to the event emitter
emitter.timePasses(weekday);
if (weekday == specialDay) {
// On a special day, every observer should have received the event
for (final EventObserver observer : observers) {
verify(observer, times(1)).onEvent(eq(event));
}
} else {
// On any other normal day, the observers should have received nothing at all
verifyZeroInteractions(observers);
}
}
// The observers should not have received any additional events after the week
verifyNoMoreInteractions(observers);
}
}

View File

@ -24,7 +24,7 @@ public class KingsHandTest extends EventEmitterTest<KingsHand> {
}
/**
* The {@link KingsHand} is both an {@EventEmitter} as an {@link EventObserver} so verify if every
* The {@link KingsHand} is both an {@link EventEmitter} as an {@link EventObserver} so verify if every
* event received is passed up to it's superior, in most cases {@link KingJoffrey} but now just a
* mocked observer.
*/

View File

@ -17,9 +17,6 @@ public class App {
/**
* Program entry point
*
* @param args command line args
* @throws IOException
*/
public static void main(String[] args) throws IOException {

View File

@ -11,6 +11,9 @@ import java.io.IOException;
*/
public class SimpleFileWriter {
/**
* Constructor
*/
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
FileWriter writer = new FileWriter(filename);
try {

View File

@ -65,11 +65,11 @@ public class SimpleFileWriterTest {
* Verify if an {@link IOException} during the write ripples through
*/
@Test(expected = IOException.class)
public void testIOException() throws Exception {
public void testIoException() throws Exception {
final File temporaryFile = this.testFolder.newFile();
new SimpleFileWriter(temporaryFile.getPath(), writer -> {
throw new IOException("");
});
throw new IOException("");
});
}
}

View File

@ -16,6 +16,9 @@ public class DwarvenGoldmineFacade {
private final List<DwarvenMineWorker> workers;
/**
* Constructor
*/
public DwarvenGoldmineFacade() {
workers = new ArrayList<>();
workers.add(new DwarvenGoldDigger());

View File

@ -46,6 +46,9 @@ public abstract class DwarvenMineWorker {
}
}
/**
* Perform actions
*/
public void action(Action... actions) {
for (Action action : actions) {
action(action);

View File

@ -1,15 +1,19 @@
package com.iluwatar.fluentinterface.app;
import static java.lang.String.valueOf;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.function.Predicate;
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;
import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import static java.lang.String.valueOf;
/**
* The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API.
* Those interfaces tend to mimic domain specific languages, so they can nearly be read as human
@ -24,6 +28,9 @@ import static java.lang.String.valueOf;
*/
public class App {
/**
* Program entry point
*/
public static void main(String[] args) {
List<Integer> integerList = new ArrayList<>();

View File

@ -5,8 +5,6 @@ import java.util.Iterator;
/**
* This class is used to realize LazyFluentIterables. It decorates a given iterator. Does not
* support consecutive hasNext() calls.
*
* @param <TYPE>
*/
public abstract class DecoratingIterator<TYPE> implements Iterator<TYPE> {
@ -16,8 +14,6 @@ public abstract class DecoratingIterator<TYPE> implements Iterator<TYPE> {
/**
* Creates an iterator that decorates the given iterator.
*
* @param fromIterator
*/
public DecoratingIterator(Iterator<TYPE> fromIterator) {
this.fromIterator = fromIterator;

View File

@ -1,12 +1,16 @@
package com.iluwatar.fluentinterface.fluentiterable.simple;
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
/**
* This is a simple implementation of the FluentIterable interface. It evaluates all chained
* operations eagerly. This implementation would be costly to be utilized in real applications.

View File

@ -26,7 +26,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
public abstract class FluentIterableTest {
/**
* Create a new {@link FluentIterable<Integer>} from the given integers
* Create a new {@link FluentIterable} from the given integers
*
* @param integers The integers
* @return The new iterable, use for testing

View File

@ -31,6 +31,9 @@ public class Dispatcher {
stores.add(store);
}
/**
* Menu item selected handler
*/
public void menuItemSelected(MenuItem menuItem) {
dispatchAction(new MenuAction(menuItem));
switch (menuItem) {

View File

@ -14,6 +14,9 @@ public class AlchemistShop {
private List<Potion> topShelf;
private List<Potion> bottomShelf;
/**
* Constructor
*/
public AlchemistShop() {
topShelf = new ArrayList<>();
bottomShelf = new ArrayList<>();
@ -58,6 +61,9 @@ public class AlchemistShop {
return Collections.unmodifiableList(this.bottomShelf);
}
/**
* Enumerate potions
*/
public void enumerate() {
System.out.println("Enumerating top shelf potions\n");

View File

@ -2,32 +2,34 @@ package com.iluwatar.front.controller;
/**
*
* The Front Controller is a presentation tier pattern. Essentially it defines a
* controller that handles all requests for a web site.
* The Front Controller is a presentation tier pattern. Essentially it defines a controller that
* handles all requests for a web site.
* <p>
* The Front Controller pattern consolidates request handling through a single handler
* object ({@link FrontController}). This object can carry out the common the behavior such as
* The Front Controller pattern consolidates request handling through a single handler object (
* {@link FrontController}). This object can carry out the common the behavior such as
* authorization, request logging and routing requests to corresponding views.
* <p>
* Typically the requests are mapped to command objects ({@link Command}) which then display
* the correct view ({@link View}).
* Typically the requests are mapped to command objects ({@link Command}) which then display the
* correct view ({@link View}).
* <p>
* In this example we have implemented two views: {@link ArcherView} and {@link CatapultView}. These
* are displayed by sending correct request to the {@link FrontController} object. For example,
* the {@link ArcherView} gets displayed when {@link FrontController} receives request "Archer". When
* are displayed by sending correct request to the {@link FrontController} object. For example, the
* {@link ArcherView} gets displayed when {@link FrontController} receives request "Archer". When
* the request is unknown, we display the error view ({@link ErrorView}).
*
*/
public class App {
/**
* Program entry point
* @param args command line args
*/
public static void main(String[] args) {
FrontController controller = new FrontController();
controller.handleRequest("Archer");
controller.handleRequest("Catapult");
controller.handleRequest("foobar");
}
/**
* Program entry point
*
* @param args
* command line args
*/
public static void main(String[] args) {
FrontController controller = new FrontController();
controller.handleRequest("Archer");
controller.handleRequest("Catapult");
controller.handleRequest("foobar");
}
}

View File

@ -7,9 +7,9 @@ package com.iluwatar.front.controller;
*/
public class ApplicationException extends RuntimeException {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public ApplicationException(Throwable cause) {
super(cause);
}
public ApplicationException(Throwable cause) {
super(cause);
}
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class ArcherCommand implements Command {
@Override
public void process() {
new ArcherView().display();
}
@Override
public void process() {
new ArcherView().display();
}
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class ArcherView implements View {
@Override
public void display() {
System.out.println("Displaying archers");
}
@Override
public void display() {
System.out.println("Displaying archers");
}
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class CatapultCommand implements Command {
@Override
public void process() {
new CatapultView().display();
}
@Override
public void process() {
new CatapultView().display();
}
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class CatapultView implements View {
@Override
public void display() {
System.out.println("Displaying catapults");
}
@Override
public void display() {
System.out.println("Displaying catapults");
}
}

View File

@ -6,6 +6,6 @@ package com.iluwatar.front.controller;
*
*/
public interface Command {
void process();
void process();
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class ErrorView implements View {
@Override
public void display() {
System.out.println("Error 500");
}
@Override
public void display() {
System.out.println("Error 500");
}
}

View File

@ -2,33 +2,33 @@ package com.iluwatar.front.controller;
/**
*
* FrontController is the handler class that takes in all the requests and
* renders the correct response.
* FrontController is the handler class that takes in all the requests and renders the correct
* response.
*
*/
public class FrontController {
public void handleRequest(String request) {
Command command = getCommand(request);
command.process();
}
private Command getCommand(String request) {
Class commandClass = getCommandClass(request);
try {
return (Command) commandClass.newInstance();
} catch (Exception e) {
throw new ApplicationException(e);
}
}
private Class getCommandClass(String request) {
Class result;
try {
result = Class.forName("com.iluwatar.front.controller." + request + "Command");
} catch (ClassNotFoundException e) {
result = UnknownCommand.class;
}
return result;
}
public void handleRequest(String request) {
Command command = getCommand(request);
command.process();
}
private Command getCommand(String request) {
Class commandClass = getCommandClass(request);
try {
return (Command) commandClass.newInstance();
} catch (Exception e) {
throw new ApplicationException(e);
}
}
private Class getCommandClass(String request) {
Class result;
try {
result = Class.forName("com.iluwatar.front.controller." + request + "Command");
} catch (ClassNotFoundException e) {
result = UnknownCommand.class;
}
return result;
}
}

View File

@ -7,8 +7,8 @@ package com.iluwatar.front.controller;
*/
public class UnknownCommand implements Command {
@Override
public void process() {
new ErrorView().display();
}
@Override
public void process() {
new ErrorView().display();
}
}

View File

@ -7,5 +7,5 @@ package com.iluwatar.front.controller;
*/
public interface View {
void display();
void display();
}

View File

@ -10,10 +10,10 @@ import com.iluwatar.front.controller.App;
*
*/
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
@Test
public void test() {
String[] args = {};
App.main(args);
}
}

View File

@ -1,8 +1,8 @@
package com.iluwatar.front.controller;
import org.junit.Test;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Date: 12/13/15 - 1:35 PM

View File

@ -21,17 +21,15 @@ import java.util.concurrent.LinkedBlockingQueue;
*
* <p>
* <i>APPLICABILITY</i> <br/>
* <ul>
* <li>UNIX network subsystems - In operating systems network operations are carried out
* asynchronously with help of hardware level interrupts.</li>
* <li>CORBA - At the asynchronous layer one thread is associated with each socket that is connected
* UNIX network subsystems - In operating systems network operations are carried out
* asynchronously with help of hardware level interrupts.<br/>
* CORBA - At the asynchronous layer one thread is associated with each socket that is connected
* to the client. Thread blocks waiting for CORBA requests from the client. On receiving request it
* is inserted in the queuing layer which is then picked up by synchronous layer which processes the
* request and sends response back to the client.</li>
* <li>Android AsyncTask framework - Framework provides a way to execute long running blocking
* request and sends response back to the client.<br/>
* Android AsyncTask framework - Framework provides a way to execute long running blocking
* calls, such as downloading a file, in background threads so that the UI thread remains free to
* respond to user inputs.</i>
* </ul>
* respond to user inputs.<br/>
*
* <p>
* <i>IMPLEMENTATION</i> <br/>
@ -121,6 +119,7 @@ public class App {
try {
Thread.sleep(i);
} catch (InterruptedException e) {
System.out.println(e);
}
return (i) * (i + 1) / 2;
}

View File

@ -14,7 +14,8 @@ public class AddressFilter extends AbstractFilter {
String result = super.execute(order);
if (order.getAddress() == null || order.getAddress().isEmpty()) {
return result + "Invalid address! ";
} else
} else {
return result;
}
}
}

View File

@ -32,8 +32,12 @@ public class Client extends JFrame {
private JLabel jl;
private JTextField[] jtFields;
private JTextArea[] jtAreas;
private JButton clearButton, processButton;
private JButton clearButton;
private JButton processButton;
/**
* Constructor
*/
public Client() {
super("Client System");
setDefaultCloseOperation(EXIT_ON_CLOSE);

View File

@ -11,30 +11,21 @@ public interface Filter {
/**
* Execute order processing filter.
*
* @param order
* @return empty string on success, otherwise error message.
*/
String execute(Order order);
/**
* Set next filter in chain after this.
*
* @param filter
*/
void setNext(Filter filter);
/**
* Get next filter in chain after this.
*
* @return
*/
Filter getNext();
/**
* Get last filter in the chain.
*
* @return
*/
Filter getLast();
}

View File

@ -12,10 +12,16 @@ public class FilterChain {
private final Target target;
/**
* Constructor
*/
public FilterChain(Target target) {
this.target = target;
}
/**
* Adds filter
*/
public void addFilter(Filter filter) {
if (chain == null) {
chain = filter;
@ -24,6 +30,9 @@ public class FilterChain {
}
}
/**
* Execute filter chain
*/
public String execute(Order order) {
if (chain != null) {
return chain.execute(order);

View File

@ -14,6 +14,9 @@ public class Order {
public Order() {}
/**
* Constructor
*/
public Order(String name, String contactNumber, String address, String depositNumber, String order) {
this.name = name;
this.contactNumber = contactNumber;

View File

@ -29,6 +29,9 @@ public class Target extends JFrame {
private DefaultTableModel dtm;
private JButton del;
/**
* Constructor
*/
public Target() {
super("Order System");
setDefaultCloseOperation(EXIT_ON_CLOSE);
@ -67,8 +70,9 @@ public class Target extends JFrame {
@Override
public void actionPerformed(ActionEvent e) {
int temp = jt.getSelectedRow();
if (temp == -1)
if (temp == -1) {
return;
}
int temp2 = jt.getSelectedRowCount();
for (int i = 0; i < temp2; i++) {
dtm.removeRow(temp);

View File

@ -73,6 +73,9 @@ public class FilterTest {
private final Order order;
private final String result;
/**
* Constructor
*/
public FilterTest(Filter filter, Order order, String result) {
this.filter = filter;
this.order = order;

View File

@ -55,6 +55,9 @@ public class App {
return s.equals("+") || s.equals("-") || s.equals("*");
}
/**
* Get expression for string
*/
public static Expression getOperatorInstance(String s, Expression left, Expression right) {
switch (s) {
case "+":
@ -63,7 +66,8 @@ public class App {
return new MinusExpression(left, right);
case "*":
return new MultiplyExpression(left, right);
default:
return new MultiplyExpression(left, right);
}
return null;
}
}

View File

@ -27,9 +27,9 @@ public abstract class ExpressionTest<E extends Expression> {
for (int i = -10; i < 10; i++) {
for (int j = -10; j < 10; j++) {
testData.add(new Object[]{
new NumberExpression(i),
new NumberExpression(j),
resultCalc.apply(i, j)
new NumberExpression(i),
new NumberExpression(j),
resultCalc.apply(i, j)
});
}
}

View File

@ -20,28 +20,28 @@ public class App {
public static void main(String[] args) {
TreasureChest chest = new TreasureChest();
ItemIterator ringIterator = chest.Iterator(ItemType.RING);
ItemIterator ringIterator = chest.iterator(ItemType.RING);
while (ringIterator.hasNext()) {
System.out.println(ringIterator.next());
}
System.out.println("----------");
ItemIterator potionIterator = chest.Iterator(ItemType.POTION);
ItemIterator potionIterator = chest.iterator(ItemType.POTION);
while (potionIterator.hasNext()) {
System.out.println(potionIterator.next());
}
System.out.println("----------");
ItemIterator weaponIterator = chest.Iterator(ItemType.WEAPON);
ItemIterator weaponIterator = chest.iterator(ItemType.WEAPON);
while (weaponIterator.hasNext()) {
System.out.println(weaponIterator.next());
}
System.out.println("----------");
ItemIterator it = chest.Iterator(ItemType.ANY);
ItemIterator it = chest.iterator(ItemType.ANY);
while (it.hasNext()) {
System.out.println(it.next());
}

View File

@ -12,6 +12,9 @@ public class TreasureChest {
private List<Item> items;
/**
* Constructor
*/
public TreasureChest() {
items = new ArrayList<>();
items.add(new Item(ItemType.POTION, "Potion of courage"));
@ -26,10 +29,13 @@ public class TreasureChest {
items.add(new Item(ItemType.WEAPON, "Dagger of poison"));
}
ItemIterator Iterator(ItemType type) {
return new TreasureChestItemIterator(this, type);
ItemIterator iterator(ItemType itemType) {
return new TreasureChestItemIterator(this, itemType);
}
/**
* Get all items
*/
public List<Item> getItems() {
ArrayList<Item> list = new ArrayList<>();
list.addAll(items);

View File

@ -13,6 +13,9 @@ public class TreasureChestItemIterator implements ItemIterator {
private int idx;
private ItemType type;
/**
* Constructor
*/
public TreasureChestItemIterator(TreasureChest chest, ItemType type) {
this.chest = chest;
this.type = type;

View File

@ -60,7 +60,7 @@ public class TreasureChestTest {
@Test
public void testIterator() {
final TreasureChest chest = new TreasureChest();
final ItemIterator iterator = chest.Iterator(expectedItem.getType());
final ItemIterator iterator = chest.iterator(expectedItem.getType());
assertNotNull(iterator);
while (iterator.hasNext()) {

View File

@ -4,31 +4,31 @@ import java.util.Arrays;
/**
*
* Layers is an architectural style where software responsibilities are divided among the different
* layers of the application.
* Layers is an architectural style where software responsibilities are divided among the different layers of the
* application.
* <p>
* This example demonstrates a traditional 3-layer architecture consisting of data access layer,
* business layer and presentation layer.
* This example demonstrates a traditional 3-layer architecture consisting of data access layer, business layer and
* presentation layer.
* <p>
* The data access layer is formed of Spring Data repositories <code>CakeDao</code>,
* <code>CakeToppingDao</code> and <code>CakeLayerDao</code>. The repositories can be used for CRUD
* operations on cakes, cake toppings and cake layers respectively.
* The data access layer is formed of Spring Data repositories <code>CakeDao</code>, <code>CakeToppingDao</code> and
* <code>CakeLayerDao</code>. The repositories can be used for CRUD operations on cakes, cake toppings and cake layers
* respectively.
* <p>
* The business layer is built on top of the data access layer. <code>CakeBakingService</code>
* offers methods to retrieve available cake toppings and cake layers and baked cakes. Also the
* service is used to create new cakes out of cake toppings and cake layers.
* The business layer is built on top of the data access layer. <code>CakeBakingService</code> offers methods to
* retrieve available cake toppings and cake layers and baked cakes. Also the service is used to create new cakes out of
* cake toppings and cake layers.
* <p>
* The presentation layer is built on the business layer and in this example it simply lists the
* cakes that have been baked.
* The presentation layer is built on the business layer and in this example it simply lists the cakes that have been
* baked.
* <p>
* We have applied so called strict layering which means that the layers can only access the classes
* directly beneath them. This leads the solution to create an additional set of DTOs (
* <code>CakeInfo</code>, <code>CakeToppingInfo</code>, <code>CakeLayerInfo</code>) to translate
* data between layers. In other words, <code>CakeBakingService</code> cannot return entities (
* <code>Cake</code>, <code>CakeTopping</code>, <code>CakeLayer</code>) directly since these reside
* on data access layer but instead translates these into business layer DTOs (<code>CakeInfo</code>, <code>CakeToppingInfo</code>, <code>CakeLayerInfo</code>) and returns them instead. This way
* the presentation layer does not have any knowledge of other layers than the business layer and
* thus is not affected by changes to them.
* We have applied so called strict layering which means that the layers can only access the classes directly beneath
* them. This leads the solution to create an additional set of DTOs ( <code>CakeInfo</code>,
* <code>CakeToppingInfo</code>, <code>CakeLayerInfo</code>) to translate data between layers. In other words,
* <code>CakeBakingService</code> cannot return entities ( <code>Cake</code>, <code>CakeTopping</code>,
* <code>CakeLayer</code>) directly since these reside on data access layer but instead translates these into business
* layer DTOs (<code>CakeInfo</code>, <code>CakeToppingInfo</code>, <code>CakeLayerInfo</code>) and returns them
* instead. This way the presentation layer does not have any knowledge of other layers than the business layer and thus
* is not affected by changes to them.
*
* @see Cake
* @see CakeTopping
@ -63,8 +63,6 @@ public class App {
/**
* Initializes the example data
*
* @param cakeBakingService
*/
private static void initializeData(CakeBakingService cakeBakingService) {
cakeBakingService.saveNewLayer(new CakeLayerInfo("chocolate", 1200));

View File

@ -11,44 +11,31 @@ public interface CakeBakingService {
/**
* Bakes new cake according to parameters
*
* @param cakeInfo
* @throws CakeBakingException
*/
void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;
/**
* Get all cakes
*
* @return
*/
List<CakeInfo> getAllCakes();
/**
* Store new cake topping
*
* @param toppingInfo
*/
void saveNewTopping(CakeToppingInfo toppingInfo);
/**
* Get available cake toppings
*
* @return
*/
List<CakeToppingInfo> getAvailableToppings();
/**
* Add new cake layer
*
* @param layerInfo
*/
void saveNewLayer(CakeLayerInfo layerInfo);
/**
* Get available cake layers
*
* @return
*/
List<CakeLayerInfo> getAvailableLayers();
}

View File

@ -14,18 +14,27 @@ public class CakeInfo {
public final CakeToppingInfo cakeToppingInfo;
public final List<CakeLayerInfo> cakeLayerInfos;
/**
* Constructor
*/
public CakeInfo(Long id, CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {
this.id = Optional.of(id);
this.cakeToppingInfo = cakeToppingInfo;
this.cakeLayerInfos = cakeLayerInfos;
}
/**
* Constructor
*/
public CakeInfo(CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {
this.id = Optional.empty();
this.cakeToppingInfo = cakeToppingInfo;
this.cakeLayerInfos = cakeLayerInfos;
}
/**
* Calculate calories
*/
public int calculateTotalCalories() {
int total = cakeToppingInfo != null ? cakeToppingInfo.calories : 0;
total += cakeLayerInfos.stream().mapToInt(c -> c.calories).sum();

View File

@ -13,12 +13,18 @@ public class CakeLayerInfo {
public final String name;
public final int calories;
/**
* Constructor
*/
public CakeLayerInfo(Long id, String name, int calories) {
this.id = Optional.of(id);
this.name = name;
this.calories = calories;
}
/**
* Constructor
*/
public CakeLayerInfo(String name, int calories) {
this.id = Optional.empty();
this.name = name;

View File

@ -13,12 +13,18 @@ public class CakeToppingInfo {
public final String name;
public final int calories;
/**
* Constructor
*/
public CakeToppingInfo(Long id, String name, int calories) {
this.id = Optional.of(id);
this.name = name;
this.calories = calories;
}
/**
* Constructor
*/
public CakeToppingInfo(String name, int calories) {
this.id = Optional.empty();
this.name = name;

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="jpaData" />
<persistence-unit name="jpaData" />
</persistence>

View File

@ -1,42 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<jpa:repositories base-package="com.iluwatar" />
<jpa:repositories base-package="com.iluwatar" />
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:~/databases/cake" />
<property name="username" value="sa" />
<property name="password" value="sa" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:~/databases/cake" />
<property name="username" value="sa" />
<property name="password" value="sa" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.iluwatar" />
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<entry key="hibernate.hbm2ddl.auto" value="create-drop" />
<entry key="hibernate.show_sql" value="false" />
</map>
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.iluwatar" />
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<entry key="hibernate.hbm2ddl.auto" value="create-drop" />
<entry key="hibernate.show_sql" value="false" />
</map>
</property>
</bean>
</beans>

View File

@ -7,6 +7,9 @@ package com.iluwatar.lazy.loading;
*/
public class Heavy {
/**
* Constructor
*/
public Heavy() {
System.out.println("Creating Heavy ...");
try {

View File

@ -9,10 +9,16 @@ public class HolderNaive {
private Heavy heavy;
/**
* Constructor
*/
public HolderNaive() {
System.out.println("HolderNaive created");
}
/**
* Get heavy object
*/
public Heavy getHeavy() {
if (heavy == null) {
heavy = new Heavy();

View File

@ -10,10 +10,16 @@ public class HolderThreadSafe {
private Heavy heavy;
/**
* Constructor
*/
public HolderThreadSafe() {
System.out.println("HolderThreadSafe created");
}
/**
* Get heavy object
*/
public synchronized Heavy getHeavy() {
if (heavy == null) {
heavy = new Heavy();

View File

@ -5,7 +5,7 @@ import java.util.function.Supplier;
/**
*
* This lazy loader is thread safe and more efficient than {@link HolderThreadSafe}. It utilizes
* Java 8 functional interface {@link Supplier<T>} as {@link Heavy} factory.
* Java 8 functional interface {@link Supplier} as {@link Heavy} factory.
*
*/
public class Java8Holder {

View File

@ -23,6 +23,9 @@ import java.util.Stack;
*/
public class App {
/**
* Program entry point
*/
public static void main(String[] args) {
Stack<StarMemento> states = new Stack<>();

View File

@ -11,12 +11,18 @@ public class Star {
private int ageYears;
private int massTons;
/**
* Constructor
*/
public Star(StarType startType, int startAge, int startMass) {
this.type = startType;
this.ageYears = startAge;
this.massTons = startMass;
}
/**
* Makes time pass for the star
*/
public void timePasses() {
ageYears *= 2;
massTons *= 8;

View File

@ -30,9 +30,6 @@ public class App {
/**
* Program entry point
*
* @param args command line args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();

View File

@ -39,9 +39,7 @@ public class FileLoader {
br.close();
return sb.toString();
}
catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -26,7 +26,7 @@ public class FileSelectorJFrame extends JFrame implements FileSelectorView, Acti
/**
* The "OK" button for loading the file.
*/
private JButton OK;
private JButton ok;
/**
* The cancel button.
@ -121,10 +121,10 @@ public class FileSelectorJFrame extends JFrame implements FileSelectorView, Acti
/*
* Add the OK button.
*/
this.OK = new JButton("OK");
this.panel.add(OK);
this.OK.setBounds(250, 50, 100, 25);
this.OK.addActionListener(this);
this.ok = new JButton("OK");
this.panel.add(ok);
this.ok.setBounds(250, 50, 100, 25);
this.ok.addActionListener(this);
/*
* Add the cancel button.
@ -140,13 +140,11 @@ public class FileSelectorJFrame extends JFrame implements FileSelectorView, Acti
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == this.OK) {
if (e.getSource() == this.ok) {
this.fileName = this.input.getText();
presenter.fileNameChanged();
presenter.confirmed();
}
else if (e.getSource() == this.cancel) {
} else if (e.getSource() == this.cancel) {
presenter.cancelled();
}
}

View File

@ -51,6 +51,9 @@ public class FileSelectorPresenter {
loader.setFileName(view.getFileName());
}
/**
* Ok button handler
*/
public void confirmed() {
if (loader.getFileName() == null || loader.getFileName().equals("")) {
view.showMessage("Please give the name of the file first!");
@ -60,9 +63,7 @@ public class FileSelectorPresenter {
if (loader.fileExists()) {
String data = loader.loadData();
view.displayData(data);
}
else {
} else {
view.showMessage("The file specified does not exist.");
}
}

View File

@ -1,14 +1,13 @@
package com.iluwatar.model.view.presenter;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import com.iluwatar.model.view.presenter.FileLoader;
import com.iluwatar.model.view.presenter.FileSelectorPresenter;
import com.iluwatar.model.view.presenter.FileSelectorStub;
/**
* This test case is responsible for testing our application by taking advantage of the
* Model-View-Controller architectural pattern.
@ -57,13 +56,13 @@ public class FileSelectorPresenterTest {
*/
@Test
public void updateFileNameToLoader() {
String EXPECTED_FILE = "Stamatis";
stub.setFileName(EXPECTED_FILE);
String expectedFile = "Stamatis";
stub.setFileName(expectedFile);
presenter.start();
presenter.fileNameChanged();
assertEquals(EXPECTED_FILE, loader.getFileName());
assertEquals(expectedFile, loader.getFileName());
}
/**

View File

@ -24,6 +24,9 @@ public class LoadBalancer {
servers.add(new Server("localhost", 8084, ++id));
}
/**
* Add new server
*/
public final void addServer(Server server) {
synchronized (servers) {
servers.add(server);
@ -39,6 +42,9 @@ public class LoadBalancer {
return lastServedId;
}
/**
* Handle request
*/
public void serverequest(Request request) {
if (lastServedId >= servers.size()) {
lastServedId = 0;

View File

@ -11,6 +11,9 @@ public class Server {
public final int port;
public final int id;
/**
* Constructor
*/
public Server(String host, int port, int id) {
this.host = host;
this.port = port;

View File

@ -21,9 +21,7 @@ import org.apache.isis.applib.annotation.HomePage;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.SemanticsOf;
@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY // trick to suppress the actions
// from the top-level menu
)
@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
public class HomePageService {
// region > homePage (action)

View File

@ -69,9 +69,12 @@ public class SimpleObjects {
}
}
/**
* Create simple object
*/
@Action(domainEvent = CreateDomainEvent.class)
@MemberOrder(sequence = "3")
public SimpleObject create(final @ParameterLayout(named = "Name") String name) {
public SimpleObject create(@ParameterLayout(named = "Name") final String name) {
final SimpleObject obj = container.newTransientInstance(SimpleObject.class);
obj.setName(name);
container.persistIfNotAlready(obj);

View File

@ -45,8 +45,6 @@ public class SimpleObjectCreate extends FixtureScript {
/**
* The created simple object (output).
*
* @return
*/
public SimpleObject getSimpleObject() {
return simpleObject;

View File

@ -29,7 +29,7 @@ import domainapp.fixture.modules.simple.SimpleObjectsTearDown;
public class RecreateSimpleObjects extends FixtureScript {
public final List<String> NAMES = Collections.unmodifiableList(Arrays.asList("Foo", "Bar", "Baz",
public final List<String> names = Collections.unmodifiableList(Arrays.asList("Foo", "Bar", "Baz",
"Frodo", "Froyo", "Fizz", "Bip", "Bop", "Bang", "Boo"));
public RecreateSimpleObjects() {
@ -72,9 +72,9 @@ public class RecreateSimpleObjects extends FixtureScript {
final int number = defaultParam("number", ec, 3);
// validate
if (number < 0 || number > NAMES.size()) {
if (number < 0 || number > names.size()) {
throw new IllegalArgumentException(String.format("number must be in range [0,%d)",
NAMES.size()));
names.size()));
}
//
@ -83,7 +83,7 @@ public class RecreateSimpleObjects extends FixtureScript {
ec.executeChild(this, new SimpleObjectsTearDown());
for (int i = 0; i < number; i++) {
final SimpleObjectCreate fs = new SimpleObjectCreate().setName(NAMES.get(i));
final SimpleObjectCreate fs = new SimpleObjectCreate().setName(names.get(i));
ec.executeChild(this, fs.getName(), fs);
simpleObjects.add(fs.getSimpleObject());
}

View File

@ -21,6 +21,9 @@ import org.apache.isis.objectstore.jdo.datanucleus.IsisConfigurationForJdoIntegT
public class SimpleAppSystemInitializer {
/**
* Init test system
*/
public static void initIsft() {
IsisSystemForTest isft = IsisSystemForTest.getElseNull();
if (isft == null) {

View File

@ -29,7 +29,7 @@ import static org.junit.Assert.assertThat;
public class SimpleObjectGlue extends CukeGlueAbstract {
@Given("^there are.* (\\d+) simple objects$")
public void there_are_N_simple_objects(int n) throws Throwable {
public void thereAreNumSimpleObjects(int n) throws Throwable {
try {
final List<SimpleObject> findAll = service(SimpleObjects.class).listAll();
assertThat(findAll.size(), is(n));
@ -41,7 +41,7 @@ public class SimpleObjectGlue extends CukeGlueAbstract {
}
@When("^I create a new simple object$")
public void I_create_a_new_simple_object() throws Throwable {
public void createNewSimpleObject() throws Throwable {
service(SimpleObjects.class).create(UUID.randomUUID().toString());
}

View File

@ -27,13 +27,13 @@ import domainapp.integtests.bootstrap.SimpleAppSystemInitializer;
public abstract class SimpleAppIntegTest extends IntegrationTestAbstract {
@BeforeClass
public static void initClass() {
org.apache.log4j.PropertyConfigurator.configure("logging.properties");
SimpleAppSystemInitializer.initIsft();
@BeforeClass
public static void initClass() {
org.apache.log4j.PropertyConfigurator.configure("logging.properties");
SimpleAppSystemInitializer.initIsft();
// instantiating will install onto ThreadLocal
new ScenarioExecutionForIntegration();
}
// instantiating will install onto ThreadLocal
new ScenarioExecutionForIntegration();
}
}

View File

@ -35,87 +35,86 @@ import static org.assertj.core.api.Assertions.assertThat;
public class SimpleObjectIntegTest extends SimpleAppIntegTest {
@Inject
FixtureScripts fixtureScripts;
RecreateSimpleObjects fs;
SimpleObject simpleObjectPojo;
SimpleObject simpleObjectWrapped;
@Before
public void setUp() throws Exception {
// given
fs = new RecreateSimpleObjects().setNumber(1);
fixtureScripts.runFixtureScript(fs, null);
simpleObjectPojo = fs.getSimpleObjects().get(0);
assertThat(simpleObjectPojo).isNotNull();
simpleObjectWrapped = wrap(simpleObjectPojo);
}
public static class Name extends SimpleObjectIntegTest {
@Test
public void accessible() throws Exception {
// when
final String name = simpleObjectWrapped.getName();
// then
assertThat(name).isEqualTo(fs.names.get(0));
}
@Test
public void cannotBeUpdatedDirectly() throws Exception {
// expect
expectedExceptions.expect(DisabledException.class);
// when
simpleObjectWrapped.setName("new name");
}
}
public static class UpdateName extends SimpleObjectIntegTest {
@Test
public void happyCase() throws Exception {
// when
simpleObjectWrapped.updateName("new name");
// then
assertThat(simpleObjectWrapped.getName()).isEqualTo("new name");
}
@Test
public void failsValidation() throws Exception {
// expect
expectedExceptions.expect(InvalidException.class);
expectedExceptions.expectMessage("Exclamation mark is not allowed");
// when
simpleObjectWrapped.updateName("new name!");
}
}
public static class Title extends SimpleObjectIntegTest {
@Inject
FixtureScripts fixtureScripts;
DomainObjectContainer container;
RecreateSimpleObjects fs;
SimpleObject simpleObjectPojo;
SimpleObject simpleObjectWrapped;
@Test
public void interpolatesName() throws Exception {
@Before
public void setUp() throws Exception {
// given
fs = new RecreateSimpleObjects().setNumber(1);
fixtureScripts.runFixtureScript(fs, null);
// given
final String name = simpleObjectWrapped.getName();
simpleObjectPojo = fs.getSimpleObjects().get(0);
// when
final String title = container.titleOf(simpleObjectWrapped);
assertThat(simpleObjectPojo).isNotNull();
simpleObjectWrapped = wrap(simpleObjectPojo);
}
public static class Name extends SimpleObjectIntegTest {
@Test
public void accessible() throws Exception {
// when
final String name = simpleObjectWrapped.getName();
// then
assertThat(name).isEqualTo(fs.NAMES.get(0));
}
@Test
public void cannotBeUpdatedDirectly() throws Exception {
// expect
expectedExceptions.expect(DisabledException.class);
// when
simpleObjectWrapped.setName("new name");
}
}
public static class UpdateName extends SimpleObjectIntegTest {
@Test
public void happyCase() throws Exception {
// when
simpleObjectWrapped.updateName("new name");
// then
assertThat(simpleObjectWrapped.getName()).isEqualTo("new name");
}
@Test
public void failsValidation() throws Exception {
// expect
expectedExceptions.expect(InvalidException.class);
expectedExceptions.expectMessage("Exclamation mark is not allowed");
// when
simpleObjectWrapped.updateName("new name!");
}
}
public static class Title extends SimpleObjectIntegTest {
@Inject
DomainObjectContainer container;
@Test
public void interpolatesName() throws Exception {
// given
final String name = simpleObjectWrapped.getName();
// when
final String title = container.titleOf(simpleObjectWrapped);
// then
assertThat(title).isEqualTo("Object: " + name);
}
// then
assertThat(title).isEqualTo("Object: " + name);
}
}
}

Some files were not shown because too many files have changed in this diff Show More