+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.balking; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * In Balking Design Pattern if an object’s method is invoked when it is in an inappropriate state, + * then the method will return without doing anything. Objects that use this pattern are generally only in a + * state that is prone to balking temporarily but for an unknown amount of time + * + * In this example implementation WashingMachine is an object that has two states + * in which it can be: ENABLED and WASHING. If the machine is ENABLED + * the state is changed into WASHING that any other thread can't invoke this action on this and then do the job. + * On the other hand if it have been already washing and any other thread execute wash() + * it can't do that once again and returns doing nothing. + */ + +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** + * @param args the command line arguments - not used + */ + public static void main(String... args) { + final WashingMachine washingMachine = new WashingMachine(); + ExecutorService executorService = Executors.newFixedThreadPool(3); + for (int i = 0; i < 3; i++) { + executorService.execute(washingMachine::wash); + } + executorService.shutdown(); + try { + executorService.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException ie) { + LOGGER.error("ERROR: Waiting on executor service shutdown!"); + } + } + +} diff --git a/balking/src/main/java/com/iluwatar/balking/WashingMachine.java b/balking/src/main/java/com/iluwatar/balking/WashingMachine.java new file mode 100644 index 000000000..e4f1259ad --- /dev/null +++ b/balking/src/main/java/com/iluwatar/balking/WashingMachine.java @@ -0,0 +1,76 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.balking; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Washing machine class + */ +public class WashingMachine { + + private static final Logger LOGGER = LoggerFactory.getLogger(WashingMachine.class); + + private WashingMachineState washingMachineState; + + public WashingMachine() { + washingMachineState = WashingMachineState.ENABLED; + } + + public WashingMachineState getWashingMachineState() { + return washingMachineState; + } + + /** + * Method responsible for washing + * if the object is in appropriate state + */ + public void wash() { + synchronized (this) { + LOGGER.info("{}: Actual machine state: {}", Thread.currentThread().getName(), getWashingMachineState()); + if (washingMachineState == WashingMachineState.WASHING) { + LOGGER.error("ERROR: Cannot wash if the machine has been already washing!"); + return; + } + washingMachineState = WashingMachineState.WASHING; + } + LOGGER.info("{}: Doing the washing", Thread.currentThread().getName()); + try { + Thread.sleep(50); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + endOfWashing(); + } + + /** + * Method responsible of ending the washing + * by changing machine state + */ + public synchronized void endOfWashing() { + washingMachineState = WashingMachineState.ENABLED; + LOGGER.info("{}: Washing completed.", Thread.currentThread().getId()); + } + +} diff --git a/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java b/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java new file mode 100644 index 000000000..40a5b2f38 --- /dev/null +++ b/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java @@ -0,0 +1,32 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.balking; + +/** + * WashingMachineState enum describes in which state machine is, + * it can be enabled and ready to work as well as during washing + */ + +public enum WashingMachineState { + ENABLED, WASHING +} diff --git a/balking/src/test/java/com/iluwatar/balking/AppTest.java b/balking/src/test/java/com/iluwatar/balking/AppTest.java new file mode 100644 index 000000000..df104b901 --- /dev/null +++ b/balking/src/test/java/com/iluwatar/balking/AppTest.java @@ -0,0 +1,39 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.balking; + +import org.junit.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void main() throws Exception { + String[] args = {}; + App.main(args); + } + +} \ No newline at end of file diff --git a/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java b/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java new file mode 100644 index 000000000..ecf81f409 --- /dev/null +++ b/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java @@ -0,0 +1,65 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.balking;
+
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link WashingMachine}
+ */
+public class WashingMachineTest {
+
+ private volatile WashingMachineState machineStateGlobal;
+
+ @Test
+ public void wash() throws Exception {
+ WashingMachine washingMachine = new WashingMachine();
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ executorService.execute(washingMachine::wash);
+ executorService.execute(() -> {
+ washingMachine.wash();
+ machineStateGlobal = washingMachine.getWashingMachineState();
+ });
+ executorService.shutdown();
+ try {
+ executorService.awaitTermination(10, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ assertEquals(WashingMachineState.WASHING, machineStateGlobal);
+ }
+
+ @Test
+ public void endOfWashing() throws Exception {
+ WashingMachine washingMachine = new WashingMachine();
+ washingMachine.wash();
+ assertEquals(WashingMachineState.ENABLED, washingMachine.getWashingMachineState());
+ }
+
+}
\ No newline at end of file
diff --git a/bridge/pom.xml b/bridge/pom.xml
index ec04ff395..7c60f8ef8 100644
--- a/bridge/pom.xml
+++ b/bridge/pom.xml
@@ -29,7 +29,7 @@
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.converter;
+
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The Converter pattern is a behavioral design pattern which allows a common way of bidirectional
+ * conversion between corresponding types (e.g. DTO and domain representations of the logically
+ * isomorphic types). Moreover, the pattern introduces a common way of converting a collection of
+ * objects between types.
+ */
+public class App {
+ /**
+ * Program entry point
+ *
+ * @param args command line args
+ */
+ public static void main(String[] args) {
+ Converter
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.converter;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Generic converter, thanks to Java8 features not only provides a way of generic bidirectional
+ * conversion between coresponding types, but also a common way of converting a collection of objects
+ * of the same type, reducing boilerplate code to the absolute minimum.
+ * @param
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.converter;
+
+import java.util.Objects;
+
+/**
+ * User class
+ */
+public class User {
+ private String firstName;
+ private String lastName;
+ private boolean isActive;
+ private String userId;
+
+ /**
+ * @param firstName user's first name
+ * @param lastName user's last name
+ * @param isActive flag indicating whether the user is active
+ * @param userId user's identificator
+ */
+ public User(String firstName, String lastName, boolean isActive, String userId) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.isActive = isActive;
+ this.userId = userId;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public boolean isActive() {
+ return isActive;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ User user = (User) o;
+ return isActive == user.isActive && Objects.equals(firstName, user.firstName) && Objects
+ .equals(lastName, user.lastName) && Objects.equals(userId, user.userId);
+ }
+
+ @Override public int hashCode() {
+ return Objects.hash(firstName, lastName, isActive, userId);
+ }
+
+ @Override public String toString() {
+ return "User{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\''
+ + ", isActive=" + isActive + ", userId='" + userId + '\'' + '}';
+ }
+}
diff --git a/converter/src/main/java/com/iluwatar/converter/UserConverter.java b/converter/src/main/java/com/iluwatar/converter/UserConverter.java
new file mode 100644
index 000000000..9ef1d03c2
--- /dev/null
+++ b/converter/src/main/java/com/iluwatar/converter/UserConverter.java
@@ -0,0 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.converter;
+
+/**
+ * Example implementation of the simple User converter.
+ */
+public class UserConverter extends Converter
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.converter;
+
+
+import java.util.Objects;
+
+/**
+ * User DTO class
+ */
+public class UserDto {
+
+ private String firstName;
+ private String lastName;
+ private boolean isActive;
+ private String email;
+
+ /**
+ * @param firstName user's first name
+ * @param lastName user's last name
+ * @param isActive flag indicating whether the user is active
+ * @param email user's email address
+ */
+ public UserDto(String firstName, String lastName, boolean isActive, String email) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.isActive = isActive;
+ this.email = email;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public boolean isActive() {
+ return isActive;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ UserDto userDto = (UserDto) o;
+ return isActive == userDto.isActive && Objects.equals(firstName, userDto.firstName) && Objects
+ .equals(lastName, userDto.lastName) && Objects.equals(email, userDto.email);
+ }
+
+ @Override public int hashCode() {
+ return Objects.hash(firstName, lastName, isActive, email);
+ }
+
+ @Override public String toString() {
+ return "UserDto{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\''
+ + ", isActive=" + isActive + ", email='" + email + '\'' + '}';
+ }
+}
diff --git a/converter/src/test/java/com/iluwatar/converter/AppTest.java b/converter/src/test/java/com/iluwatar/converter/AppTest.java
new file mode 100644
index 000000000..091fbe2ca
--- /dev/null
+++ b/converter/src/test/java/com/iluwatar/converter/AppTest.java
@@ -0,0 +1,38 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.converter;
+
+import org.junit.Test;
+
+/**
+ * App running test
+ */
+public class AppTest {
+
+ @Test
+ public void testMain() {
+ String[] args = {};
+ App.main(args);
+ }
+
+}
diff --git a/converter/src/test/java/com/iluwatar/converter/ConverterTest.java b/converter/src/test/java/com/iluwatar/converter/ConverterTest.java
new file mode 100644
index 000000000..9fc2e2a0c
--- /dev/null
+++ b/converter/src/test/java/com/iluwatar/converter/ConverterTest.java
@@ -0,0 +1,84 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.converter;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Tests for {@link Converter}
+ */
+public class ConverterTest {
+
+ private UserConverter userConverter = new UserConverter();
+
+ /**
+ * Tests whether a converter created of opposite functions holds equality as a bijection.
+ */
+ @Test public void testConversionsStartingFromDomain() {
+ User u1 = new User("Tom", "Hanks", true, "tom@hanks.com");
+ User u2 = userConverter.convertFromDto(userConverter.convertFromEntity(u1));
+ assertEquals(u1, u2);
+ }
+
+ /**
+ * Tests whether a converter created of opposite functions holds equality as a bijection.
+ */
+ @Test public void testConversionsStartingFromDto() {
+ UserDto u1 = new UserDto("Tom", "Hanks", true, "tom@hanks.com");
+ UserDto u2 = userConverter.convertFromEntity(userConverter.convertFromDto(u1));
+ assertEquals(u1, u2);
+ }
+
+ /**
+ * Tests the custom users converter. Thanks to Java8 lambdas, converter can be easily and
+ * cleanly instantiated allowing various different conversion strategies to be implemented.
+ */
+ @Test public void testCustomConverter() {
+ Converter
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus;
+
+import com.iluwatar.databus.data.MessageData;
+import com.iluwatar.databus.data.StartingData;
+import com.iluwatar.databus.data.StoppingData;
+import com.iluwatar.databus.members.MessageCollectorMember;
+import com.iluwatar.databus.members.StatusMember;
+
+import java.time.LocalDateTime;
+
+/**
+ * The Data Bus pattern
+ *
+ * {@see http://wiki.c2.com/?DataBusPattern}
+ * The Data-Bus pattern provides a method where different parts of an application may
+ * pass messages between each other without needing to be aware of the other's existence. Similar to the {@code ObserverPattern}, members register themselves with the {@link DataBus}
+ * and may then receive each piece of data that is published to the Data-Bus. The member
+ * may react to any given message or not. It allows for Many-to-Many distribution of data, as there may be any number of
+ * publishers to a Data-Bus, and any number of members receiving the data. All members
+ * will receive the same data, the order each receives a given piece of data, is an
+ * implementation detail. Members may unsubscribe from the Data-Bus to stop receiving data. This example of the pattern implements a Synchronous Data-Bus, meaning that
+ * when data is published to the Data-Bus, the publish method will not return until
+ * all members have received the data and returned. The {@link DataBus} class is a Singleton. Members of the Data-Bus must implement the {@link Member} interface. Data to be published via the Data-Bus must implement the {@link DataType} interface. The {@code data} package contains example {@link DataType} implementations. The {@code members} package contains example {@link Member} implementations. The {@link StatusMember} demonstrates using the DataBus to publish a message
+ * to the Data-Bus when it receives a message.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The Data-Bus implementation.
+ *
+ * This implementation uses a Singleton.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus.data;
+
+import com.iluwatar.databus.AbstractDataType;
+import com.iluwatar.databus.DataType;
+
+/**
+ * An event raised when a string message is sent.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class MessageData extends AbstractDataType {
+
+ private final String message;
+
+ public MessageData(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public static DataType of(final String message) {
+ return new MessageData(message);
+ }
+}
diff --git a/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java b/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java
new file mode 100644
index 000000000..ac7391f1a
--- /dev/null
+++ b/data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java
@@ -0,0 +1,51 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus.data;
+
+import com.iluwatar.databus.AbstractDataType;
+import com.iluwatar.databus.DataType;
+
+import java.time.LocalDateTime;
+
+/**
+ * An event raised when applications starts, containing the start time of the application.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class StartingData extends AbstractDataType {
+
+ private final LocalDateTime when;
+
+ public StartingData(LocalDateTime when) {
+ this.when = when;
+ }
+
+ public LocalDateTime getWhen() {
+ return when;
+ }
+
+ public static DataType of(final LocalDateTime when) {
+ return new StartingData(when);
+ }
+}
diff --git a/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java b/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java
new file mode 100644
index 000000000..976fdc4e9
--- /dev/null
+++ b/data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java
@@ -0,0 +1,51 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus.data;
+
+import com.iluwatar.databus.AbstractDataType;
+import com.iluwatar.databus.DataType;
+
+import java.time.LocalDateTime;
+
+/**
+ * An event raised when applications stops, containing the stop time of the application.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class StoppingData extends AbstractDataType {
+
+ private final LocalDateTime when;
+
+ public StoppingData(LocalDateTime when) {
+ this.when = when;
+ }
+
+ public LocalDateTime getWhen() {
+ return when;
+ }
+
+ public static DataType of(final LocalDateTime when) {
+ return new StoppingData(when);
+ }
+}
diff --git a/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java b/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java
new file mode 100644
index 000000000..a8ee94ad5
--- /dev/null
+++ b/data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java
@@ -0,0 +1,67 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus.members;
+
+import com.iluwatar.databus.DataType;
+import com.iluwatar.databus.Member;
+import com.iluwatar.databus.data.MessageData;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * Receiver of Data-Bus events that collects the messages from each {@link MessageData}.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class MessageCollectorMember implements Member {
+
+ private static final Logger LOGGER = Logger.getLogger(MessageCollectorMember.class.getName());
+
+ private final String name;
+
+ private List
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.databus.members;
+
+import com.iluwatar.databus.DataType;
+import com.iluwatar.databus.Member;
+import com.iluwatar.databus.data.MessageData;
+import com.iluwatar.databus.data.StartingData;
+import com.iluwatar.databus.data.StoppingData;
+
+import java.time.LocalDateTime;
+import java.util.logging.Logger;
+
+/**
+ * Receiver of Data-Bus events.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class StatusMember implements Member {
+
+ private static final Logger LOGGER = Logger.getLogger(StatusMember.class.getName());
+
+ private final int id;
+
+ private LocalDateTime started;
+
+ private LocalDateTime stopped;
+
+ public StatusMember(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public void accept(final DataType data) {
+ if (data instanceof StartingData) {
+ handleEvent((StartingData) data);
+ } else if (data instanceof StoppingData) {
+ handleEvent((StoppingData) data);
+ }
+ }
+
+ private void handleEvent(StartingData data) {
+ started = data.getWhen();
+ LOGGER.info(String.format("Receiver #%d sees application started at %s", id, started));
+ }
+
+ private void handleEvent(StoppingData data) {
+ stopped = data.getWhen();
+ LOGGER.info(String.format("Receiver #%d sees application stopping at %s", id, stopped));
+ LOGGER.info(String.format("Receiver #%d sending goodbye message", id));
+ data.getDataBus().publish(MessageData.of(String.format("Goodbye cruel world from #%d!", id)));
+ }
+
+ public LocalDateTime getStarted() {
+ return started;
+ }
+
+ public LocalDateTime getStopped() {
+ return stopped;
+ }
+}
diff --git a/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java b/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java
new file mode 100644
index 000000000..90c326ebf
--- /dev/null
+++ b/data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java
@@ -0,0 +1,52 @@
+package com.iluwatar.databus;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.BDDMockito.then;
+import static org.mockito.Mockito.never;
+
+/**
+ * Tests for {@link DataBus}.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class DataBusTest {
+
+ @Mock
+ private Member member;
+
+ @Mock
+ private DataType event;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void publishedEventIsReceivedBySubscribedMember() {
+ //given
+ final DataBus dataBus = DataBus.getInstance();
+ dataBus.subscribe(member);
+ //when
+ dataBus.publish(event);
+ //then
+ then(member).should().accept(event);
+ }
+
+ @Test
+ public void publishedEventIsNotReceivedByMemberAfterUnsubscribing() {
+ //given
+ final DataBus dataBus = DataBus.getInstance();
+ dataBus.subscribe(member);
+ dataBus.unsubscribe(member);
+ //when
+ dataBus.publish(event);
+ //then
+ then(member).should(never()).accept(event);
+ }
+
+}
diff --git a/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java b/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java
new file mode 100644
index 000000000..96fc090ee
--- /dev/null
+++ b/data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java
@@ -0,0 +1,40 @@
+package com.iluwatar.databus.members;
+
+import com.iluwatar.databus.data.MessageData;
+import com.iluwatar.databus.data.StartingData;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.time.LocalDateTime;
+
+/**
+ * Tests for {@link MessageCollectorMember}.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class MessageCollectorMemberTest {
+
+ @Test
+ public void collectMessageFromMessageData() {
+ //given
+ final String message = "message";
+ final MessageData messageData = new MessageData(message);
+ final MessageCollectorMember collector = new MessageCollectorMember("collector");
+ //when
+ collector.accept(messageData);
+ //then
+ Assert.assertTrue(collector.getMessages().contains(message));
+ }
+
+ @Test
+ public void collectIgnoresMessageFromOtherDataTypes() {
+ //given
+ final StartingData startingData = new StartingData(LocalDateTime.now());
+ final MessageCollectorMember collector = new MessageCollectorMember("collector");
+ //when
+ collector.accept(startingData);
+ //then
+ Assert.assertEquals(0, collector.getMessages().size());
+ }
+
+}
diff --git a/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java b/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java
new file mode 100644
index 000000000..e5983dcea
--- /dev/null
+++ b/data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java
@@ -0,0 +1,57 @@
+package com.iluwatar.databus.members;
+
+import com.iluwatar.databus.DataBus;
+import com.iluwatar.databus.data.MessageData;
+import com.iluwatar.databus.data.StartingData;
+import com.iluwatar.databus.data.StoppingData;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.time.LocalDateTime;
+import java.time.Month;
+
+/**
+ * Tests for {@link StatusMember}.
+ *
+ * @author Paul Campbell (pcampbell@kemitix.net)
+ */
+public class StatusMemberTest {
+
+ @Test
+ public void statusRecordsTheStartTime() {
+ //given
+ final LocalDateTime startTime = LocalDateTime.of(2017, Month.APRIL, 1, 19, 9);
+ final StartingData startingData = new StartingData(startTime);
+ final StatusMember statusMember = new StatusMember(1);
+ //when
+ statusMember.accept(startingData);
+ //then
+ Assert.assertEquals(startTime, statusMember.getStarted());
+ }
+
+ @Test
+ public void statusRecordsTheStopTime() {
+ //given
+ final LocalDateTime stop = LocalDateTime.of(2017, Month.APRIL, 1, 19, 12);
+ final StoppingData stoppingData = new StoppingData(stop);
+ stoppingData.setDataBus(DataBus.getInstance());
+ final StatusMember statusMember = new StatusMember(1);
+ //when
+ statusMember.accept(stoppingData);
+ //then
+ Assert.assertEquals(stop, statusMember.getStopped());
+ }
+
+ @Test
+ public void statusIgnoresMessageData() {
+ //given
+ final MessageData messageData = new MessageData("message");
+ final StatusMember statusMember = new StatusMember(1);
+ //when
+ statusMember.accept(messageData);
+ //then
+ Assert.assertNull(statusMember.getStarted());
+ Assert.assertNull(statusMember.getStopped());
+ }
+
+}
diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml
index c23868a4e..878f02fed 100644
--- a/data-mapper/pom.xml
+++ b/data-mapper/pom.xml
@@ -28,7 +28,7 @@
Prototype
* @author Jeroen Meulemeester
*/
@RunWith(Parameterized.class)
diff --git a/proxy/pom.xml b/proxy/pom.xml
index f12db724c..293f3098d 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -29,7 +29,7 @@
+ * This App shows how to create an isolated space per each thread. In this
+ * example the usage of SimpleDateFormat is made to be thread-safe. This is an
+ * example of the ThreadLocal pattern.
+ *
+ * By applying the ThreadLocal pattern you can keep track of application
+ * instances or locale settings throughout the handling of a request. The
+ * ThreadLocal class works like a static variable, with the exception that it is
+ * only bound to the current thread! This allows us to use static variables in a
+ * thread-safe way.
+ *
+ * In Java, thread-local variables are implemented by the ThreadLocal class
+ * object. ThreadLocal holds a variable of type T, which is accessible via get/set
+ * methods.
+ *
+ * SimpleDateFormat is one of the basic Java classes and is not thread-safe. If
+ * you do not isolate the instance of SimpleDateFormat per each thread then
+ * problems arise.
+ *
+ * App converts the String date value 15/12/2015 to the Date format using the
+ * Java class SimpleDateFormat. It does this 20 times using 4 threads, each doing
+ * it 5 times. With the usage of as ThreadLocal in DateFormatCallable everything
+ * runs well. But if you comment out the ThreadLocal variant (marked with "//TLTL")
+ * and comment in the non ThreadLocal variant (marked with "//NTLNTL") you can
+ * see what will happen without the ThreadLocal. Most likely you will get incorrect
+ * date values and / or exceptions.
+ *
+ * This example clearly show what will happen when using non thread-safe classes
+ * in a thread. In real life this may happen one in of 1.000 or 10.000 conversions
+ * and those are really hard to find errors.
+ *
+ * @author Thomas Bauer, 2017
+ */
+public class App {
+ /**
+ * Program entry point
+ *
+ * @param args
+ * command line args
+ */
+ public static void main(String[] args) {
+ int counterDateValues = 0;
+ int counterExceptions = 0;
+
+ // Create a callable
+ DateFormatCallable callableDf = new DateFormatCallable("dd/MM/yyyy", "15/12/2015");
+ // start 4 threads, each using the same Callable instance
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ Future
+ * After a successful run 5 date values should be in the result object. All dates should have
+ * the same value (15.11.2015). To avoid problems with time zone not the date instances themselves
+ * are compared by the test. For the test the dates are converted into string format DD.MM.YYY
+ *
+ * Additionally the number of list entries are tested for both the list with the date values
+ * and the list with the exceptions
+ *
+ * @author Thomas Bauer, January 2017
+ *
+ */
+public class DateFormatCallableTest {
+
+ // Class variables used in setup() have to be static because setup() has to be static
+ /**
+ * Result object given back by DateFormatCallable
+ * -- Array with converted date values
+ * -- Array with thrown exceptions
+ */
+ static Result result;
+
+ /**
+ * The date values created by the run of of DateFormatRunnalbe. List will be filled in the setup() method
+ */
+ static List
+ * An incorrect formatted date is passed to the Callable
+ * After a successful run 0 date values and 5 exceptions should be in the result object.
+ *
+ * @author Thomas Bauer, January 2017
+ *
+ */
+public class DateFormatCallableTestIncorrectDateFormat {
+
+ // Class variables used in setup() have to be static because setup() has to be static
+ /**
+ * Result object given back by DateFormatCallable
+ * -- Array with converted date values
+ * -- Array with thrown exceptions
+ */
+ static Result result;
+
+ /**
+ * The date values created by the run of DateFormatRunnalbe. List will be filled in the setup() method
+ */
+ static List
+ * After a successful run 5 date values should be in the result object of each thread. All dates
+ * should have the same value (15.11.2015). To avoid problems with time zone not the date instances
+ * themselves are compared by the test. For the test the dates are converted into string format DD.MM.YYY
+ *
+ * Additionally the number of list entries are tested for both the list with the date values
+ * and the list with the exceptions
+ *
+ * @author Thomas Bauer, January 2017
+ *
+ */
+public class DateFormatCallableTestMultiThread {
+
+ // Class variables used in setup() have to be static because setup() has to be static
+ /**
+ * Result object given back by DateFormatCallable, one for each thread
+ * -- Array with converted date values
+ * -- Array with thrown exceptions
+ */
+ static Result[] result = new Result[4];
+
+ /**
+ * The date values created by the run of of DateFormatRunnalbe. List will be filled in the setup() method
+ */
+ @SuppressWarnings("serial")
+ static class StringArrayList extends ArrayList Observable
+ * @param , O extends Observer, A> {
diff --git a/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java
index 7120a31e0..70a7922c5 100644
--- a/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java
+++ b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java
@@ -22,18 +22,18 @@
*/
package com.iluwatar.observer;
+import static org.junit.Assert.assertEquals;
+
import com.iluwatar.observer.utils.InMemoryAppender;
+import java.util.function.Supplier;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import java.util.function.Supplier;
-
-import static org.junit.Assert.assertEquals;
-
/**
* Date: 12/27/15 - 11:44 AM
- *
+ * Weather Observer Tests
+ * @param Supplier method generating singletons
* @author Jeroen Meulemeester
* @author Richard Jones
*/
diff --git a/specification/pom.xml b/specification/pom.xml
index 40584b7ca..33cc0f1e5 100644
--- a/specification/pom.xml
+++ b/specification/pom.xml
@@ -29,7 +29,7 @@