Adjust checkstyle rules. Make checkstyle fail the build when violations are found. Correct all current checkstyle violations.
This commit is contained in:
abstract-factory/src/main/java/com/iluwatar/abstractfactory
async-method-invocation/src
main
java
com
iluwatar
async
method
test
java
com
iluwatar
async
method
invocation
builder/src/main/java/com/iluwatar/builder
business-delegate/src/main/java/com/iluwatar/business/delegate
caching/src
main
java
test
java
com
iluwatar
caching
callback/src/main/java/com/iluwatar/callback
chain/src/main/java/com/iluwatar/chain
checkstyle.xmlcommand/src/main/java/com/iluwatar/command
composite/src/main/java/com/iluwatar/composite
dao/src/main
double-checked-locking/src
main
java
com
iluwatar
doublechecked
locking
test
java
com
iluwatar
doublechecked
locking
double-dispatch/src
main
java
com
iluwatar
doubledispatch
test
java
com
iluwatar
doubledispatch
event-aggregator/src/test/java/com/iluwatar/event/aggregator
execute-around/src
main
java
com
iluwatar
execute
test
java
com
iluwatar
execute
facade/src/main/java/com/iluwatar/facade
fluentinterface/src
main
java
com
iluwatar
fluentinterface
test
java
com
iluwatar
fluentinterface
fluentiterable
flux/src/main/java/com/iluwatar/flux/dispatcher
flyweight/src/main/java/com/iluwatar/flyweight
front-controller/src
main
java
test
java
com
iluwatar
front
half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync
intercepting-filter/src
main
java
com
iluwatar
test
java
com
iluwatar
intercepting
filter
interpreter/src
iterator/src
main
java
com
iluwatar
test
java
com
iluwatar
iterator
layers/src/main
java
resources
lazy-loading/src/main/java/com/iluwatar/lazy/loading
memento/src/main/java/com/iluwatar/memento
message-channel/src/main/java/com/iluwatar/message/channel
model-view-presenter/src
main
java
com
iluwatar
model
test
java
com
iluwatar
model
view
presenter
monostate/src/main/java/com/iluwatar/monostate
naked-objects
dom
src
main
java
domainapp
dom
fixture
src
main
java
domainapp
fixture
integtests
src
test
java
domainapp
integtests
bootstrap
specglue
modules
simple
tests
webapp
src
main
java
domainapp
webapp
null-object/src/main/java/com/iluwatar/nullobject
object-pool/src/main/java/com/iluwatar/object/pool
observer/src/main/java/com/iluwatar/observer
poison-pill/src/main/java/com/iluwatar/poison/pill
pom.xmlprivate-class-data/src/main/java/com/iluwatar/privateclassdata
producer-consumer/src/main/java/com/iluwatar/producer/consumer
property/src/main/java/com/iluwatar/property
prototype/src/main/java/com/iluwatar/prototype
proxy/src/main/java/com/iluwatar/proxy
publish-subscribe/src/main/java/com/iluwatar/publish/subscribe
reactor/src/main/java/com/iluwatar/reactor
repository/src
main
java
com
iluwatar
resources
test
java
com
iluwatar
resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization
servant/src/main/java/com/iluwatar/servant
service-layer/src/main/java/com/iluwatar/servicelayer
app
common
hibernate
magic
spell
spellbook
wizard
service-locator/src/main/java/com/iluwatar/servicelocator
singleton/src
main
java
test
java
com
iluwatar
specification/src/main/java/com/iluwatar/specification
state/src/main/java/com/iluwatar/state
step-builder/src/main/java/com/iluwatar/stepbuilder
template-method/src/main/java/com/iluwatar/templatemethod
tolerant-reader/src/main/java/com/iluwatar/tolerantreader
twin/src/main/java/com/iluwatar/twin
visitor/src/main/java/com/iluwatar/visitor
@@ -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;
|
||||
}
|
||||
@@ -63,6 +50,10 @@ public class App {
|
||||
this.king = king;
|
||||
}
|
||||
|
||||
Castle getCastle(final KingdomFactory factory) {
|
||||
return factory.createCastle();
|
||||
}
|
||||
|
||||
public Castle getCastle() {
|
||||
return castle;
|
||||
}
|
||||
@@ -71,6 +62,10 @@ public class App {
|
||||
this.castle = castle;
|
||||
}
|
||||
|
||||
Army getArmy(final KingdomFactory factory) {
|
||||
return factory.createArmy();
|
||||
}
|
||||
|
||||
public Army getArmy() {
|
||||
return army;
|
||||
}
|
||||
@@ -79,11 +74,11 @@ 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) {
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -5,8 +5,6 @@ import java.util.concurrent.ExecutionException;
|
||||
/**
|
||||
*
|
||||
* AsyncResult interface
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface AsyncResult<T> {
|
||||
|
||||
|
22
async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java
22
async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java
@@ -34,8 +34,7 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
|
||||
}
|
||||
|
||||
@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;
|
||||
|
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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());
|
||||
|
||||
|
@@ -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");
|
||||
|
@@ -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).
|
||||
|
@@ -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);
|
||||
|
@@ -9,88 +9,115 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes remaining content in the cache into the DB.
|
||||
*/
|
||||
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();
|
||||
|
@@ -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));
|
||||
}
|
@@ -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
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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).
|
||||
|
@@ -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() {
|
||||
|
@@ -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) {
|
||||
|
@@ -13,6 +13,9 @@ public abstract class RequestHandler {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
*/
|
||||
public void handleRequest(Request req) {
|
||||
if (next != null) {
|
||||
next.handleRequest(req);
|
||||
|
@@ -26,7 +26,9 @@
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<property name="severity" value="warning"/>
|
||||
<property name="fileExtensions" value="java, xml, properties"/>
|
||||
|
||||
<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">
|
||||
|
@@ -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()));
|
||||
|
@@ -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();
|
||||
|
@@ -24,6 +24,9 @@ public abstract class LetterComposite {
|
||||
|
||||
protected abstract void printThisAfter();
|
||||
|
||||
/**
|
||||
* Print
|
||||
*/
|
||||
public void print() {
|
||||
printThisBefore();
|
||||
for (LetterComposite letter : children) {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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,9 +57,10 @@ 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;
|
||||
}
|
||||
|
||||
|
@@ -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())) {};
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -77,7 +77,7 @@ 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())) {};
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -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("");
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -65,7 +65,7 @@ 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("");
|
||||
|
@@ -16,6 +16,9 @@ public class DwarvenGoldmineFacade {
|
||||
|
||||
private final List<DwarvenMineWorker> workers;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public DwarvenGoldmineFacade() {
|
||||
workers = new ArrayList<>();
|
||||
workers.add(new DwarvenGoldDigger());
|
||||
|
@@ -46,6 +46,9 @@ public abstract class DwarvenMineWorker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actions
|
||||
*/
|
||||
public void action(Action... actions) {
|
||||
for (Action action : actions) {
|
||||
action(action);
|
||||
|
@@ -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<>();
|
||||
|
@@ -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;
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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");
|
||||
|
@@ -2,19 +2,19 @@ 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}).
|
||||
*
|
||||
*/
|
||||
@@ -22,7 +22,9 @@ public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*
|
||||
* @param args
|
||||
* command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
FrontController controller = new FrontController();
|
||||
|
@@ -2,8 +2,8 @@ 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 {
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
return new MultiplyExpression(left, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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()) {
|
||||
|
@@ -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));
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -1,12 +1,9 @@
|
||||
<?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" />
|
||||
|
||||
|
@@ -7,6 +7,9 @@ package com.iluwatar.lazy.loading;
|
||||
*/
|
||||
public class Heavy {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Heavy() {
|
||||
System.out.println("Creating Heavy ...");
|
||||
try {
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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 {
|
||||
|
@@ -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<>();
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
@@ -39,9 +39,7 @@ public class FileLoader {
|
||||
br.close();
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
15
model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java
15
model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -45,8 +45,6 @@ public class SimpleObjectCreate extends FixtureScript {
|
||||
|
||||
/**
|
||||
* The created simple object (output).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public SimpleObject getSimpleObject() {
|
||||
return simpleObject;
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -61,7 +61,7 @@ public class SimpleObjectIntegTest extends SimpleAppIntegTest {
|
||||
// when
|
||||
final String name = simpleObjectWrapped.getName();
|
||||
// then
|
||||
assertThat(name).isEqualTo(fs.NAMES.get(0));
|
||||
assertThat(name).isEqualTo(fs.names.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -99,7 +99,6 @@ public class SimpleObjectIntegTest extends SimpleAppIntegTest {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Title extends SimpleObjectIntegTest {
|
||||
|
||||
@Inject
|
||||
|
@@ -74,7 +74,7 @@ public class SimpleApplication extends IsisWicketApplication {
|
||||
* <p>
|
||||
* for demos only, obvious.
|
||||
*/
|
||||
private final static boolean DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS = false;
|
||||
private static final boolean DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS = false;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -116,6 +116,7 @@ public class SimpleApplication extends IsisWicketApplication {
|
||||
servletRequest.getSession().invalidate();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
WebRequest request = super.newWebRequest(servletRequest, filterPath);
|
||||
return request;
|
||||
|
@@ -11,6 +11,9 @@ public class NodeImpl implements Node {
|
||||
private final Node left;
|
||||
private final Node right;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public NodeImpl(String name, Node left, Node right) {
|
||||
this.name = name;
|
||||
this.left = left;
|
||||
|
@@ -5,8 +5,6 @@ import java.util.HashSet;
|
||||
/**
|
||||
*
|
||||
* Generic object pool
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class ObjectPool<T> {
|
||||
|
||||
@@ -15,6 +13,9 @@ public abstract class ObjectPool<T> {
|
||||
|
||||
protected abstract T create();
|
||||
|
||||
/**
|
||||
* Checkout object from pool
|
||||
*/
|
||||
public synchronized T checkOut() {
|
||||
if (available.size() <= 0) {
|
||||
available.add(create());
|
||||
|
@@ -11,6 +11,9 @@ public class Oliphaunt {
|
||||
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Oliphaunt() {
|
||||
id = counter++;
|
||||
try {
|
||||
|
@@ -27,6 +27,9 @@ public class Weather {
|
||||
observers.remove(obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes time pass for weather
|
||||
*/
|
||||
public void timePasses() {
|
||||
WeatherType[] enumValues = WeatherType.values();
|
||||
currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
|
||||
|
@@ -15,6 +15,9 @@ public class GWeather extends Observable<GWeather, Race, WeatherType> {
|
||||
currentWeather = WeatherType.SUNNY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes time pass for weather
|
||||
*/
|
||||
public void timePasses() {
|
||||
WeatherType[] enumValues = WeatherType.values();
|
||||
currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
|
||||
|
@@ -22,6 +22,9 @@ public abstract class Observable<S extends Observable<S, O, A>, O extends Observ
|
||||
this.observers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify observers
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void notifyObservers(A argument) {
|
||||
for (O observer : observers) {
|
||||
|
@@ -3,10 +3,6 @@ package com.iluwatar.observer.generic;
|
||||
/**
|
||||
*
|
||||
* Observer
|
||||
*
|
||||
* @param <S>
|
||||
* @param <O>
|
||||
* @param <A>
|
||||
*/
|
||||
public interface Observer<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A> {
|
||||
|
||||
|
@@ -7,14 +7,17 @@ import com.iluwatar.poison.pill.Message.Headers;
|
||||
*/
|
||||
public class Consumer {
|
||||
|
||||
private final MQSubscribePoint queue;
|
||||
private final MqSubscribePoint queue;
|
||||
private final String name;
|
||||
|
||||
public Consumer(String name, MQSubscribePoint queue) {
|
||||
public Consumer(String name, MqSubscribePoint queue) {
|
||||
this.name = name;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume message
|
||||
*/
|
||||
public void consume() {
|
||||
while (true) {
|
||||
Message msg;
|
||||
|
@@ -3,6 +3,6 @@ package com.iluwatar.poison.pill;
|
||||
/**
|
||||
* Represents abstraction of channel (or pipe) that bounds {@link Producer} and {@link Consumer}
|
||||
*/
|
||||
public interface MessageQueue extends MQPublishPoint, MQSubscribePoint {
|
||||
public interface MessageQueue extends MqPublishPoint, MqSubscribePoint {
|
||||
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package com.iluwatar.poison.pill;
|
||||
/**
|
||||
* Endpoint to publish {@link Message} to queue
|
||||
*/
|
||||
public interface MQPublishPoint {
|
||||
public interface MqPublishPoint {
|
||||
|
||||
public void put(Message msg) throws InterruptedException;
|
||||
}
|
@@ -3,7 +3,7 @@ package com.iluwatar.poison.pill;
|
||||
/**
|
||||
* Endpoint to retrieve {@link Message} from queue
|
||||
*/
|
||||
public interface MQSubscribePoint {
|
||||
public interface MqSubscribePoint {
|
||||
|
||||
public Message take() throws InterruptedException;
|
||||
}
|
@@ -10,16 +10,22 @@ import com.iluwatar.poison.pill.Message.Headers;
|
||||
*/
|
||||
public class Producer {
|
||||
|
||||
private final MQPublishPoint queue;
|
||||
private final MqPublishPoint queue;
|
||||
private final String name;
|
||||
private boolean isStopped;
|
||||
|
||||
public Producer(String name, MQPublishPoint queue) {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Producer(String name, MqPublishPoint queue) {
|
||||
this.name = name;
|
||||
this.queue = queue;
|
||||
this.isStopped = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to queue
|
||||
*/
|
||||
public void send(String body) {
|
||||
if (isStopped) {
|
||||
throw new IllegalStateException(String.format(
|
||||
@@ -38,6 +44,9 @@ public class Producer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop system by sending poison pill
|
||||
*/
|
||||
public void stop() {
|
||||
isStopped = true;
|
||||
try {
|
||||
|
2
pom.xml
2
pom.xml
@@ -244,7 +244,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.15</version>
|
||||
<version>2.17</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate</id>
|
||||
|
@@ -13,6 +13,9 @@ public class ImmutableStew {
|
||||
data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix the stew
|
||||
*/
|
||||
public void mix() {
|
||||
System.out.println(String.format(
|
||||
"Mixing the immutable stew we find: %d potatoes, %d carrots, %d meat and %d peppers",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user