From 9d4fff6029a67efeeb1aeaad980fc2c5f8a9fcef Mon Sep 17 00:00:00 2001 From: hoswey Date: Fri, 27 Nov 2015 11:22:33 +0800 Subject: [PATCH 001/112] Fix #216 Repository vs DAO --- pom.xml | 12 ++ repository/etc/repository.png | Bin 9683 -> 55254 bytes repository/etc/repository.ucls | 40 ++++++- repository/index.md | 6 + repository/pom.xml | 73 ++++++------ .../java/com/iluwatar/repository/App.java | 34 ++++-- .../java/com/iluwatar/repository/Person.java | 58 +++++++++- .../iluwatar/repository/PersonRepository.java | 8 +- .../repository/PersonSpecifications.java | 50 ++++++++ .../src/main/resources/applicationContext.xml | 6 +- .../java/com/iluwatar/repository/AppTest.java | 19 --- .../iluwatar/repository/RepositoryTest.java | 109 ++++++++++++++++++ 12 files changed, 343 insertions(+), 72 deletions(-) create mode 100644 repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java delete mode 100644 repository/src/test/java/com/iluwatar/repository/AppTest.java create mode 100644 repository/src/test/java/com/iluwatar/repository/RepositoryTest.java diff --git a/pom.xml b/pom.xml index bcdf9affe..e6603b06c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ UTF-8 5.0.1.Final + 4.1.7.RELEASE 1.9.0.RELEASE 1.4.188 4.12 @@ -20,6 +21,7 @@ 1.4 2.15.3 1.2.17 + 18.0 abstract-factory @@ -101,6 +103,11 @@ ${hibernate.version} + org.springframework + spring-test + ${spring.version} + + org.springframework.data spring-data-jpa ${spring-data.version} @@ -142,6 +149,11 @@ log4j ${log4j.version} + + com.google.guava + guava + ${guava.version} + diff --git a/repository/etc/repository.png b/repository/etc/repository.png index 1e031f3ae327d8dd20c46ea0b0fa69a0333efc27..08d5d571d0a82607a3c714686c6f58e0999f81b1 100644 GIT binary patch literal 55254 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%0Db#Ymqoa9Uf5(TB(u>Gdf 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 literal 9683 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 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repository/index.md b/repository/index.md index a65044d29..8ecd16528 100644 --- a/repository/index.md +++ b/repository/index.md @@ -25,3 +25,9 @@ querying is utilized. **Real world examples:** * [Spring Data](http://projects.spring.io/spring-data/) + +**Credits:** + +* [Don’t use DAO, use Repository](http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/) +* [Advanced Spring Data JPA - Specifications and Querydsl](https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/) + diff --git a/repository/pom.xml b/repository/pom.xml index 60b51568e..c3adc7a92 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -1,35 +1,42 @@ - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.8.0-SNAPSHOT - - repository - - - org.springframework.data - spring-data-jpa - - - org.hibernate - hibernate-entitymanager - - - commons-dbcp - commons-dbcp - - - com.h2database - h2 - - - junit - junit - test - - + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.8.0-SNAPSHOT + + repository + + + org.springframework + spring-test + + + org.springframework.data + spring-data-jpa + + + org.hibernate + hibernate-entitymanager + + + commons-dbcp + commons-dbcp + + + com.h2database + h2 + + + junit + junit + test + + + com.google.guava + guava + + diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java index fb9680cb6..2442c854c 100644 --- a/repository/src/main/java/com/iluwatar/repository/App.java +++ b/repository/src/main/java/com/iluwatar/repository/App.java @@ -5,7 +5,6 @@ import java.util.List; import org.springframework.context.support.ClassPathXmlApplicationContext; /** - * * Repository pattern mediates between the domain and data mapping layers using a collection-like * interface for accessing domain objects. A system with complex domain model often benefits from a * layer that isolates domain objects from the details of the database access code and in such @@ -16,9 +15,9 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; *

* In this example we utilize Spring Data to automatically generate a repository for us from the * {@link Person} domain object. Using the {@link PersonRepository} we perform CRUD operations on - * the entity. Underneath we have configured in-memory H2 database for which schema is created and - * dropped on each run. - * + * the entity, moreover, the query by {@link org.springframework.data.jpa.domain.Specification} are + * also performed. Underneath we have configured in-memory H2 database for which schema is created + * and dropped on each run. */ public class App { @@ -28,16 +27,21 @@ public class App { * @param args command line args */ public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); PersonRepository repository = context.getBean(PersonRepository.class); - Person peter = new Person("Peter", "Sagan"); - Person nasta = new Person("Nasta", "Kuzminova"); + Person peter = new Person("Peter", "Sagan", 17); + Person nasta = new Person("Nasta", "Kuzminova", 25); + Person john = new Person("John", "lawrence", 35); + Person terry = new Person("Terry", "Law", 36); // Add new Person records repository.save(peter); repository.save(nasta); + repository.save(john); + repository.save(terry); // Count Person records System.out.println("Count Person records: " + repository.count()); @@ -48,9 +52,6 @@ public class App { System.out.println(person); } - // Find Person by surname - System.out.println("Find by surname 'Sagan': " + repository.findBySurname("Sagan")); - // Update Person nasta.setName("Barbora"); nasta.setSurname("Spotakova"); @@ -61,9 +62,22 @@ public class App { // Remove record from Person repository.delete(2L); - // And finally count records + // count records System.out.println("Count Person records: " + repository.count()); + // find by name + Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); + System.out.println("Find by John is " + p); + + // find by age + persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); + + System.out.println("Find Person with age between 20,40: "); + for (Person person : persons) { + System.out.println(person); + } + context.close(); + } } diff --git a/repository/src/main/java/com/iluwatar/repository/Person.java b/repository/src/main/java/com/iluwatar/repository/Person.java index 97d5e7120..57439b8c0 100644 --- a/repository/src/main/java/com/iluwatar/repository/Person.java +++ b/repository/src/main/java/com/iluwatar/repository/Person.java @@ -18,11 +18,14 @@ public class Person { private String name; private String surname; + private int age; + public Person() {} - public Person(String name, String surname) { + public Person(String name, String surname, int age) { this.name = name; this.surname = surname; + this.age = age; } public Long getId() { @@ -49,8 +52,59 @@ public class Person { this.surname = surname; } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + @Override public String toString() { - return "Person [id=" + id + ", name=" + name + ", surname=" + surname + "]"; + return "Person [id=" + id + ", name=" + name + ", surname=" + surname + ", age=" + age + "]"; } + + @Override + public int hashCode() { + + final int prime = 31; + int result = 1; + result = prime * result + age; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((surname == null) ? 0 : surname.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + if (age != other.age) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (surname == null) { + if (other.surname != null) + return false; + } else if (!surname.equals(other.surname)) + return false; + return true; + } + } diff --git a/repository/src/main/java/com/iluwatar/repository/PersonRepository.java b/repository/src/main/java/com/iluwatar/repository/PersonRepository.java index 167b40d19..98bb7abce 100644 --- a/repository/src/main/java/com/iluwatar/repository/PersonRepository.java +++ b/repository/src/main/java/com/iluwatar/repository/PersonRepository.java @@ -1,7 +1,6 @@ package com.iluwatar.repository; -import java.util.List; - +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @@ -11,7 +10,8 @@ import org.springframework.stereotype.Repository; * */ @Repository -public interface PersonRepository extends CrudRepository { +public interface PersonRepository + extends CrudRepository, JpaSpecificationExecutor { - public List findBySurname(String surname); + public Person findByName(String name); } diff --git a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java new file mode 100644 index 000000000..dadaae36b --- /dev/null +++ b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java @@ -0,0 +1,50 @@ +package com.iluwatar.repository; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.springframework.data.jpa.domain.Specification; + +/** + * Helper class, includes vary Specification as the abstraction of sql query criteria + */ +public class PersonSpecifications { + + public static class AgeBetweenSpec implements Specification { + + private int from; + + private int to; + + public AgeBetweenSpec(int from, int to) { + this.from = from; + this.to = to; + } + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + + return cb.between(root.get("age"), from, to); + + } + + } + public static class NameEqualSpec implements Specification { + + public String name; + + public NameEqualSpec(String name) { + this.name = name; + } + + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + + return cb.equal(root.get("name"), this.name); + + } + } + +} + diff --git a/repository/src/main/resources/applicationContext.xml b/repository/src/main/resources/applicationContext.xml index 3fe15b2f6..9322c9f64 100644 --- a/repository/src/main/resources/applicationContext.xml +++ b/repository/src/main/resources/applicationContext.xml @@ -6,10 +6,10 @@ 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/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> + + diff --git a/repository/src/test/java/com/iluwatar/repository/AppTest.java b/repository/src/test/java/com/iluwatar/repository/AppTest.java deleted file mode 100644 index 929f61941..000000000 --- a/repository/src/test/java/com/iluwatar/repository/AppTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.iluwatar.repository; - -import org.junit.Test; - -import com.iluwatar.repository.App; - -/** - * - * Application test - * - */ -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} diff --git a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java new file mode 100644 index 000000000..26689321a --- /dev/null +++ b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java @@ -0,0 +1,109 @@ +package com.iluwatar.repository; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import javax.annotation.Resource; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.common.collect.Lists; + +/** + * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query + * by {@link org.springframework.data.jpa.domain.Specification} are also test. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) +public class RepositoryTest { + + @Resource + private PersonRepository repository; + + Person peter = new Person("Peter", "Sagan", 17); + Person nasta = new Person("Nasta", "Kuzminova", 25); + Person john = new Person("John", "lawrence", 35); + Person terry = new Person("Terry", "Law", 36); + + List persons = Arrays.asList(peter, nasta, john, terry); + + /** + * Prepare data for test + */ + @Before + public void setup() { + + repository.save(persons); + } + + @Test + public void testFindAll() { + + List actuals = Lists.newArrayList(repository.findAll()); + assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals)); + } + + @Test + public void testSave() { + + Person terry = repository.findByName("Terry"); + terry.setSurname("Lee"); + terry.setAge(47); + repository.save(terry); + + terry = repository.findByName("Terry"); + assertEquals(terry.getSurname(), "Lee"); + assertEquals(47, terry.getAge()); + } + + @Test + public void testDelete() { + + Person terry = repository.findByName("Terry"); + repository.delete(terry); + + assertEquals(3, repository.count()); + assertNull(repository.findByName("Terry")); + } + + @Test + public void testCount() { + + assertEquals(4, repository.count()); + } + + @Test + public void testFindAllByAgeBetweenSpec() { + + List persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); + + assertEquals(3, persons.size()); + assertTrue(persons.stream().allMatch((item) -> { + return item.getAge() > 20 && item.getAge() < 40; + })); + } + + @Test + public void testFindOneByNameEqualSpec() { + + Person actual = repository.findOne(new PersonSpecifications.NameEqualSpec("Terry")); + assertEquals(terry, actual); + } + + @After + public void cleanup() { + + repository.deleteAll(); + } + +} + From 9a85dfe9dfe08654f56048b4328a3938bddad8e1 Mon Sep 17 00:00:00 2001 From: neonds Date: Fri, 27 Nov 2015 21:23:55 -0600 Subject: [PATCH 002/112] Annotation Config was added. Now AppConfig contains a Main Method (same logic in App.java) to execute --- .../com/iluwatar/repository/AppConfig.java | 131 ++++++++++++++++++ .../AnnotationBasedRepositoryTest.java | 110 +++++++++++++++ .../iluwatar/repository/AppConfigTest.java | 54 ++++++++ 3 files changed, 295 insertions(+) create mode 100644 repository/src/main/java/com/iluwatar/repository/AppConfig.java create mode 100644 repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java create mode 100644 repository/src/test/java/com/iluwatar/repository/AppConfigTest.java diff --git a/repository/src/main/java/com/iluwatar/repository/AppConfig.java b/repository/src/main/java/com/iluwatar/repository/AppConfig.java new file mode 100644 index 000000000..eceb13637 --- /dev/null +++ b/repository/src/main/java/com/iluwatar/repository/AppConfig.java @@ -0,0 +1,131 @@ +package com.iluwatar.repository; + +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.commons.dbcp.BasicDataSource; +import org.hibernate.jpa.HibernatePersistenceProvider; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +/** + * Annotations based configuration for Spring + * + */ +@EnableJpaRepositories +public class AppConfig { + + /** + * Creation of H2 db + * + * @return A new Instance of DataSource + */ + @Bean(destroyMethod = "close") + public DataSource dataSource() { + BasicDataSource basicDataSource = new BasicDataSource(); + basicDataSource.setDriverClassName("org.h2.Driver"); + basicDataSource.setUrl("jdbc:h2:~/databases/person"); + basicDataSource.setUsername("sa"); + basicDataSource.setPassword("sa"); + return (DataSource) basicDataSource; + } + + /** + * Factory to create a especific instance of Entity Manager + * @return + */ + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); + entityManager.setDataSource(dataSource()); + entityManager.setPackagesToScan("com.iluwatar"); + entityManager.setPersistenceProvider(new HibernatePersistenceProvider()); + entityManager.setJpaProperties(jpaProperties()); + + return entityManager; + } + + /** + * Properties for Jpa + * @return + */ + private Properties jpaProperties() { + Properties properties = new Properties(); + properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); + return properties; + } + + @Bean + public JpaTransactionManager transactionManager() throws SQLException { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + /** + * Program entry point + * + * @param args command line args + */ + public static void main(String[] args) { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); + PersonRepository repository = context.getBean(PersonRepository.class); + + Person peter = new Person("Peter", "Sagan", 17); + Person nasta = new Person("Nasta", "Kuzminova", 25); + Person john = new Person("John", "lawrence", 35); + Person terry = new Person("Terry", "Law", 36); + + // Add new Person records + repository.save(peter); + repository.save(nasta); + repository.save(john); + repository.save(terry); + + // Count Person records + System.out.println("Count Person records: " + repository.count()); + + // Print all records + List persons = (List) repository.findAll(); + for (Person person : persons) { + System.out.println(person); + } + + // Update Person + nasta.setName("Barbora"); + nasta.setSurname("Spotakova"); + repository.save(nasta); + + System.out.println("Find by id 2: " + repository.findOne(2L)); + + // Remove record from Person + repository.delete(2L); + + // count records + System.out.println("Count Person records: " + repository.count()); + + // find by name + Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); + System.out.println("Find by John is " + p); + + // find by age + persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); + + System.out.println("Find Person with age between 20,40: "); + for (Person person : persons) { + System.out.println(person); + } + + context.close(); + + } + +} diff --git a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java new file mode 100644 index 000000000..5e4cf8021 --- /dev/null +++ b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java @@ -0,0 +1,110 @@ +package com.iluwatar.repository; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import javax.annotation.Resource; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.google.common.collect.Lists; + +/** + * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query + * by {@link org.springframework.data.jpa.domain.Specification} are also test. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { AppConfig.class}, loader = AnnotationConfigContextLoader.class) +public class AnnotationBasedRepositoryTest { + + @Resource + private PersonRepository repository; + + Person peter = new Person("Peter", "Sagan", 17); + Person nasta = new Person("Nasta", "Kuzminova", 25); + Person john = new Person("John", "lawrence", 35); + Person terry = new Person("Terry", "Law", 36); + + List persons = Arrays.asList(peter, nasta, john, terry); + + /** + * Prepare data for test + */ + @Before + public void setup() { + + repository.save(persons); + } + + @Test + public void testFindAll() { + + List actuals = Lists.newArrayList(repository.findAll()); + assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals)); + } + + @Test + public void testSave() { + + Person terry = repository.findByName("Terry"); + terry.setSurname("Lee"); + terry.setAge(47); + repository.save(terry); + + terry = repository.findByName("Terry"); + assertEquals(terry.getSurname(), "Lee"); + assertEquals(47, terry.getAge()); + } + + @Test + public void testDelete() { + + Person terry = repository.findByName("Terry"); + repository.delete(terry); + + assertEquals(3, repository.count()); + assertNull(repository.findByName("Terry")); + } + + @Test + public void testCount() { + + assertEquals(4, repository.count()); + } + + @Test + public void testFindAllByAgeBetweenSpec() { + + List persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); + + assertEquals(3, persons.size()); + assertTrue(persons.stream().allMatch((item) -> { + return item.getAge() > 20 && item.getAge() < 40; + })); + } + + @Test + public void testFindOneByNameEqualSpec() { + + Person actual = repository.findOne(new PersonSpecifications.NameEqualSpec("Terry")); + assertEquals(terry, actual); + } + + @After + public void cleanup() { + + repository.deleteAll(); + } + +} + diff --git a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java new file mode 100644 index 000000000..5f74f2be7 --- /dev/null +++ b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java @@ -0,0 +1,54 @@ +package com.iluwatar.repository; + +import static org.junit.Assert.*; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.annotation.Transactional; + +/** + * This case is Just for test the Annotation Based configuration + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { AppConfig.class}, loader = AnnotationConfigContextLoader.class) +public class AppConfigTest { + + @Autowired + DataSource dataSource; + + /** + * Test for bean instance + */ + @Test + public void testDataSource() { + assertNotNull(dataSource); + } + + /** + * Test for correct query execution + * @throws SQLException + */ + @Test + @Transactional + public void testQuery() throws SQLException{ + ResultSet resultSet = dataSource.getConnection().createStatement().executeQuery("SELECT 1"); + String result = null; + String expected = "1"; + while (resultSet.next()) { + result = resultSet.getString(1); + + } + assertTrue(result.equals(expected)); + } + +} From 119d2647798dd78efc52ed7f4f388ed445d2115b Mon Sep 17 00:00:00 2001 From: JuhoKang Date: Tue, 1 Dec 2015 16:00:31 +0900 Subject: [PATCH 003/112] issue #292 --- adapter/etc/adapter.png | Bin 11970 -> 12086 bytes adapter/etc/adapter.ucls | 78 ++++++------- adapter/etc/adapter_1.png | Bin 29974 -> 0 bytes adapter/index.md | 2 +- .../main/java/com/iluwatar/adapter/App.java | 53 +++++---- .../java/com/iluwatar/adapter/Engineer.java | 11 -- .../com/iluwatar/adapter/GnomeEngineer.java | 23 ---- .../adapter/GnomeEngineeringManager.java | 26 ----- .../com/iluwatar/adapter/GoblinGlider.java | 21 ---- .../iluwatar/adapter/AdapterPatternTest.java | 107 +++++++++++------- 10 files changed, 139 insertions(+), 182 deletions(-) delete mode 100644 adapter/etc/adapter_1.png delete mode 100644 adapter/src/main/java/com/iluwatar/adapter/Engineer.java delete mode 100644 adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java delete mode 100644 adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java delete mode 100644 adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java diff --git a/adapter/etc/adapter.png b/adapter/etc/adapter.png index 511bb5880ee7a3dff0ce29bed65b15cb484f310a..f43358b042e73edcbcb9589e540a8d306fa1d6c1 100644 GIT binary patch literal 12086 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 literal 11970 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 P(@{PE72lUh82J4!|7lHV diff --git a/adapter/etc/adapter.ucls b/adapter/etc/adapter.ucls index 8c09f0399..290ff544e 100644 --- a/adapter/etc/adapter.ucls +++ b/adapter/etc/adapter.ucls @@ -1,61 +1,61 @@ - - - + + + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + - + + + + + - - + + diff --git a/adapter/etc/adapter_1.png b/adapter/etc/adapter_1.png deleted file mode 100644 index 64eb34b84f799f7834e2517bf2e60decbef3ae8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29974 zcmb@uWn5R$wk}LJ(%oGmAtBuoA}t^wjeNeD~LZL-MLO#MmfuAUy zIfo%3xlOAo%ISH&UrWX`A?cuKyR$2)EypDydlgHh-XoBvsYWjt3LQcK=!SmDz~vv-a>5O7#s*DJh}@k(l)v@4 zBE`V4UC4%5AY-_=tTs_?dJZF2hKQD4uoEXYR$vZ3X?*NmZ*N+61}!~8wE3%zr11m{ z8gdGoIk`A>ez#4lJzs<<-E(y%Ddf@(U0zNJI?c?Kz10;uY=f$VE=TyX{<=07=U3<5 z)z4iCK{gM#@9CM`TX%Rg@$qA;tT+!(!%S_{@TaEN%-ja~YiKL;Y^3j=BPM(>AC>d; zlyYN3CQq9sE&#Pk+KZTpr6fEjIM`Fz@sUyG_5rW)TatMy8Na#nvo4j6_VzpU^jC6Q zn%|8Kavz+Zsj{!^{kG!JIHVvV>!9A=j=dT6>&qA8O2_H9wY4O7UF#j3XS%y7O|gU& zKU?-FYReG@pKQwNnWLo&+So=>f0x6fm%PEqqN}4fNBClUv>;5Lx*1iU##!iwr`&8U zooWY@g7>3Ik%Tfzt87iDe1ig!FHSFV3P%c^W(Rwd^K^AA|IFYQ7~MIUZwiVP%cQ^I zJM|TL(`8Pn;Z|JC)m_sQ@{z{kwr`mgkwYR?m_@&D#PiGD-= z<->>M7^2kpc&$96_~Bv75z7|=#D;g1I>^aJsIM@XVm~A$+q2iuV5YRcVznth_oF^i z+}XTxO`VhsP3{IRfg<|aSdnnD_}$S0GoQuQq@*NlLBYuI&e4JnQ_~MUJ+~iz9}H^j zdHbCMot9QSEbOG7(8+05PVZ1c(q6!_?yOwdxQh9;g$twa#*Fl1ZHv70w7JI9qx{g& z?{4lqnkkZKdWwRW5dk}!#B(9_&o?tvNOF@9mg7w87micpx`N_;;OJzY=5u~3GSXdN zUzwgB$++{QD`)#h8Jvo|eDzzQPne$>xlfNW?S{OUu4=tbSMYgBX+c6>Zm4(YiUqSU zt7X0OSx-Pf;8{n2yF#)!Mq$5&Vn`VVCsG%qGpZgkIVUo5N~{>gwMUp>LE)o)Z~tLK zaXExlk6B*4n2t?iB%A(Lc6@rIuGN2fGfJJ&e|_T9*~t@jp66g(vFiMsR@T;7jnOeg zd><&S-ih`J3g@}+EMF5`5OsX?&G$rdD;~!lzo7xwd;d{fsz1G;gM&XBc1$;NMZ*zu zPtpAh@R~;7Lk@01JaT0Is<1mD`HnU&?j!F++lMTfWI~AZw++Z(eyRYr zt>}=JgEfozr8W&GccUocm%|tl5u5l3CoM~Vp5gNI{&ru((8(ib`#Q^KXW|qp3Rm0< zE{8*+=HQkdppm`Rx{>mWN+5wU)A(dJ=&4=y)1z3loA+og1B3KiHtsaqyf#(S-SLcSqNd4s+R{S}*t*GB1M3zCLV%$I?J z3)zRq8fak(^3|uO>~euIVVbELO+%mWl$Dismf4Tyu2saVQ@J!*QH5RZnj|$Vcb@NY znW6Qf|M8^SkEz95`ldBkDbCR_o{!AbOkOM5SoqyPQT6JOD~dWvFV~PsO6t#e$p=P) zwj;Jn_N7ymRXWGD52Acu1&97Jm60o!SsGD=SwNLk?olIs&r)ZN%1K zFOMy{IbxwLD-R4$;sfP{%*`YF#X4S-!4jEsTA_i*k&}EU)k)jEy&g8K&Mv>$@@bcJ z7ISlhVT;Xg@9fzZzxc0RjK3us*R$+KRqZ}pjkSTfL4W;P&GF%V_oDtx?%K}aLvAsd2Yw6x;AERl~(Q671IcgWCinC!Xl8Jiat!ZaH`$Yr1`)0Oo; zOpofBuyAA|A-~CM?B^mZDerBV<};af#rZW?rPt0?XZO|ql!ferjae!||1)>N546Je zzj{)n2FJz-2YK|>2`R`r{xQiOVzLaL5mS+u#y1J3m!*aJ>FAm8#TFt^MvAk;*#m0uaCmQo%_!d=HSj~+-ShSR9{N>4FJi$!G)-5zKGmxIwB{ig&>Hcu0Q6Ug`wRY~bE6!F-EthPlFD(0KM6e*X{{1#mDuUsao-riH8 z_}6pl$S-{xI|3*2$8t(nry6Hg&QxtpmH$QWuo*65oL`F1GGbHx{Z0=9qR8@aztnD zU6$r2Ms80w{FlNRR4+Ca;vV$949w|H6rfFMZF6#QJt^lIjiRwY#c+$^<%T?}sAs;n zxb{f&Nq$$l0?#7{|J}W0Eat7_Jpqb@8Q&8RTCu^A?ruX9JyrrauN(%1InOi6YKuK? z^#3(%5$$=r+uohTV!oPsz3r}^Cu;n!?_ZXGum$8q(-M*u%f>Kq7q(N%_%T|WR*}mq zhJ@=TT;tu|>8r3G#kOguKWK@j}7kHL=t!Gf*xsT zEQAqcx3laKU7jXWgA4-Pnp^4wtqp%k>`4?johXZ5TPx90H8myPle>JVq266P=Jc3H z#G@%qZuDGhX=V6;^Nxh9*vp}93P7> zkcmr7I?PJH`nTb1d5dqB<7)&2W;`dMmh9NDIddbxQ$ ziGqdXmHrn<_V;yk%okffE|B#m3Oqf3YVd1O8WG+apYdc^7JIL*q7Hpj?&T^S-^9{n z(yi`}q|lz2AS<|sTj~0M&rrSlID(8P^JD8XztvUSl@sR7$Y zj*30?EC9qh+~$jjPQl0qiY-!>UZY3`vy@J=aWj4#HB1BUUudi&61Mh|SLgcgN@m~T ziFE({F(y^>3Z2mwB*uygWpG=?i_?!ftR%VKd!ILElFc954t?BeiIn@dfzfjx^z-dc zN|m>s9Mc-(VS5^7$_{ zd1J{>g8rwMICU5!TM2zB`2C({;5kx{^53Absi1c*$7bai!^=1{v{+nBJj_4x#o@Q= zWqyMfvUbh<@6}LSIyy2};f-Sv6F+`T1Gvt9bYygN)NcCQR?oXCl>nv4n=8vHJa%PD zcn`m5$#o4Dr+=`jpcekD@F8p5JNA1(bMvz|ygdl-OUKGq3Xz*HsFTGrtvOD8fzo|5 zTB{h&Y-{VCVu%EJfw5?w-`PZTZ=Vc-bfi-Qvu0UthCDZ#ad9)9qLN-j9>-m}OI#}s zUd${ZLwdwPMLq%n0TU(1w_o~W;L_|!gJh;WASew5*wi@b;uL~>M z+x}smL8Yam_mznCy@XAt){W7L3E1O0116XUBMljk{*5PpHt?&=k&$sJJfU)wIK=A; zy#Ap4>$i!6Khraf8Q1i#RZTR788qs$uqepXsX}^>Vdq{j*7R64$NtRkcUpgTk`QAV z6Z1tK0nRt%9UiZI%)RvZz{$;??m~9^MrlBks!|7Z9Y1Obo_`2r_P8( zzVELi!u^w{D|gS z_CVLJcplsjV(Oa~bAN`iQSJ1evb1O2YJ0<1fXdO?JJSCa;s+gZSafvj z$r2Q`ojH=P~UBUq(em&5(e#AAf; z3Y=FL+dLENB60lf4h~Z9+l?27=jeUW4|yH-+`r`h9urd~(Nfke3G;DeK_neHa@p=t zvyKiqMx)HcwTGgP@5jFw7{^vxwV{k>=ve<&?dOk1hELVN|UF$+mgKjkWV{ImPa${Z< zl%1fq{Ckl$m!EV#?oXFeeo=^xYkZaaRHwH$pH6J|*Y^tqj=m+(8h}r8pWk79d@%~q z?78=qnR|Qfl+##mBtLng?xMn%$)ZEh*?bfV^$5B%B}*E)MwPq|AJ!Kak+BJ5!?9+$ z?{H^jKAnt2e{I$8z4c5# z?`m#tw|PzR(<9I5;O_2VOC=?+;NPPP?}WdY)mD?|gnzQ*b@39Qyh_SQGJ@<9fn(^r ziIUSWHrC(N6!6-bjBG2910VlO%=?O0*z-)V#?DrK(rzFNSr$4wmQGBbV3qGEaXF1B?Gqa)jd%V9@c_}8yd ztTp}@g8jU98O#?Waf~w7UyDwYCi$+H$(xe-YAu z095}CzrC5@8>7apUU_)_nh0&c(D|!&Fx#y+{T|3*Uy*4!oPqiIjz&h*4t&s^ynzW- zP_A*sH7Tj&atdf$zQ62qplMTcaz_x-(w?rQ`Va1-z?-g!H-mzjVpx=IeF7l8h-vAO zG6@Q9kK`Gb*2qFb-sdF zA)%rj4Br^Xp;_)Ut1*cSKj{s~$iNbHoGL6Y|G170HoAfscXxM}*SNg@pEJ5_v_e%T zx7_nic@q5}uQ7hjg4h|(%E^sW?EZV?6@$#*B^al{?m}l4@d6483cZY<`sJq_;Zy(i zj?3xcmc)}ke?Ri??^xobU(TcgWmqtK~f{2WNjbLZ4AqX~c;Bw0qU@})6 zKf(8P&`8NzpyxYQ<0Jat=cU%t{G7zD>KPabd_)cX@&)EA5o({tN*?rOYo`9S4YL2* zDjn{T+`Fz9=e~bui%uG^6JY!q&MG`8Lx-D~n3!JDQ}*(x@}Fg72nk-lZjf)HdijI5 zX*sVcWn^TQ1s8JURVF4UC!3mrQp{ivcjdIX1Q@wJJUm!?9({_9i_sLK&VsN0KUjuH zc!|xvz3Ubr%YuBzAK%>VkB>F1d!Rq;1)1HGsh{vugs?8EPfQ`vOIX16G%SEqKs_z4 zKB63`iT>HYbVKoMBh#wNCEak$p>8{8>%19Q>njl(s}Q<7R_<`kUZ7PYb;hK?)IonX z(XY#>sn++F#FKIj)#sHyqSX)YtOL$aTaNag+lBsGeOCYlI^XS^A8+n4Td<&MH_YiN zIe(u0`{gV2CdjTakcXF6QWKK7#+@wKA74@rPM-WljJ{WSdG(c*C7{tT(g`LO;C>xG zomO%en1??Vxx%#4)x_dY^@a`8N{6Tvf_zn{YKJR!j@;eOLk#ADTumh055$AQz6RVFXit?V}IX#ZmPduDf(#JM(=3b$jeKWiOKZ#+u@*>9Ned&<(G8C zYAJNEXaySCuRbcu*`zTTv23n=s`^>)lcl94QXHyooVYul`L&i^;}PmKr0&vs{8dkW zOdPDu*WH!Q77{lI_~fenM%3}wlp1d`W&}2HAuYBzr+wqE1X{w4phJB%>OayF{d9F@q}%7#sM{4zsT{=b@QOwVX{*y7^obOz zg{m7*GNdP{EkB!_dm6KBcwM*<&O+`v4hBa-6h#wqJb!=}hB~A90?Ka#7v%PTu@gz1 z|6nI_Taqt93X2_83+2x4X{Ch%3mu(<=X=q zK12kHn302SW$vf1$k#G6fqK7W+)SphW1lZ#moX}Wf((yX zXpa(1VmxDkqz1Xs`t;AI6e8E>a^K1{W!e)w)Z`jMz>#XbT-8rs;_0n*C9taU^duLm z;*UiNMOiAM2PvM(=^X1PQt+IoN7If-q(5$kwYL+JVMXZQdQ|hF=H-lJ;^As{2*=8t z0ISzY>?+%R*KaDJ-RqN8K6?+1%RYM~$*ZeB1U6Iq=|xwmKVm{!vCTe}@tzt#9qh|qg zf3xX&w5IenR8PBsF`bMx>rqH}#2bAvPm>Bq>W)XVwPGER&DaJNZJPJ(KFGJOtIynw zXgPmudG_=BK*cNh@f-R!MFhrhHRl}~*C#Xtc%g-`a^^tI<}o?hjp zfws^3WJT%Sl4Jgk#2b$Z$8Wt(Or6avcX;>fm;Rr@tQKgBu zu=5yWO33W|h_wZT^RlwDhpL|V45D$Wb-h^zLMHWPoNmEe;XQM?pL6|3-@jatO)~%H zDxNJOj=}{?&U_vbRTsHPo-l`-uC+W+)#lh>_5AjXgoDYLV&QzihcrB{(?8SLIoZHK z5AMc44KG}UIOOiOhG=eic2;Xc8^2))hpd#5nGyNy{o2v~>Hw1`j%yV(=XQS%ArC_L z%H6G$>0Xf~x+gW+9?w&>Opa6NQXlWxD_9(9P8qZrv#ws{(KE-@&6qB4 zdu6a+wVmmH5AO#IyK|K;P1Wa21w|&6#k2kw_e`d4l9J^!-O=M$u|b+fKD1fgmXlo)er`(oUm z(FN))v%Vo{R$Ai8!MVCcaSs7yF2y`obp_)*t7)RKZBqtAN^Aj6VBoTXcQ5S&Xx*^t zJ?N&qf}xA-dAw~yO2Wsl9prrfg~=pyPm+{RbqlIB@IHbIz=0!-Z!X@{&X|6p#J`|wuMZwRxXUwo2^#aePf^(ge zD&@7C$y|#w<88hFiwh);JYjjPb9h>|HM?y6bDY8d%G=eiE$a!sGa3H1&q5LkvhKW8 z&rH({ydM{}*u2=%Ur5d653J5|5YoM{(vlK7F|^NkXQx#gok1dTo)*gN+CRhFOD=ehy8gNS<87=C=YG7ZcO6|x?Z7p>aJR%1*V&+v<+t49I4l4c_?6EEp zyNBUKC(PG)(oof=eq_KfoBMKdm2~xratq(1$1cCn@9Y6_IO5E@viq|~X(0;`Su8{I zVp~`TQ*k59hCc*e#f#jv$Y$K}=C{u&2Ju6$tgCj)?lu_3nLOZ=Ff~jLaF^LdyYV_c z9w`WE_Zro|7GULQ>ZZWrhd^MzfAQfFbN|!o&-Zih$2m_xHPL}d%V5Hp_lk< zcWs=dEBs94=0cY5$uiJ;*OwO;nI@@h^VR2zzeBu~N6(9Gjr@oE6woP!l(ZkGLXeDS zjL9aW@{5SX**SP!^`xmqDdZFbBb7qsYt2~&4`X|RwxAKr{*k7d(B7 zyrBQq<7=BHAt_Jo5`l(Wl)(1^v_Ktfc!g+>1~XFW9^SNiwr%&H|pNgZi+@qOb#-ZM?) z1&tzCsv!5zbr(X3527bUft##9DKQUtM|{ThDfJTBm@)-%ESHkex9*t=s|Pq$Mvxy)OG^TB^_#`OPsQKt;K|Z_|M6wtC|2V%o9nA zXha*2cYkUXn64X@?M_rU)%qL|e>>mI0E`D=925KCOz#Z`Wn)BkwjkcJ)e z%GFdUpCv#NWL0lt4F8K?rus*rM=F5-TvHeUtj|ML9sg8<9ze%qVzS~1aPUdT_AwTJ z>pvx;q3A=sk}b;{X=Ln2M=Ncw7@!WPS-lQL&hiqgMv7!JXu#$grb&p)Wdm|@%%E!+ z@BtdpW8d7b(Eb|kIG(CR`WOl=;jTAPEXn(u^YMOuaf%^NUj3OUV`KH+dk7LMF54Dp ze;@f5Mctkhb$W?UH&J3%r@?C^#O$w%@t;X&{a>bw0JD&9lajsAbfku57+Db0R-5mx z)<%EzzmS!Ew({$H9LH^taZGjQ+~L91p3nQ+h7Kesv8q)>hwN zR_M3u$irXmdlEuILV}t$B>(T!b4bqS4EgQ1Prt+^VXM+lRE@4=r~1{K2HR%jm_KzH zg0t<%iMv~JGdP6ze#*D10~wd*SDF5Y=^Z5xl+%ZR-TE*7d0^l#|7@XQv0e%cbmmaw zTIcw<;~$d*;AF-o&R2g+5Q)!&nVOh*AFNM4UQ#iJ>NCbLJ6;m)M-rV(5rv)LTTX7u z)F~l|jirrC&Dj1fk*nF7ue#rhp?o8++?vkT%>H6f@HQa)2y7*TN1j*)2t2@Pml&RWocaOi#*S|F=!+hr&p(z}{SKWYBp+(PCPqX?7_w3F1`21jRpY_l zX&v*Am)hx1mfwCS^l3CrE*a>|_u^%y-<{UL+#1%Qoqs3qbI;h>3FcD4{IBnXP($1~ z6tQaE1d}T+>DynQ6yW1iRRDaW{V~V9l+$FTD?xixUfjKyyblx`1WCZG80<}QHod0b z5rlQiaZ&6>QoQ;(lK1_K!3B#ZpUGJM7vrO!LoD3BR;r2BK2PN5sa;(A1f+QeKt6HH zL!XSyF@1eQ=Jw?`CPvLDd9yx|C}sgpzIijWz>I-Kj6V>hfNBPMdPJ9>2w3A!^0mB& zzA>Z!ZkmxP_V6c>^pILSH=>_^`WnI&pQ++Bko7HD2hhjb+jRr(+Hrb9=_NbsBdQyP z_ItnX(9w#=)yk=9B+g;6fu8W`>7nyzJ}=a1(Dv(mZwZ==0Zfise}5fTDfLWY@548J|~^N6bBW}XXV!Kna4Tpq4`_|dDI7FmLR>^S-HNyPp9#IlOv?0nE2PQK=cF5 zJIG+iECsM}?F_sLe3)JNx`X(HWW0GUi){o`#Wo^bBqSv>z*Z2&M-%e(CjuYoG(JfC zD?z)`T6Kinu0?V-43)}a&}meC6t(31iH~x9hkMXfmHnuKce^Obx$BasCt!)i?uQ{>|<4rSi za1dD{lmD*r;0^VjnmVqRkHe1p(beWO#ve5HXZlvA@G(?EsHoGx`vBaSEVV=6_ zgOqS?JpWz^v>Y4eNE1!@Ei505USW4`_B*oS|0y3E-6X3D2$k3GsKYkgDL;Y4+-;Y42x8Cj2Z{KB}b(#&_Ex(kR;O-d3_ z;qrQr#$>21Ct%2Vc%oTS`iL{nWh6G2cQC@MmH>0GQPKW+vSxK(@le-!`Sq?jE>JOe z?XPjFze^j6z@a!`+%X3%$*w_*mdd^(F%{1vVUdOP{F81NQ4t3Q17>$o8tX28?BWk$ z@BOtH*6C_5)WbvaYqaR8=6OcmFXTpJ%hMh>xc!rf%nfC0Qrx~gt_B4c977!)#-Hvl z8X}WrX77-IS96)_@f)d8^A`WMb`J{2VZHgXH01HcQinTqbfG6qq8)%%&7?(E`u$U! z@BqO`=iOVy3UBkk$*#S z$L`uaadLKbRub~pgqHjUgnV37?EE!W?1UMONyu*4R2IzRww_-Jj<(71OycoKI&=+b zYsob8qjpZqC=BpsqZWhxpbKiF5Oo>IWr{R=r!;C082}VH| zG8XQ?J;ams3Mnn5ZB>Qb_>wo)4l(-OJH9uf$=Ux9byZ<}J#O_pN!i_(_=*2K-*}p_ zM5V~8ZA9;rj$I$UlOd!0hLopsNKw%|D1viS*{uUNn+8kL<^n4!Fwx{=`tAv;gBrrk zt+c?5fGt({>YbgPzBqo+#K=B;h-U>FPeYmz1uccAr|hdp2sV^M9kCeF4Rdn{hGYaY zA`aAM)s&gokQPY!xG8zrqR7YHi@!C5tKGkkk~>K)EZEU2-4)(BQKoxxuyK{!Bpi=+ zjO?Y_m-l6?_K~HQDH}}zFH-4!FwQLNrmgI&3;K#$AR6Sh>~ENjlsgP<)LmSW1{s{a z)3i9I^wkkflI}jISa1fCIBG)lC3(tm3uf->VunCm@3gYA@uQtd#fzu6OoFGY5>)I# zUmpO3YPcBz7-^i%6FY>9N4gc}-!q25$@H_jI`iT8&!G3YiLjfP-(lVe|Grh^t_BOh zNeoh0v1sxmCc{A`iU%NA_Rz)x!swT1h$lgwLHmXO?&JGPu?T%kBr6lsNlW7j^GcT6 zW-qiYU#}(yAIYg|TCDx0STp>YsgGstsN>hMyXBIT*HyeXOc~gD4-w&|CX@1m(%lr! zH4Gt4TnTiwPFw9W0lp?k#aQRHUkK~?j|@Q_^3j)Hm~|BSbG!M(aMrEJl|B}xX|Uwn zOyNv`?)cws6^VZc(RJjU%HXy%4TS_t_%!iZji2vTA-93nsOuf^!Q5rW6&`GC=#UMz z>jN@ob9nAwChZ{Lh-Yl)U(?`JspF61FLkFR43=9PJZX}a!(7a?}nyG@zB74i*p;c&n885>uPm< zH1<``pCiMCjh#|h?@Tz(&B!?fOiO5DmAR1o%28_^@HK{?$zMJ64>d(akv?zD2j$2k zzLKw8g(vTI_PwkeD4_fVK@h)@Py>ARwKbo_8@r9~OpM@_}w_yu?_-tuXhV zv410)GI3(=z$MH$@x7$gqDxll(*k2NG0nSPjt)pQguFE9D$zLz8JCt=$*V%Be>*);RQpcOjXvlq1Y!V+ICnxpJa`h4dLO7`_>GIsT)-i3@tUSh{7EUUcqG2a>1cjms4 zi5}_k2npDS&Cl9;U!S{p_%+*VEBrljh`3(+#c}1L$si_$R2_eEKtTHUbLxqODc7jj zwYBRSI}KTF+C;SH@k>B@Vvdjh+a+dhCYwC9{DahQI@b4e3vS`9v{=ERrwEum9 zbi)W8_^Ls)DtT^;V|wd18XCiv2r{5rTfN1x<76&gJVR687%50K{iM?Z9HW~3l|g{S z0)m3Mx^2&%&epq)&iWICxkB$gY_w{Ra)~p#GeEf1(m*6-a7#Hi%#Ox6 z3z7HYY-5(M=&tAo)S!+e(Ei4f*P+bJ`cuCay?#BEyyJ~zuCU7FN)PnuT$3X`NphWH zJgaC#dxP&tD~=Re$fV~ulVq)*h7V-?vL&iU;QTXF52gK&Rvw$djwYGbMKldXeoG|F40t0;@c4+ z=BSm#mN^9gPt&W((lon3m{>jk{MW6&Z4aS*1d)SB@{;B+u`IV3@gE)tDz@ojG{KN& zobXi~IyykDx0PGXNNQ?;Qdd9ENNE!H$KuLLLP`p#KY~%-Qns?O@$oqU1-_{=8B-VF z?0fKs4s-@=n``4G6J_?wH*XGlC>~wC_sy+8O%9|boX;|JBp>v?w;Roe=gw`~UedjJ z^F~Ze45)OqTXJ#@aQn*6C!M&sqy#8X1_lPrNg~DRv>ejDmPiU{8QA%3F@)k#3EFg$ zf(Ri3)us5!#?085;l#_FXcpy{LLh&Wkx4CQ2{)3{o@cYOvja_pl*bySgEArdV|RCV zXJ;h4^!4zEM?bSuMIMcTT0t=nMsI@8`XBvB=12PM_Wj44 zaJ!+8fOg)LQ-mMOYIB8#5ipq6c*mDhtSzmqR5;E0^}H2^v6gZ-5345eJB=SXu7nV_J#ST zu-4Yr(i%>B0|SF6PoBW8>L4rGO_r}`C`H;z$VcH)T%)9-@;yIIf?e&D(~d#U)&4VE zr#Tt9aJ2hVw<#2#fKFU-k|;PC1Uw6Sq`kepJ1c$J>*yIST6$=W@jM22`1q+Z{u+}+ znVb}SrY~N;BtJFNiTD8+3swp*eO$-NFw)Yq9w;!Y!z7^Z-gx;Ao)zcHH%`}q(i(m7e-1V`$%n}_~&qQ>VS>sG>`2inoQ_wQ*FQ|#w{ zm=3o0^f-(aTBxhz!TFN~W-!O+=3bqd#yc#iJO8Zx;iij=ApAo6;lqcXo;S{us<8$T zjU&y)}r#nOIsm6(`tS}LGh=D{0_=r!;_Pz!Nx&Ql!HS` z_UUwYNE6nVxgNp{q7#eeaH7(hev?|iGn|Y-V?EVH(32b=AJbl(P-O6Pa<4r-Kdscs zQmd@2ETz*9&dtsJc>7&wNXUSPA_=mRnD6l}>>MoF?mifa_bx((#f_{KLPtsMd3N#( z$UzIi@C2vN3{RdMNc$dde%r|jc=6(eQQ5=vT^vw5d2E9SO6e0UzKKBQwEn=Lflo(A z=lpa>lm4E7N=!0HA?!!5%<{|!WHf4k01B-T{Y_2HS+&=Wtxq~v_0yy6!>z^f@$pi+ zc}zwQhskn$eEcjpCu=P|!}h*DI4SAeeme;rBd{xjDv$N+4|@AO6c69a_|JfkKpO&H zBuU^i%fItw1fe972;?LoB@1xxY)J@;-2`%G7X5ZKSr>CuiSgKgIJCx1*52SNJ9#mmV}9hQ)gkeA1M zPMk&w^9uYv1BPcO!7K}A0%0S#3VDl;H2wk+ph4v|xG!G@!RX>}@zweHIn0A$bL3v_ zQ!1ET{zO{A!wzAzZ& zY>^cv9Ab-{_7MS(e(p2mgmQ{s<{+&iCntv+wJ<(D3A=h>Sy@Y!^q04w+WMY*m&Ct# zfsd2>Z6y2)3xn4Wk=2D`V`H5YNcWJYU7(K-d4m*9>4#a0q!)8$RS9VqA|49aK0C>w zxMgHCk!M^{`}9bDlIZq41ZVIu`Ln7-xFL3waI~}Hp`*gg&U#mVrDNMgsPQg{$;mMy$tFy5-U0LDwmwmomiDZi#f0_x_3Lm` z>SE-B-}d(QTOm7QDk@coXU%Cjw&IK&uuI0ZPsJRRZ(vqmC!m+C&$G29qM$IS^Yg7X zrrVI!KB6)FVB6TzoC}Us41xJFOkjmUcv>IK>VgxsmB<*tqrE|xEm4iC^utL%-{ez= zsIjEWQaHbdmOgpHwR^{#^QaDdLdh~0r@ES&1ng3XgozZgwuHxPv~4n~4UJO8>a{cpD3gq6dBS6EC&cSy|D@9pGfZp|+zS z?^#(bW@fU2$!!N_Y~v@s(ReHLyqsdU(*5_FfPet@+2>1e++kPf8ViucT55eypfwdh z!MP10K&MAD)n2=+1K>Ppu$?DcZ4AOY_gT$qp9cIyH+5{56MypO>hQgn!I%-9qJB{C z8x)uh><99UjgRvh7Cr+D!5HEE`0*o%{vZ`JqU5GSuo)U0grGr65P_rf8d5yiiSDK` zQg~cyDgzlAItvBF=TC?*yS>x_<`IFZq_hiu2GM9}KhXHSq!(OgG<41Xbo=)0mb?6I z0e$TdmU@#VVAmqRtxLi58iFw4Sy%N`>FI%i7=)dI`c=w%xBf)QCH3|@kp>PxJDHSP zdbPeu`C_^*M;$#qWgz=2cc5`l*6VVDE8qSXex5~$Avt7ZW(Nni`_mQRf7SsRfhufl zY)Zz)@4(H`O3{`{JoC6;si>&r7*{xYc!(e-Z~HALGb`(^q2Zi=_FY6K{m~f@$cH=s zUe$eDTTkeE!db9cwMR1{goZV;nHfJb!0et+il{99=t=;|M*4b)+TrPutCm*(2jy3= zTdxyW`ci-Y{w?Es{JNY4OXBS{ZU};hzTbqvMJK;LwgSUOJDd{UAxLSgA04gGOqGU# z#|GTA2R7fSbS^KnL_(y`S`Ufk;^bT%El91Z0zg980>L-3veHXWj}-n#E_6@N&CSi3 z=aJoeara-q&}6_1&!eKI%j_x6Z}dG`SX_i%FDWiYoS)K=61qM&U`bcsR^CVakc0I7v-KWw$Mrh~8@Ee+D{} zgUxvb*p&-p@DV^2Ti&tEhbJeR$>M;iI_IaWo`7qIV57k-ZQwe}Lt|rONSl{W=bP4i z1N|?oc)%lA!PCd*GA^LVWyU5XjF#FBHH8rj0d}AujrUhoRYh2H04gS=U$Xn%iOARG zCQM(ynVK?5?7n7J`yOzR+6|xm+@hk#_wTaH;AU&U_G~IEX(hf+^;*^ zr-6woUNcA0%hsT)eikRr$zA;Hr>3(re{QawgghpoZ|NDDbpUs85q1(}$gs`si_6Q9 zrqw4*ZQ=12BoYQ(T-*uMemMh!geMXe6r`kA?-sLia)!ev(ZM;h3kohyHtL2v6hDAa zDg^>T!y-bHEs>!QK*=cIM67y?xsgxAX=Wq@?6W^(6U8Tzp8r&Fb%OXp{J1YG`Pj zLtwM>VWRl-=@XcXjL-g6*nxZqx0awF?zq5A!-`OQ-qGFtUcd@8;CdSB>gteyZGE&Q z!3!N79n;g(Av%0*DR-EJBj4QnZ2$=f)c6syA_B>hUI0b)upCdqH>soJL>wl9gM$H4 zEh5z77PC$<6qC}8C^nGuy}Y~-qqM_K`iH|g4OJILkk3Km-P=1;Y!jKY$$fL8mNON8 ztMN`Gs+^+u1|*T>WIEHOpmy`dU~Cc&4M3>(pf8&1+xs=(reA+wXXfaq0SI3Q zH-KRya5%X;)6>%CAhv;h={5yp3B8zlsh$PJp5oId5dbjV;16^_{e+5v2NoUlf@D6A z5-?e3JkOnVrVMRXHnzJ)MiH6npNUCGjLRQ!txrKmikg}lG7I-KPke8xCr(6!AeE49 zKRD@+qiJa-riRW=HK=;vVxF~qBTS|0>sR$8K_yMizKMyqN3$bP9L;}A-LNK4sEg+i0&Lsd@ag9`ax$5fbCjREnXcYISmVSEpWY*W9!tq|mQQVEG zB$+J=QnDYeaJ>QSq3e+TDkEdsy($j|T!=YLl`Z6)ie(SKt00F*KoRpCXXAS7X`U}s z{IMAb%H~II5+gShId7IT56fQ_-k=n7VO4!_|Na{;U3Lx*Qom$!GUdN{4Bc8p|5nahZJxDeIJD=Hcq8UOS5nFhIr z0v>CIu^2^Y+A(Kk&jwl6q4i)b_pw==sJBr(A(oUZkz2qx8xjwRc8rvNU|9=Xt+5e` z+Q}Y-D+R>nOSj>&XF5L%OVE;}&;FVb6C|CehzR1kyb;J^=s)C`5}8u8!#6jb?`ILj z@%?KSrBDH?`CyBSi~s!jleNZSQiOwpBR16V?EGZIrtayFo7B}&V9c0n*R1Z zN1J7wkCp|Wi)*3e8XQVy&ZDuy0IqU?lg!*Ly{V8WnHCd>zwK~Xz&DNB4Zg+J@j6YE zVlV3w(u|CZEFC!OhY*sTyW=kZgpLE$G^}r|BQMQBP%*2${1pUA;fKTFk&!{ck&#`{ zf>AwBy8fU&^OY*$Yce~2+O_E_3f8>cJ4}*+?$_A3xcTb_zJG^HU4C#wHz){b49gYR zY2VNHszh=h8NO>h()|gyCol_xAJnQ@KC4ZMjb%P*=Fm*3*U}h-V*dvTTii?Ic zK*H}6sEm&B18h7jG_>)>8bl-R%}6?T#}h2wMksMN#)=dqclu;5@bK`OB?#@=A12-c zOhoYJhSN;7h1BQeqquq)hX=qSd7VKs)Jo|Onpl()47FFvU&+bI@sovw#6(8ozF^O2 zyyXUiWcvP&vPFSWz+uECB);Uh+y+V`ufFqbr9m^`fZxNP7EQ746|f@9K;I@erTp8I z4SFIXWS52I<@**E$U#`@#ICNc--pCAilAJj8c}%u{5h27aB1xqJ2$tQ-r<8eAmt0- z#H6I??*AyH%w8Y$fA$^q>gVD9{;mW*Xgc<)V5w_Bm#3zt=6k_Ob?awu!3LieR73^<= z>uj4>WYy4=l&0%TbD;g8bS)4M8~f+*r~gygSB6Eou5BwVAs`H;fCESiNP{2}L)QqB z(t?zPBAwDhBM6Ap&`1i1Qqn0X-7PJhL%#Q{Hs#i`CeQac81leE+5hkGE zG`@fl*Y&lx<5q=o60x#d-(g@t0;18k2pVd9e0;z+%K7v)qx1zx&u9d!qbHUlsQH4% z*h;{GP+wnPVA(e?@CNlVNx0P6sy|BsYtMv&NT!^HN$rtqXNu*|1+b2u|rZi6N7Ao5w8g^UN`yD=1BmED{HE& zr8NCd*y~_eF>QUBayNzSlrL;2iVf~BEy;#pr03>j?jujT^ygBIx zPDuW&W!COW!x8F2=B!UzJoL2xwrEw^zh==6t@9$5n zsH+o4y`wbM@ML_Rm6e{Seg&roRBju^>OjKu?QI>hX~IR?0%T6G8DoPNpoo-M=*I^t z2|)Iv7D2PSy{%Je9iOMJY6l!ueKa`9KjevE#b9Z+jEp33w$Mv>7lPygq&Mg_GOT;| z$wmwZ7D)3W9!%(SE30b@t~xqYt7F%%U;lb>!T~D*1WK?&KrN>lcsHFK`Dt7Ywx3H& zu~&LKI()N3Gcur@8rvgqnVts4Z15E%zE4H!K?Eh~k5dHTY2qUT1Q2q_3CKb}g2Nd& zJ01y;d_)!(7bAjRxOH@P=Ie$82BMQ_%|S&O8LYy7K&P~O`t;}88oSv56Bb+m_@`hL z8E4l_t((SI?{jPdio6Zy8?UiofgDfj+<}5m2B@CekCsBq(`X@{o}LvI6#!n4U(F2a zk-0@h&p}>-VgVX>5i4s$FNSiLlnJ)m<}E` zM{__%{YC6R@#Y_|2l`FP($cc1u8wb{ zcg2?jY0cuAH2~*$tegNKal&2wHXyB6VETOX*H{r6viHaW^jDFOVj)f40sNX6+_wxL zh{Oo|IT}T7_KF;L65ano+zUYz` zy|*}d|82S-*mM7zDd)(D#2|fC{A3Kkl8ow3=qo02)o|f+_Dnx0j`t2Xc7V2t%Z47I z+|=X=TI45^nFZI%D&8NZ>9lW6wOLuo(WJO|G}C-1*`EgVXdA2I;;0;me}a6REEaMD zGZ>Vnu5i;&V+q4$Ev!yNk=Np6HCa^;(jg(7yaT3f0YHxhb_w}ge2{=l0MFWJCbUqb zAhkLpkChDDeY?@0BmKyBl!sB`vi28xL}}+h76ukLQ!S-^+koil!#^2#7D8wSUea}& zds=Y6T_)UN5}?;d2}H6We*lX3^6-BFmBAnJp?MF3E!O<@0j*0X**^quLa(wN&cg-) zXtWT*i?h+x9V|5W2SpFExgNrto|vbewk9by{6RZ;NC>SvH(F(HwcI<*^Qy)}=oa&H z5?!=%;gHId3`l}x%IG}*3yH6K>)%OyGB^!?>IkA4f^WYeo4B9phTUrm!Hu z&EvR179U6;CrKPcL*;?u#g_>rCkqY5w|V*C0bQot5yU>OQmP}El7O4qQ20H8JqFu1 zw3;7zm?>1js{mKg*xbBr?IzIR5_mZ1PXmLUzkBlrukBrPA|mIHt@7wy<>7y4`Caq3 z2PD7Jg1}b$H_Qj#r_ZDE98{(%ti)eXuy*}Jt>6h`IfYp`DMS{^1j80JFEPAS%>nKc z$Un-!Y6ThC3wuB}?t_^e$D?1Uy^at(qhWjiFTBo8VfX@20$+yw-q+;U6{czGdDBjsB)gh)X!&30Y_P=*09b2_|a z?oX@iihy_l89Dz~c&5D)0{B1>dnGxQ{7bPAs2W^Fb%#`#hIf)cN`VZ7uVw=wL5^PO zaL{{$8VczuoH`Q-WO&K@QoQz2Hlp-OF#rCq*0AOt5KzFEfLVjRBf zyKiX2XN&Z78+fTthJVutzoq`Eb%3T3%Df0cq!`=}q0q5xw#IylX(2m2Y{Ar~1B27746F>A zoyA6Lm!YVij*nm9-C#({T+2_!gTX@c=8(r|{$av-_049 zGOpJAnf7E?J8!=}(h{TKy26mkL4%mMkKO1GJc|8oVf$19)ZJiGpsabj<)PKX2%uKh zc#njq^OgWE4LCkX8fIJqpMzr|$X)7DwubnwcKnT@=oGI{9p;U(BGv@_gkK(k#*?Eo zypNxUDgTda8tA_Lf4x@MC$4v&Thy8%;G1N~{c_H z5%%4klf|sdSQ*pkpj#c>k9PkgDn`gF5DnH8KKjEcu`+Q_DPM@Vx~CD@ZDOA{e6y5{b=UXI^+c7!z@GWs%@DhrCc8@8edY{i^Or`!V3R0JHltdUW$ zd%|NyBRT%7DCvF{cTCI9<0%bs#-$tnPBv-Y(cBy4iD}}VuF;cQs=Zpqs&5n8AKWEN zD~oqJWbPqzTMN**opumpp?D2FNg38~Hz#iMIO)$bXMCrx?GRNSTf_PtsG)VjTYyGZZh0-u}f3S}1$AF<<^t`NXn2=ytMiA?ygG z1KII^KiJrsN8@?|nbNaXKkSmPQZ(Z9M{z%WQQtzY?S5^EV?i>Y)C>}nb@T+C01^}U zOCS%E@j>OiaL5?nF;JX6KY7(ZR5V$ZIh3!lp79fqY&xMF9OXa~HmqoFV`9M{=M@Om ztTSbqfheJ|g<2sBsNbkV-fzy$83RZxK)76DWT!)|Pcf%0x%d1SqV{%o=A*z|y@FWrT7fsvJ8a|P?WoaTr zPJG2u_;*RD;!L^#u5!m6aOA`N+8Ru$cTJpuB-r}OXpv&P;&vQ$4;taGmf>=-Elmcz zShVwtwZ~aeU3pitkmgD+UGZ~4%69WccS2M`j2Z)xY39E;g+q0IXe$weikO~Oz@ZDy z%=V1AE&m5$6ffXE2&2sH0Okzv;wBcu05BIu=?{D-P!@FQdB;X#1VZQl({F6^7`K;y z73rwytYdi`toeX?8`cq;6yvy{>E7 zvi*!Iof7FXu_uMINdeqi3>N5t(yH4I6&T$X_o{xAx2+W$U977SHOb)dH=7VR@8&Wy zo7+=>z5<`?fj+c<=n4e+l)71BaQ>thYHzyKfG9Fj3~IHoHUGKw&ao70oX`Gdnf|tp z>6;_fo0Nj2wyv|RtkU>jJzOx>u*9R`bFZ=O)N`b;@9M-o#Au4P?Ut_=#UfQs1%-Zs za#mLmVM{4ojed5>9L3UKe}U2H|8jlso-eiGn7!fIUG}bbC=g2!2^4Bh-a5RPWN`|Z zQbmt3bt0M>Id4nP@a0h`;^bg3{~$bupy77fSjEn4BV?Og>qqo-dAt4-n6cMgX|&>O zCuNq;S=m@Pb#tS!ERLE{eR%9!wG$5IcbX@|3Wp$ajb>p2vadE}9c`EURqiv=P-UYznfiL26Ab>@L$6c&ENQ~FfU zenn8f^8+f;t~4~&c>SP2!=a`aF_$)}=sqpZ5Hw_+=SaD;bDDJyWXfsZizOkQBe2rBjFmPq z`G{5u260z(P$l2DRw@smDpldxZ)Bne6gOFEMYP#zwMAWJftKm_fs3`ZmykL(Dr0@#n0s9#E{np03!S^h4dDh z+nRE6H9ByUlsd?IXoYBJOAJc&K92*}KL*mZ$FeHz{_FkPjWW|sA8)uA{Uz3moElgY zyz|4?tWbRA$4qyi0s=Uq^tV6_*Ov##an=w5(Ph7H{)r`)M;rR?i(RU$+;`LVwJli8 z{`7`w@{!l}e$C%+xMMlr{)M2BPI8NOg{Kvs+`I(<>B8wg&|OswNxpo;zOiRz1h}Z%3d$(RJ&!uPK&vP+n>8G~z%; zF9o2Q)f-x~g*u6ek4!K$bonI6A=$u>U!C|e*Y*9dW;ybFrXVo4b%SzQdNcBLHqRA+ zd^aY9wgx-j-J_=`rjEUWvq$b~4G=!&=2{uAwG?33*FixL2;Z9Y-dY|jmy@aoK>{`E zBX_7ITvE|r4C=OO@p0@umw#0xptzsUPMIxD{*$;_a`9T^f#w7Ne(oN`tfUd-b*Nt) z@0i@6`FWq=qpxKjvhQ-@KG_Ou0Vg2~7V~RgtdLlefR@`IurL`IK86I8a{HSYg=0BL zJ`KbB*u~BYSl3rEC53}Zu^DZ6K3>oCI&^DNoTQ zd;PLk98_fu>(&B1W_*lXvWw?;ceL&7L=EkxM2R=5Uu90d?rwhAeU!4&^W~WuK28Xd zvou4xrT}UBcu5XkM#vq4h|T3VpD3Z@V}1E8z2~bgv->1DtPh2x6NxL!O?^<8t&%KP zreHtD>kK$f!u-Y$YcNnJ8PeS`ztVB9jlWS7YzV+PCx<+8b)|~c;GHQx(t9$gFOHM* z;7D(&Vs&C^-l)QZlX`IFpjUWJl z*i0ioIxa989LXmWvFb0Mn}h7U=zVWu*SP4GzIdvd^-^j>hU#!_h-OQjDN;(luL3vt8Kk7zwq2jiX{`mVvwX5T4ts6IE-3=d4j!$iXWm4;(KO17* zDX(@?XG{*sopY0y5;0|NdF3H=&tx?{;Ew+`_xOsV2D!gQtO~M~m&ZHg2+g zuS%TS>lCTmv7a$VNt~{KOXA#cdD~<+IT{Qx+PcP-!2PTyept{7XG`Y$Z7O#)4E`h( zT$8g|LS}KL?=jfz`C4}iA7$@GiEFtWtaU!{QPQG@wOSp^$y11A=IP*wk1ol=9cc&^ z(r{^{d&&2WlW&55^DueQSrUq9{P2Hn2cD)edfzSm-cMyo;!j`Tn(uL>`N~`F_<3P(>T>i)~(66)(5jgLNi61H6pceeK>b&vJX=|F7W!ZqR zkF7^n~=C^lW=BnIem~=lsNkV>WR+I1=uSGRmR@hCg zoNl?yvI|&G`pma%$gQ`x3W$0LazHa4w@0dgmM+&tEx{I)fx&69D>Q*?!|6U~Qr~pt zBYvP`zN|VmUubyvY90#_kaujPh&B@=w`~MufsE{adQ5V1YV2;;WE>8r;y{+hMw@i5*hRTmFW*!Dvyk= z(+pZIw2dLpI~XhL&z;F+%zt(mx+bO6Im|Xp#6u(L42H6m_zuYP^UjXVB1s?tiZk^) zX6=XHI}-bHdNRu`#ED~sUowC2x%@;cDmI;~mb|ip*9z0D2<9;?QurmEnI}xd9l)d^ zy717fBdJLn36#TXf$n*_wJk#B5RZVp>ECKvR!u4xxpfUB}bLEO(9-h4*3B;A@ zBi)^?tCDL2-nUgjT|lmS@UtWB=-0~>qWE_bJ^`^TBJ)Y3@|m}pEG>x}i!u}*pcYsD z*GREH#>5SN(XXP|{^F0D0Bx6C!zzgg4Gog!aQhOgso9%y`q_F&(az3muIbSI06CZL zpb}#p+Cds$Gdr1bf9B92OI78aSio(!!?DQu{5)VNnSK$qha|ATW2}D+tZD|oAd301 z(VFlzBKF5U zaVP%mp7gWhx4hw7{1~k4aNqPp0DPr-FI?5Ym4x5*_Ku)sd=W>1%Q>7zt&r>k!xx`Q9b{fd5QYYB5{$p zFsI2}q+YU^!XJq=rFN!>PZl~_*f2r8rGo%XS4i1`S0Z7*njFHw!ws-Ak#>W5&P94dNMzIcaKw0-S^YF&@b$ax zJXO73r*Fmfe_$e>=_c&!wehWdsZLE&TM)a4K$uf`Y$q1kCnWZNnnwCr%H#h0SqsvX zz36D(l=~8nOUe}Pk@Q9&LSMg%IUX4Fc71R)^yTscExF+jlwRM(UCaQsaN@^aE2S0H z@TUzk;HRRLSp;55^}Kt$Re#DQJV}4~83VK0#XhtOH@C%gW3?E`V0*Hk5hY=$w)H|f z*!gi4Z?e!=U@X-5Xv;<}19YsA)vmgZPT+FtI`dQI`lXU6@Cxh)uFutj@d8gzD zu3TMG2L1x(vpvi81LAbCZlvEG#}@xq@EV<6z}BAt75Ns&}2fCUCbIxUq9)2}(Mxgc9qc2Grzj$sML%5j=4PN5dp@WU<#}X~^C2&9jQFe^cunrQ zICX$^1VM~hdw+OIc8X+QXWDL$z(Kz-0^!xSH%m(YHL3J)@s(V{nFX6`sOrc)`#OPJ z)YX>FRXh+apAf~Jc}e6XzbN!3IOYHpD%){E6nLrTAEC6NK(;AVnD%^I;!a7wz_8O? z%v!rq|3D=Y!=)t~z~|GQ#F+5c?@v=bA%g}C47Jiu5PYsl#DY2ksgqSgAT#QR^Z5ej z>!D zvZTT{)AF|E=`K>cht%+y_0o+m^G$!F)5X+M`-XR6#AMjeQ&~E2)g=k{Q9NMRCSCygC{mS z##X+;>Bx70=3p5tc)X$JbMmnBR8VUF1Cl}9fP-B@AtmPZHJ6b{Im~V^DX9&=}WOL=!(mB-MG0JHnBc`}+U4K0XCNi_7id*=D&BzkapjvBeY`oK(+7p|~ zC9{}pFPQEppD5uY(;3^i?ONB(=7!Q-?8*S)d~5E@f_C7_Z5+9H1uBAxJZSXo>!_uq zx{SXUU*OOP7NUYBIHk>wHevH*CRJ!(we~8CR>@y+u18w9tTp40wZ^U4s^8t#8A&ZO zJ2lHlSP~+M_t+vLO~JeKgeDm$KQE7oN2XuMjm8=;XRRIbLqgP@79jO@s^_A82RHhSV%A?# za#97pClwvcY}X)%AQQXyjCFPG8E%z2NYj-@=v3L^FzgIzpMv$?Nx|p8@&VNn8VV$k zSw&~^hBlAGdm1WQNR zX7##@q+}}tV>1P}Dh2(eHQ0anTH9?A>&7|&TiepZn;M3guFUeuW#~x@f2jhKh$sia z%Ucr^y+rj%+9fqc4p3h+Jq@f-oy^zGLuVsPdtxS|>o!~UL*4dITrgdX`)#aL-bqli z__(}nOCm(aQJj?Vd&^bkPrtEdUAo?<65N$<**43`t?}7ar$T>)vv)_}QI8FJpY#45 zJXI&Tpq;b%|DD$SXEfyJceSN=R-$9%fmE&H6<8or3JnL)F zR7jcz6%zS&Q84d&k$}I%Q?47>^jn|pgkXUr^Ab8->}vz{5$i8KxY%LYvkSB%8#&`r0!-UZ8FZ8R+|2OAHrMj!l46imm~|L0#Xt^GV}|$ne2tS;&T;i@rpubMh9(~L!ap_7 z^%1J?GiTL!^z{LXp`g4tE`vw=zozTtZ&gY+wl@_|sKB8C$HeZ)d4)x}g^!cg(xS@x zniG|?jGqMh`bZJa@gGoF|GxJRGKd+CfQIRuV!+WT~|qocHm46-%i1|lh`_pdv< zqSi;ghlhp&ysgvWFG|1~Vim1?MK@Fs(jHX;$Xy#s+;`%*jVM^??mK(Py{46Ra0spQ z&}dm56*XRX?Q`$*v+u*0I28m$cSrIE$d-G(IB_gFMAlv@a`3o+?PWyoE%I-g-T>2@ zY1--`Xq$Mjm|$~Luu!*Xd}AZ9;#Ss)2`PV$PFX|e8(e5l`|eb|7umg`^%7z(Loq!6 za2?hvXvqvaSdU5@w`>=Il$Jc@T8qcz8& z?ERuq#YoV`wt8g`#dp4T-^o(MnI{peU~gEzxz(68!j*FYgi!?e>;P#)XLU!ePW3sq zY}(-ONlEI80->hoV!SspLd+lpQPGR zc<)}HwS+U(N}Sehx@k1u_~>@gPu7h%E#rNK-wU3Ye+EFy&YUM>V+3W7sw_!4WMF#BeL9+@vSz9I z8gG9127qSx2jJe3wv^L`vTcOQ0_KXb$8idJo$&E|ZNI+LS9EM(hvgdQ>@wQ6B6c2s z&_aaZsVJ^-Qs`QV$eV$Jl%n`>KACQCnIC?C)*^Cb`6D|SNdidZhvhRx06u4 zXP^Nf`;XF7vgqM<+|xkq^k=6C({}S8lDH4il{^`n0zP1@+(_MNjnBfojv4~l6x=)B z!8|<(`|2rDqnU54>^;}y+}H4+?fR>m=7-46>-7=G45 zvD_!O{@K6_)Pj-o;uZKeX)8_MR7U`xg%@L%vzy7z4({j(s#bZRm^2^S+J6!bq^N^} zwVi5CM$67yAGE1x+CHj6n7tx127;2ft5erjeS;J*4sY7hlBb-6o3{Hd)&m!0Jo@aRp3GM* z&0p&OdPs8SVW(DbD{zk{F2ip=IQIviqa9?(Eq(EvR- diff --git a/adapter/index.md b/adapter/index.md index 36a2a0ad3..7c7dc15e5 100644 --- a/adapter/index.md +++ b/adapter/index.md @@ -15,7 +15,7 @@ tags: expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. -![alt text](./etc/adapter_1.png "Adapter") +![alt text](./etc/adapter.png "Adapter") **Applicability:** Use the Adapter pattern when diff --git a/adapter/src/main/java/com/iluwatar/adapter/App.java b/adapter/src/main/java/com/iluwatar/adapter/App.java index d2353eec4..c33780198 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/App.java +++ b/adapter/src/main/java/com/iluwatar/adapter/App.java @@ -1,28 +1,43 @@ package com.iluwatar.adapter; /** - * An adapter helps two incompatible interfaces to work together. This is the real world definition - * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need. - * The Adapter design pattern allows otherwise incompatible classes to work together by converting - * the interface of one class into an interface expected by the clients. + * An adapter helps two incompatible interfaces to work together. This is the + * real world definition for an adapter. Interfaces may be incompatible but the + * inner functionality should suit the need. The Adapter design pattern allows + * otherwise incompatible classes to work together by converting the interface + * of one class into an interface expected by the clients. * - *

There are two variations of the Adapter pattern: The class adapter implements the adaptee's - * interface whereas the object adapter uses composition to contain the adaptee in the adapter - * object. This example uses the object adapter approach. + *

+ * There are two variations of the Adapter pattern: The class adapter implements + * the adaptee's interface whereas the object adapter uses composition to + * contain the adaptee in the adapter object. This example uses the object + * adapter approach. + * + *

+ * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee + * class ( {@link FishingBoat}) into a suitable one expected by the client ( + * {@link BattleShip} ). + * + *

+ * The story of this implementation is this.
+ * Pirates are coming! we need a {@link BattleShip} to fight! We have a + * {@link FishingBoat} and our captain. We have no time to make up a new ship! + * we need to reuse this {@link FishingBoat}. The captain needs a battleship + * which can fire and move. The spec is in {@link BattleShip}. We will use the + * Adapter pattern to reuse {@link FishingBoat}. * - *

The Adapter ({@link GnomeEngineer}) converts the interface of the target class ( - * {@link GoblinGlider}) into a suitable one expected by the client ({@link GnomeEngineeringManager} - * ). */ public class App { - /** - * Program entry point. - * - * @param args command line args - */ - public static void main(String[] args) { - Engineer manager = new GnomeEngineeringManager(new GnomeEngineer()); - manager.operateDevice(); - } + /** + * Program entry point. + * + * @param args + * command line args + */ + public static void main(String[] args) { + Captain captain = new Captain(new BattleFishingBoat()); + captain.move(); + captain.fire(); + } } diff --git a/adapter/src/main/java/com/iluwatar/adapter/Engineer.java b/adapter/src/main/java/com/iluwatar/adapter/Engineer.java deleted file mode 100644 index a973cb530..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/Engineer.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Engineers can operate devices. - * - */ -public interface Engineer { - - void operateDevice(); -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java b/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java deleted file mode 100644 index 70e166ac3..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Adapter class. Adapts the interface of the device ({@link GoblinGlider}) into {@link Engineer} - * interface expected by the client ({@link GnomeEngineeringManager}). - * - */ -public class GnomeEngineer implements Engineer { - - private GoblinGlider glider; - - public GnomeEngineer() { - glider = new GoblinGlider(); - } - - @Override - public void operateDevice() { - glider.attachGlider(); - glider.gainSpeed(); - glider.takeOff(); - } -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java b/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java deleted file mode 100644 index ff4ddb617..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.iluwatar.adapter; - -/** - * GnomeEngineering manager uses {@link Engineer} to operate devices. - */ -public class GnomeEngineeringManager implements Engineer { - - private Engineer engineer; - - public GnomeEngineeringManager() { - - } - - public GnomeEngineeringManager(Engineer engineer) { - this.engineer = engineer; - } - - @Override - public void operateDevice() { - engineer.operateDevice(); - } - - public void setEngineer(Engineer engineer) { - this.engineer = engineer; - } -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java b/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java deleted file mode 100644 index 79a9acef6..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Device class (adaptee in the pattern). - * - */ -public class GoblinGlider { - - public void attachGlider() { - System.out.println("Glider attached."); - } - - public void gainSpeed() { - System.out.println("Gaining speed."); - } - - public void takeOff() { - System.out.println("Lift-off!"); - } -} diff --git a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java index 866bfb968..c9a1a9bca 100644 --- a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java +++ b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java @@ -9,60 +9,83 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; +import com.iluwatar.adapter.BattleFishingBoat; +import com.iluwatar.adapter.BattleShip; +import com.iluwatar.adapter.Captain; +import com.iluwatar.adapter.FishingBoat; + /** - * An adapter helps two incompatible interfaces to work together. This is the real world definition - * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need. - * The Adapter design pattern allows otherwise incompatible classes to work together by converting - * the interface of one class into an interface expected by the clients. + * An adapter helps two incompatible interfaces to work together. This is the + * real world definition for an adapter. Interfaces may be incompatible but the + * inner functionality should suit the need. The Adapter design pattern allows + * otherwise incompatible classes to work together by converting the interface + * of one class into an interface expected by the clients. * - *

There are two variations of the Adapter pattern: - * The class adapter implements the adaptee's - * interface whereas the object adapter uses composition to contain the adaptee in the adapter - * object. This example uses the object adapter approach. + *

+ * There are two variations of the Adapter pattern: The class adapter implements + * the adaptee's interface whereas the object adapter uses composition to + * contain the adaptee in the adapter object. This example uses the object + * adapter approach. + * + *

+ * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee + * class ( {@link FishingBoat}) into a suitable one expected by the client ( + * {@link BattleShip} ). + * + *

+ * The story of this implementation is this.
+ * Pirates are coming! we need a {@link BattleShip} to fight! We have a + * {@link FishingBoat} and our captain. We have no time to make up a new ship! + * we need to reuse this {@link FishingBoat}. The captain needs a battleship + * which can fire and move. The spec is in {@link BattleShip}. We will use the + * Adapter pattern to reuse {@link FishingBoat} which operates properly * - *

The Adapter ({@link GnomeEngineer}) converts the interface - * of the target class ({@link GoblinGlider}) into a suitable one expected by - * the client ({@link GnomeEngineeringManager} - * ). */ public class AdapterPatternTest { - private Map beans; + private Map beans; - private static final String ENGINEER_BEAN = "engineer"; + private static final String BATTLESHIP_BEAN = "engineer"; - private static final String MANAGER_BEAN = "manager"; + private static final String CAPTAIN_BEAN = "captain"; - /** - * This method runs before the test execution and sets the bean objects in the beans Map. - */ - @Before - public void setup() { - beans = new HashMap<>(); + /** + * This method runs before the test execution and sets the bean objects in + * the beans Map. + */ + @Before + public void setup() { + beans = new HashMap<>(); - GnomeEngineer gnomeEngineer = spy(new GnomeEngineer()); - beans.put(ENGINEER_BEAN, gnomeEngineer); + BattleFishingBoat battleFishingBoat = spy(new BattleFishingBoat()); + beans.put(BATTLESHIP_BEAN, battleFishingBoat); - GnomeEngineeringManager manager = new GnomeEngineeringManager(); - manager.setEngineer((GnomeEngineer) beans.get(ENGINEER_BEAN)); - beans.put(MANAGER_BEAN, manager); - } + Captain captain = new Captain(); + captain.setBattleship((BattleFishingBoat) beans.get(BATTLESHIP_BEAN)); + beans.put(CAPTAIN_BEAN, captain); + } - /** - * This test asserts that when we call operateDevice() method on a manager bean, it is internally - * calling operateDevice method on the engineer object. The Adapter ({@link GnomeEngineer}) - * converts the interface of the target class ( {@link GoblinGlider}) into a suitable one expected - * by the client ({@link GnomeEngineeringManager} ). - */ - @Test - public void testAdapter() { - Engineer manager = (Engineer) beans.get(MANAGER_BEAN); + /** + * This test asserts that when we use the move() method on a captain + * bean(client), it is internally calling move method on the battleship + * object. The Adapter ({@link BattleFishingBoat}) converts the interface of + * the target class ( {@link FishingBoat}) into a suitable one expected by + * the client ({@link Captain} ). + */ + @Test + public void testAdapter() { + BattleShip captain = (BattleShip) beans.get(CAPTAIN_BEAN); - // when manager is asked to operate device - manager.operateDevice(); + // when captain moves + captain.move(); - // Manager internally calls the engineer object to operateDevice - Engineer engineer = (Engineer) beans.get(ENGINEER_BEAN); - verify(engineer).operateDevice(); - } + // the captain internally calls the battleship object to move + BattleShip battleship = (BattleShip) beans.get(BATTLESHIP_BEAN); + verify(battleship).move(); + + // same with above with firing + captain.fire(); + verify(battleship).fire(); + + } } From 33b41f872e0d7023a8f2ccd6cf21b85cd2f9f27f Mon Sep 17 00:00:00 2001 From: JuhoKang Date: Wed, 2 Dec 2015 18:45:08 +0900 Subject: [PATCH 004/112] The new java files was not added.. #292 --- .../iluwatar/adapter/BattleFishingBoat.java | 29 ++++++++++++++++ .../java/com/iluwatar/adapter/BattleShip.java | 14 ++++++++ .../java/com/iluwatar/adapter/Captain.java | 33 +++++++++++++++++++ .../com/iluwatar/adapter/FishingBoat.java | 18 ++++++++++ 4 files changed, 94 insertions(+) create mode 100644 adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java create mode 100644 adapter/src/main/java/com/iluwatar/adapter/BattleShip.java create mode 100644 adapter/src/main/java/com/iluwatar/adapter/Captain.java create mode 100644 adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java new file mode 100644 index 000000000..ffd73de3a --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java @@ -0,0 +1,29 @@ +package com.iluwatar.adapter; + +/** + * + * Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link BattleShip} + * interface expected by the client ({@link Captain}).
+ * In this case we added a new function fire to suit the interface. We are reusing the + * {@link FishingBoat} without changing itself. The Adapter class can just map the functions of the + * Adaptee or add, delete features of the Adaptee. + * + */ +public class BattleFishingBoat implements BattleShip { + + private FishingBoat boat; + + public BattleFishingBoat() { + boat = new FishingBoat(); + } + + @Override + public void fire() { + System.out.println("fire!"); + } + + @Override + public void move() { + boat.sail(); + } +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java new file mode 100644 index 000000000..90b18f758 --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java @@ -0,0 +1,14 @@ +package com.iluwatar.adapter; + +/** + * The interface expected by the client.
+ * A Battleship can fire and move. + * + */ +public interface BattleShip { + + void fire(); + + void move(); + +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/Captain.java b/adapter/src/main/java/com/iluwatar/adapter/Captain.java new file mode 100644 index 000000000..8c48daf69 --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/Captain.java @@ -0,0 +1,33 @@ +package com.iluwatar.adapter; + +/** + * The Captain uses {@link BattleShip} to fight.
+ * This is the client in the pattern. + */ +public class Captain implements BattleShip { + + private BattleShip battleship; + + public Captain() { + + } + + public Captain(BattleShip battleship) { + this.battleship = battleship; + } + + public void setBattleship(BattleShip battleship) { + this.battleship = battleship; + } + + @Override + public void fire() { + battleship.fire(); + } + + @Override + public void move() { + battleship.move(); + } + +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java new file mode 100644 index 000000000..d2f9dae25 --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java @@ -0,0 +1,18 @@ +package com.iluwatar.adapter; + +/** + * + * Device class (adaptee in the pattern). We want to reuse this class + * + */ +public class FishingBoat { + + public void sail() { + System.out.println("The Boat is moving to that place"); + } + + public void fish() { + System.out.println("fishing ..."); + } + +} From f018d13c39c2d76b950d5a2c7f581a414245e2d0 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Wed, 2 Dec 2015 23:21:44 +0200 Subject: [PATCH 005/112] Set version number for monthly release --- abstract-factory/pom.xml | 2 +- adapter/pom.xml | 2 +- async-method-invocation/pom.xml | 2 +- bridge/pom.xml | 2 +- builder/pom.xml | 2 +- business-delegate/pom.xml | 2 +- caching/pom.xml | 2 +- callback/pom.xml | 2 +- chain/pom.xml | 2 +- command/pom.xml | 2 +- composite/pom.xml | 2 +- dao/pom.xml | 2 +- decorator/pom.xml | 2 +- dependency-injection/pom.xml | 2 +- double-checked-locking/pom.xml | 2 +- double-dispatch/pom.xml | 2 +- event-aggregator/pom.xml | 2 +- execute-around/pom.xml | 2 +- facade/pom.xml | 2 +- factory-method/pom.xml | 2 +- fluentinterface/pom.xml | 2 +- flux/pom.xml | 2 +- flyweight/pom.xml | 2 +- front-controller/pom.xml | 2 +- half-sync-half-async/pom.xml | 2 +- intercepting-filter/pom.xml | 2 +- interpreter/pom.xml | 2 +- iterator/pom.xml | 2 +- layers/pom.xml | 2 +- lazy-loading/pom.xml | 2 +- mediator/pom.xml | 2 +- memento/pom.xml | 2 +- message-channel/pom.xml | 2 +- model-view-controller/pom.xml | 2 +- model-view-presenter/pom.xml | 2 +- monostate/pom.xml | 2 +- multiton/pom.xml | 2 +- naked-objects/dom/pom.xml | 2 +- naked-objects/fixture/pom.xml | 2 +- naked-objects/integtests/pom.xml | 2 +- naked-objects/pom.xml | 8 ++++---- naked-objects/webapp/pom.xml | 2 +- null-object/pom.xml | 2 +- object-pool/pom.xml | 2 +- observer/pom.xml | 2 +- poison-pill/pom.xml | 2 +- pom.xml | 2 +- private-class-data/pom.xml | 2 +- producer-consumer/pom.xml | 2 +- property/pom.xml | 2 +- prototype/pom.xml | 2 +- proxy/pom.xml | 2 +- publish-subscribe/pom.xml | 2 +- reactor/pom.xml | 2 +- repository/pom.xml | 2 +- resource-acquisition-is-initialization/pom.xml | 2 +- servant/pom.xml | 2 +- service-layer/pom.xml | 2 +- service-locator/pom.xml | 2 +- singleton/pom.xml | 2 +- specification/pom.xml | 2 +- state/pom.xml | 2 +- step-builder/pom.xml | 2 +- strategy/pom.xml | 2 +- template-method/pom.xml | 2 +- thread-pool/pom.xml | 2 +- tolerant-reader/pom.xml | 2 +- twin/pom.xml | 2 +- visitor/pom.xml | 2 +- 69 files changed, 72 insertions(+), 72 deletions(-) diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index f8c7fa106..6e0055db5 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 abstract-factory diff --git a/adapter/pom.xml b/adapter/pom.xml index ddb81441f..52a5cef43 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 adapter diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index 87dd343ac..3853ea933 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 async-method-invocation diff --git a/bridge/pom.xml b/bridge/pom.xml index c17b482a5..644fa7ad2 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 bridge diff --git a/builder/pom.xml b/builder/pom.xml index f26494b2e..a6a599ccd 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index d07f2c0ae..64ef756eb 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 business-delegate diff --git a/caching/pom.xml b/caching/pom.xml index e61b8ab8c..32729861d 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 caching diff --git a/callback/pom.xml b/callback/pom.xml index dc12efb66..3149fd213 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 callback diff --git a/chain/pom.xml b/chain/pom.xml index 1c044f7e1..eb204c866 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 chain diff --git a/command/pom.xml b/command/pom.xml index 6001ebc33..2a2a678f5 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 command diff --git a/composite/pom.xml b/composite/pom.xml index 155108064..bab87ed6d 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 composite diff --git a/dao/pom.xml b/dao/pom.xml index 3134dad96..2e4bab053 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 dao diff --git a/decorator/pom.xml b/decorator/pom.xml index 044037688..42197b943 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 decorator diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index b05451afa..2266d2521 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 dependency-injection diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index a9c0f220b..fade078eb 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -3,7 +3,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 290ddb68b..32089a7b5 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 double-dispatch diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index d5001f992..eeabcc786 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -4,7 +4,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 event-aggregator diff --git a/execute-around/pom.xml b/execute-around/pom.xml index dae6a4dad..fb0d1a91b 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 execute-around diff --git a/facade/pom.xml b/facade/pom.xml index 4447cc03b..ea7914caa 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 facade diff --git a/factory-method/pom.xml b/factory-method/pom.xml index 97c1c5681..a20fbf5ba 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 factory-method diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 48ec08161..9b4aa1d57 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -5,7 +5,7 @@ java-design-patterns com.iluwatar - 1.8.0-SNAPSHOT + 1.8.0 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index 28a634ceb..39142cbef 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 flux diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 3aa89d15c..2ad8fb725 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 5b0ef2155..32dc2dbca 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 front-controller diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index e7a27c321..17ad3d791 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 half-sync-half-async diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 1f1d89e96..041f4a500 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 863a00199..bf85b2d08 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index 258c1e3ee..02a99d1f2 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 iterator diff --git a/layers/pom.xml b/layers/pom.xml index e338a557f..9bb03250d 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index eafc0f559..de587d302 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 lazy-loading diff --git a/mediator/pom.xml b/mediator/pom.xml index 60999c5aa..da00bb736 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 mediator diff --git a/memento/pom.xml b/memento/pom.xml index 08d5c3a02..e488d035b 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 memento diff --git a/message-channel/pom.xml b/message-channel/pom.xml index 0c34678a6..b432e7ce0 100644 --- a/message-channel/pom.xml +++ b/message-channel/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 message-channel diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 0f4539747..064a82089 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 09410afc6..2f8a18e48 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 model-view-presenter model-view-presenter diff --git a/monostate/pom.xml b/monostate/pom.xml index 7531263f0..7ba3485f1 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index 4cbb326e8..8d76a4f8c 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 multiton diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index bd71db272..3c1ee8f91 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0-SNAPSHOT + 1.8.0 naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 057bbb9ff..e4267321d 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0-SNAPSHOT + 1.8.0 naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index 78819358a..1e3c28e31 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0-SNAPSHOT + 1.8.0 naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index aad8a360d..604bfcb7e 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.8.0-SNAPSHOT + 1.8.0 naked-objects @@ -350,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.8.0-SNAPSHOT + 1.8.0 ${project.groupId} naked-objects-fixture - 1.8.0-SNAPSHOT + 1.8.0 ${project.groupId} naked-objects-webapp - 1.8.0-SNAPSHOT + 1.8.0 diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index 4935bd3ef..c091d4d2d 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0-SNAPSHOT + 1.8.0 naked-objects-webapp diff --git a/null-object/pom.xml b/null-object/pom.xml index 597dad233..1337a8d8a 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 null-object diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 75bc894e8..2abf85d3d 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 object-pool diff --git a/observer/pom.xml b/observer/pom.xml index a3dd25d85..2eacdd8a0 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 observer diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 340445414..e0a317121 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 poison-pill diff --git a/pom.xml b/pom.xml index e6603b06c..db6d47e5d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 pom diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index 362e061f1..07f710c4b 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 571272102..feec05f9b 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 producer-consumer diff --git a/property/pom.xml b/property/pom.xml index b6d10bdb0..4982f7232 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 property diff --git a/prototype/pom.xml b/prototype/pom.xml index c08e79558..d603a185c 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 prototype diff --git a/proxy/pom.xml b/proxy/pom.xml index 0bb88bb79..fc1ce04e9 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 proxy diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index 07d704719..316feba89 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -4,7 +4,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 publish-subscribe diff --git a/reactor/pom.xml b/reactor/pom.xml index c60e8cf98..ec24caad2 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 reactor diff --git a/repository/pom.xml b/repository/pom.xml index c3adc7a92..565316134 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index 4b0b2cadb..72c9bfa8d 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 resource-acquisition-is-initialization diff --git a/servant/pom.xml b/servant/pom.xml index 348905d24..14fcfc456 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 servant diff --git a/service-layer/pom.xml b/service-layer/pom.xml index b188ba1d7..7dfe03266 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index f04f9199e..bd9f88e90 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 service-locator diff --git a/singleton/pom.xml b/singleton/pom.xml index de316c34c..2b0dee12a 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 singleton diff --git a/specification/pom.xml b/specification/pom.xml index bf69e481e..07de26691 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 specification diff --git a/state/pom.xml b/state/pom.xml index 2bd9d9168..45338b278 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index d31192323..d0d369281 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -6,7 +6,7 @@ java-design-patterns com.iluwatar - 1.8.0-SNAPSHOT + 1.8.0 step-builder diff --git a/strategy/pom.xml b/strategy/pom.xml index 4b4448ffe..66120a687 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 strategy diff --git a/template-method/pom.xml b/template-method/pom.xml index ecc0c4efa..689827514 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index f79388008..745b9c0ab 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 thread-pool diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index d32006ed7..eeaba2d9a 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 tolerant-reader diff --git a/twin/pom.xml b/twin/pom.xml index c2a4b131b..dd38bf15c 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 twin diff --git a/visitor/pom.xml b/visitor/pom.xml index b33f9975b..f9f7327a8 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.8.0 visitor From e709a196bdcc0edd60e1d1cd136c7f92a7f68379 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Wed, 2 Dec 2015 23:26:07 +0200 Subject: [PATCH 006/112] Set version number for next development iteration --- abstract-factory/pom.xml | 2 +- adapter/pom.xml | 2 +- async-method-invocation/pom.xml | 2 +- bridge/pom.xml | 2 +- builder/pom.xml | 2 +- business-delegate/pom.xml | 2 +- caching/pom.xml | 2 +- callback/pom.xml | 2 +- chain/pom.xml | 2 +- command/pom.xml | 2 +- composite/pom.xml | 2 +- dao/pom.xml | 2 +- decorator/pom.xml | 2 +- dependency-injection/pom.xml | 2 +- double-checked-locking/pom.xml | 2 +- double-dispatch/pom.xml | 2 +- event-aggregator/pom.xml | 2 +- execute-around/pom.xml | 2 +- facade/pom.xml | 2 +- factory-method/pom.xml | 2 +- fluentinterface/pom.xml | 2 +- flux/pom.xml | 2 +- flyweight/pom.xml | 2 +- front-controller/pom.xml | 2 +- half-sync-half-async/pom.xml | 2 +- intercepting-filter/pom.xml | 2 +- interpreter/pom.xml | 2 +- iterator/pom.xml | 2 +- layers/pom.xml | 2 +- lazy-loading/pom.xml | 2 +- mediator/pom.xml | 2 +- memento/pom.xml | 2 +- message-channel/pom.xml | 2 +- model-view-controller/pom.xml | 2 +- model-view-presenter/pom.xml | 2 +- monostate/pom.xml | 2 +- multiton/pom.xml | 2 +- naked-objects/dom/pom.xml | 2 +- naked-objects/fixture/pom.xml | 2 +- naked-objects/integtests/pom.xml | 2 +- naked-objects/pom.xml | 8 ++++---- naked-objects/webapp/pom.xml | 2 +- null-object/pom.xml | 2 +- object-pool/pom.xml | 2 +- observer/pom.xml | 2 +- poison-pill/pom.xml | 2 +- pom.xml | 2 +- private-class-data/pom.xml | 2 +- producer-consumer/pom.xml | 2 +- property/pom.xml | 2 +- prototype/pom.xml | 2 +- proxy/pom.xml | 2 +- publish-subscribe/pom.xml | 2 +- reactor/pom.xml | 2 +- repository/pom.xml | 2 +- resource-acquisition-is-initialization/pom.xml | 2 +- servant/pom.xml | 2 +- service-layer/pom.xml | 2 +- service-locator/pom.xml | 2 +- singleton/pom.xml | 2 +- specification/pom.xml | 2 +- state/pom.xml | 2 +- step-builder/pom.xml | 2 +- strategy/pom.xml | 2 +- template-method/pom.xml | 2 +- thread-pool/pom.xml | 2 +- tolerant-reader/pom.xml | 2 +- twin/pom.xml | 2 +- visitor/pom.xml | 2 +- 69 files changed, 72 insertions(+), 72 deletions(-) diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 6e0055db5..1c1e40229 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT abstract-factory diff --git a/adapter/pom.xml b/adapter/pom.xml index 52a5cef43..2b67e4d53 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT adapter diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index 3853ea933..be6aa3bca 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT async-method-invocation diff --git a/bridge/pom.xml b/bridge/pom.xml index 644fa7ad2..db2f0d340 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT bridge diff --git a/builder/pom.xml b/builder/pom.xml index a6a599ccd..7838160f5 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 64ef756eb..128738fbc 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT business-delegate diff --git a/caching/pom.xml b/caching/pom.xml index 32729861d..ab6a56ed3 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT caching diff --git a/callback/pom.xml b/callback/pom.xml index 3149fd213..91f131f43 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT callback diff --git a/chain/pom.xml b/chain/pom.xml index eb204c866..d1136420e 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT chain diff --git a/command/pom.xml b/command/pom.xml index 2a2a678f5..cc21f7f56 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT command diff --git a/composite/pom.xml b/composite/pom.xml index bab87ed6d..32c4d2934 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT composite diff --git a/dao/pom.xml b/dao/pom.xml index 2e4bab053..c0cd83be1 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT dao diff --git a/decorator/pom.xml b/decorator/pom.xml index 42197b943..ab15f0e01 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT decorator diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index 2266d2521..40970e130 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT dependency-injection diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index fade078eb..7ad651339 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -3,7 +3,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 32089a7b5..bc78a8a31 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT double-dispatch diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index eeabcc786..62c6adf14 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -4,7 +4,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT event-aggregator diff --git a/execute-around/pom.xml b/execute-around/pom.xml index fb0d1a91b..dd46f59cd 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT execute-around diff --git a/facade/pom.xml b/facade/pom.xml index ea7914caa..ea51c2138 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT facade diff --git a/factory-method/pom.xml b/factory-method/pom.xml index a20fbf5ba..23ef0e774 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT factory-method diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 9b4aa1d57..d549d5216 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -5,7 +5,7 @@ java-design-patterns com.iluwatar - 1.8.0 + 1.9.0-SNAPSHOT 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index 39142cbef..3b06d299c 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT flux diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 2ad8fb725..e00f55e52 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 32dc2dbca..33a30c258 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT front-controller diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 17ad3d791..2490e9214 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT half-sync-half-async diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 041f4a500..c69f40ee5 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index bf85b2d08..8e51c2ecb 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index 02a99d1f2..6f8cd993a 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT iterator diff --git a/layers/pom.xml b/layers/pom.xml index 9bb03250d..23b1db192 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index de587d302..044211ab6 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT lazy-loading diff --git a/mediator/pom.xml b/mediator/pom.xml index da00bb736..0e9bff5d1 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT mediator diff --git a/memento/pom.xml b/memento/pom.xml index e488d035b..0765300c9 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT memento diff --git a/message-channel/pom.xml b/message-channel/pom.xml index b432e7ce0..a558f40a3 100644 --- a/message-channel/pom.xml +++ b/message-channel/pom.xml @@ -6,7 +6,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT message-channel diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 064a82089..8e5d3d9e2 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 2f8a18e48..556f45cf5 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT model-view-presenter model-view-presenter diff --git a/monostate/pom.xml b/monostate/pom.xml index 7ba3485f1..2f253084d 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index 8d76a4f8c..96a80b5f4 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT multiton diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 3c1ee8f91..60c2043d1 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0 + 1.9.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index e4267321d..50839c54b 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0 + 1.9.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index 1e3c28e31..e0c14547f 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0 + 1.9.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index 604bfcb7e..7e8714ce8 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.8.0 + 1.9.0-SNAPSHOT naked-objects @@ -350,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.8.0 + 1.9.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.8.0 + 1.9.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.8.0 + 1.9.0-SNAPSHOT diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index c091d4d2d..71d207b70 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.8.0 + 1.9.0-SNAPSHOT naked-objects-webapp diff --git a/null-object/pom.xml b/null-object/pom.xml index 1337a8d8a..1ffb57320 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT null-object diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 2abf85d3d..c1ea55d7b 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT object-pool diff --git a/observer/pom.xml b/observer/pom.xml index 2eacdd8a0..681c19571 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT observer diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index e0a317121..0d7689b65 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index db6d47e5d..9fa150dd4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT pom diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index 07f710c4b..cced926fc 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index feec05f9b..518ef94db 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT producer-consumer diff --git a/property/pom.xml b/property/pom.xml index 4982f7232..0df1fb258 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT property diff --git a/prototype/pom.xml b/prototype/pom.xml index d603a185c..5e91880a6 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT prototype diff --git a/proxy/pom.xml b/proxy/pom.xml index fc1ce04e9..3a662b37a 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT proxy diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index 316feba89..1d5c0501d 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -4,7 +4,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT publish-subscribe diff --git a/reactor/pom.xml b/reactor/pom.xml index ec24caad2..1d450bcc8 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT reactor diff --git a/repository/pom.xml b/repository/pom.xml index 565316134..90056ab0c 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index 72c9bfa8d..133c7f3c1 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/servant/pom.xml b/servant/pom.xml index 14fcfc456..19d58490d 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT servant diff --git a/service-layer/pom.xml b/service-layer/pom.xml index 7dfe03266..b0a57cf5b 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index bd9f88e90..5ccef1fe2 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT service-locator diff --git a/singleton/pom.xml b/singleton/pom.xml index 2b0dee12a..36d326504 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT singleton diff --git a/specification/pom.xml b/specification/pom.xml index 07de26691..8c79fa9e6 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT specification diff --git a/state/pom.xml b/state/pom.xml index 45338b278..8aa1ae812 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index d0d369281..a2a7462c8 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -6,7 +6,7 @@ java-design-patterns com.iluwatar - 1.8.0 + 1.9.0-SNAPSHOT step-builder diff --git a/strategy/pom.xml b/strategy/pom.xml index 66120a687..c1668277a 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT strategy diff --git a/template-method/pom.xml b/template-method/pom.xml index 689827514..482a7c5ca 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index 745b9c0ab..c50140237 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT thread-pool diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index eeaba2d9a..2d8b26ca6 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT tolerant-reader diff --git a/twin/pom.xml b/twin/pom.xml index dd38bf15c..95e942493 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT twin diff --git a/visitor/pom.xml b/visitor/pom.xml index f9f7327a8..c51b4a7fe 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -5,7 +5,7 @@ com.iluwatar java-design-patterns - 1.8.0 + 1.9.0-SNAPSHOT visitor From 507b89d5e44c2aa46cd8aba894817c83a67d17c9 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sat, 5 Dec 2015 21:26:30 +0200 Subject: [PATCH 007/112] Apply project coding conventions to Repository example --- .../java/com/iluwatar/repository/App.java | 7 +- .../com/iluwatar/repository/AppConfig.java | 193 +++++++++--------- .../java/com/iluwatar/repository/Person.java | 4 +- .../repository/PersonSpecifications.java | 2 +- .../AnnotationBasedRepositoryTest.java | 4 +- .../iluwatar/repository/AppConfigTest.java | 57 +++--- .../iluwatar/repository/RepositoryTest.java | 3 +- 7 files changed, 138 insertions(+), 132 deletions(-) diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java index 2442c854c..9c940b36d 100644 --- a/repository/src/main/java/com/iluwatar/repository/App.java +++ b/repository/src/main/java/com/iluwatar/repository/App.java @@ -24,12 +24,13 @@ public class App { /** * Program entry point * - * @param args command line args + * @param args + * command line args */ public static void main(String[] args) { - ClassPathXmlApplicationContext context = - new ClassPathXmlApplicationContext("applicationContext.xml"); + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "applicationContext.xml"); PersonRepository repository = context.getBean(PersonRepository.class); Person peter = new Person("Peter", "Sagan", 17); diff --git a/repository/src/main/java/com/iluwatar/repository/AppConfig.java b/repository/src/main/java/com/iluwatar/repository/AppConfig.java index eceb13637..cca09d8aa 100644 --- a/repository/src/main/java/com/iluwatar/repository/AppConfig.java +++ b/repository/src/main/java/com/iluwatar/repository/AppConfig.java @@ -15,117 +15,122 @@ import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; /** - * Annotations based configuration for Spring + * This is the same example as in {@link App} but with annotations based + * configuration for Spring. * */ @EnableJpaRepositories public class AppConfig { - /** - * Creation of H2 db - * - * @return A new Instance of DataSource - */ - @Bean(destroyMethod = "close") - public DataSource dataSource() { - BasicDataSource basicDataSource = new BasicDataSource(); - basicDataSource.setDriverClassName("org.h2.Driver"); - basicDataSource.setUrl("jdbc:h2:~/databases/person"); - basicDataSource.setUsername("sa"); - basicDataSource.setPassword("sa"); - return (DataSource) basicDataSource; - } + /** + * Creation of H2 db + * + * @return A new Instance of DataSource + */ + @Bean(destroyMethod = "close") + public DataSource dataSource() { + BasicDataSource basicDataSource = new BasicDataSource(); + basicDataSource.setDriverClassName("org.h2.Driver"); + basicDataSource.setUrl("jdbc:h2:~/databases/person"); + basicDataSource.setUsername("sa"); + basicDataSource.setPassword("sa"); + return (DataSource) basicDataSource; + } - /** - * Factory to create a especific instance of Entity Manager - * @return - */ - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); - entityManager.setDataSource(dataSource()); - entityManager.setPackagesToScan("com.iluwatar"); - entityManager.setPersistenceProvider(new HibernatePersistenceProvider()); - entityManager.setJpaProperties(jpaProperties()); + /** + * Factory to create a especific instance of Entity Manager + * + * @return + */ + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); + entityManager.setDataSource(dataSource()); + entityManager.setPackagesToScan("com.iluwatar"); + entityManager.setPersistenceProvider(new HibernatePersistenceProvider()); + entityManager.setJpaProperties(jpaProperties()); - return entityManager; - } + return entityManager; + } - /** - * Properties for Jpa - * @return - */ - private Properties jpaProperties() { - Properties properties = new Properties(); - properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); - properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); - return properties; - } - - @Bean - public JpaTransactionManager transactionManager() throws SQLException { - JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return transactionManager; + /** + * Properties for Jpa + * + * @return + */ + private Properties jpaProperties() { + Properties properties = new Properties(); + properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); + return properties; + } + + @Bean + public JpaTransactionManager transactionManager() throws SQLException { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + /** + * Program entry point + * + * @param args + * command line args + */ + public static void main(String[] args) { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + AppConfig.class); + PersonRepository repository = context.getBean(PersonRepository.class); + + Person peter = new Person("Peter", "Sagan", 17); + Person nasta = new Person("Nasta", "Kuzminova", 25); + Person john = new Person("John", "lawrence", 35); + Person terry = new Person("Terry", "Law", 36); + + // Add new Person records + repository.save(peter); + repository.save(nasta); + repository.save(john); + repository.save(terry); + + // Count Person records + System.out.println("Count Person records: " + repository.count()); + + // Print all records + List persons = (List) repository.findAll(); + for (Person person : persons) { + System.out.println(person); } - - /** - * Program entry point - * - * @param args command line args - */ - public static void main(String[] args) { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); - PersonRepository repository = context.getBean(PersonRepository.class); + // Update Person + nasta.setName("Barbora"); + nasta.setSurname("Spotakova"); + repository.save(nasta); - Person peter = new Person("Peter", "Sagan", 17); - Person nasta = new Person("Nasta", "Kuzminova", 25); - Person john = new Person("John", "lawrence", 35); - Person terry = new Person("Terry", "Law", 36); + System.out.println("Find by id 2: " + repository.findOne(2L)); - // Add new Person records - repository.save(peter); - repository.save(nasta); - repository.save(john); - repository.save(terry); + // Remove record from Person + repository.delete(2L); - // Count Person records - System.out.println("Count Person records: " + repository.count()); + // count records + System.out.println("Count Person records: " + repository.count()); - // Print all records - List persons = (List) repository.findAll(); - for (Person person : persons) { - System.out.println(person); - } + // find by name + Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); + System.out.println("Find by John is " + p); - // Update Person - nasta.setName("Barbora"); - nasta.setSurname("Spotakova"); - repository.save(nasta); + // find by age + persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - System.out.println("Find by id 2: " + repository.findOne(2L)); + System.out.println("Find Person with age between 20,40: "); + for (Person person : persons) { + System.out.println(person); + } - // Remove record from Person - repository.delete(2L); + context.close(); - // count records - System.out.println("Count Person records: " + repository.count()); - - // find by name - Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); - System.out.println("Find by John is " + p); - - // find by age - persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - - System.out.println("Find Person with age between 20,40: "); - for (Person person : persons) { - System.out.println(person); - } - - context.close(); - - } + } } diff --git a/repository/src/main/java/com/iluwatar/repository/Person.java b/repository/src/main/java/com/iluwatar/repository/Person.java index 57439b8c0..ca4013b54 100644 --- a/repository/src/main/java/com/iluwatar/repository/Person.java +++ b/repository/src/main/java/com/iluwatar/repository/Person.java @@ -20,7 +20,8 @@ public class Person { private int age; - public Person() {} + public Person() { + } public Person(String name, String surname, int age) { this.name = name; @@ -52,7 +53,6 @@ public class Person { this.surname = surname; } - public int getAge() { return age; } diff --git a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java index dadaae36b..ce9842dff 100644 --- a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java +++ b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java @@ -31,6 +31,7 @@ public class PersonSpecifications { } } + public static class NameEqualSpec implements Specification { public String name; @@ -47,4 +48,3 @@ public class PersonSpecifications { } } - diff --git a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java index 5e4cf8021..6f8746aa6 100644 --- a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java +++ b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java @@ -22,9 +22,10 @@ import com.google.common.collect.Lists; /** * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query * by {@link org.springframework.data.jpa.domain.Specification} are also test. + * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { AppConfig.class}, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = { AppConfig.class }, loader = AnnotationConfigContextLoader.class) public class AnnotationBasedRepositoryTest { @Resource @@ -107,4 +108,3 @@ public class AnnotationBasedRepositoryTest { } } - diff --git a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java index 5f74f2be7..49e684bf1 100644 --- a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java +++ b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java @@ -20,35 +20,36 @@ import org.springframework.transaction.annotation.Transactional; * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { AppConfig.class}, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = { AppConfig.class }, loader = AnnotationConfigContextLoader.class) public class AppConfigTest { - @Autowired - DataSource dataSource; - - /** - * Test for bean instance - */ - @Test - public void testDataSource() { - assertNotNull(dataSource); - } - - /** - * Test for correct query execution - * @throws SQLException - */ - @Test - @Transactional - public void testQuery() throws SQLException{ - ResultSet resultSet = dataSource.getConnection().createStatement().executeQuery("SELECT 1"); - String result = null; - String expected = "1"; - while (resultSet.next()) { - result = resultSet.getString(1); - - } - assertTrue(result.equals(expected)); - } + @Autowired + DataSource dataSource; + + /** + * Test for bean instance + */ + @Test + public void testDataSource() { + assertNotNull(dataSource); + } + + /** + * Test for correct query execution + * + * @throws SQLException + */ + @Test + @Transactional + public void testQuery() throws SQLException { + ResultSet resultSet = dataSource.getConnection().createStatement().executeQuery("SELECT 1"); + String result = null; + String expected = "1"; + while (resultSet.next()) { + result = resultSet.getString(1); + + } + assertTrue(result.equals(expected)); + } } diff --git a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java index 26689321a..3d6708815 100644 --- a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java +++ b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java @@ -23,7 +23,7 @@ import com.google.common.collect.Lists; * by {@link org.springframework.data.jpa.domain.Specification} are also test. */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) +@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) public class RepositoryTest { @Resource @@ -106,4 +106,3 @@ public class RepositoryTest { } } - From 1884df525b3a8b52c86309afa5c5d85c339f9f07 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 6 Dec 2015 13:43:01 +0100 Subject: [PATCH 008/112] Add proper unit tests for async-method-invocation #293 --- async-method-invocation/pom.xml | 5 + .../invocation/ThreadAsyncExecutorTest.java | 301 ++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index be6aa3bca..de81eb0b7 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java new file mode 100644 index 000000000..7db0abfce --- /dev/null +++ b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java @@ -0,0 +1,301 @@ +package com.iluwatar.async.method.invocation; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Matchers; + +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/6/15 - 10:49 AM + * + * @author Jeroen Meulemeester + */ +public class ThreadAsyncExecutorTest { + + /** + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} + */ + @Test(timeout = 3000) + public void testSuccessfulTaskWithoutCallback() throws Exception { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenReturn(result); + + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + asyncResult.await(); // Prevent timing issues, and wait until the result is available + assertTrue(asyncResult.isCompleted()); + + // Our task should only execute once ... + verify(task, times(1)).call(); + + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } + + /** + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} + */ + @Test(timeout = 3000) + public void testSuccessfulTaskWithCallback() throws Exception { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenReturn(result); + + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(task, callback); + assertNotNull(asyncResult); + asyncResult.await(); // Prevent timing issues, and wait until the result is available + assertTrue(asyncResult.isCompleted()); + + // Our task should only execute once ... + verify(task, times(1)).call(); + + // ... same for the callback, we expect our object + final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); + verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); + + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertFalse(optionalException.isPresent()); + + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } + + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); + + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); + + try { + asyncResult.getValue(); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } + + // Our task should only execute once, but it can take a while ... + verify(task, timeout(3000).times(1)).call(); + + // Prevent timing issues, and wait until the result is available + asyncResult.await(); + assertTrue(asyncResult.isCompleted()); + verifyNoMoreInteractions(task); + + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } + + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); + + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(task, callback); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); + + verifyZeroInteractions(callback); + + try { + asyncResult.getValue(); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } + + // Our task should only execute once, but it can take a while ... + verify(task, timeout(3000).times(1)).call(); + + final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); + verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); + + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertFalse(optionalException.isPresent()); + + // Prevent timing issues, and wait until the result is available + asyncResult.await(); + assertTrue(asyncResult.isCompleted()); + verifyNoMoreInteractions(task, callback); + + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } + + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); + + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); + + try { + asyncResult.getValue(); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } + + assertSame(result, executor.endProcess(asyncResult)); + verify(task, times(1)).call(); + assertTrue(asyncResult.isCompleted()); + + // Calling end process a second time while already finished should give the same result + assertSame(result, executor.endProcess(asyncResult)); + verifyNoMoreInteractions(task); + } + + /** + * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} + * when the callable is 'null' + */ + @Test(timeout = 3000) + public void testNullTask() throws Exception { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncResult asyncResult = executor.startProcess(null); + + 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()); + + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } + + } + + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(null, callback); + + 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> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); + verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); + + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertTrue(optionalException.isPresent()); + + final Exception exception = optionalException.get(); + assertNotNull(exception); + assertEquals(NullPointerException.class, exception.getClass()); + + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } + + } + + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncResult asyncResult = executor.startProcess(null, null); + + 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()); + + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } + + } + +} \ No newline at end of file From 6c1f025d0fe524c417616155747c02f6be08fce0 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sun, 6 Dec 2015 21:42:06 +0200 Subject: [PATCH 009/112] Apply code formatting rules to async-method-invocation example tests --- .../invocation/ThreadAsyncExecutorTest.java | 451 +++++++++--------- 1 file changed, 233 insertions(+), 218 deletions(-) diff --git a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java index 7db0abfce..440e47552 100644 --- a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java +++ b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java @@ -30,272 +30,287 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; */ public class ThreadAsyncExecutorTest { - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} - */ - @Test(timeout = 3000) - public void testSuccessfulTaskWithoutCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + /** + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} + */ + @Test(timeout = 3000) + public void testSuccessfulTaskWithoutCallback() throws Exception { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenReturn(result); + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenReturn(result); - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + asyncResult.await(); // Prevent timing issues, and wait until the result is available + assertTrue(asyncResult.isCompleted()); - // Our task should only execute once ... - verify(task, times(1)).call(); + // Our task should only execute once ... + verify(task, times(1)).call(); - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } - /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} - */ - @Test(timeout = 3000) - public void testSuccessfulTaskWithCallback() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + /** + * Test used to verify the happy path of + * {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} + */ + @Test(timeout = 3000) + public void testSuccessfulTaskWithCallback() throws Exception { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenReturn(result); + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenReturn(result); - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(task, callback); - assertNotNull(asyncResult); - asyncResult.await(); // Prevent timing issues, and wait until the result is available - assertTrue(asyncResult.isCompleted()); + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(task, callback); + assertNotNull(asyncResult); + asyncResult.await(); // Prevent timing issues, and wait until the result is available + assertTrue(asyncResult.isCompleted()); - // Our task should only execute once ... - verify(task, times(1)).call(); + // Our task should only execute once ... + verify(task, times(1)).call(); - // ... same for the callback, we expect our object - final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); + // ... same for the callback, we expect our object + final ArgumentCaptor> optionalCaptor = ArgumentCaptor + .forClass((Class) Optional.class); + verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertFalse(optionalException.isPresent()); + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertFalse(optionalException.isPresent()); - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } - /** - * 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 { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } + try { + asyncResult.getValue(); + fail( + "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } - // Our task should only execute once, but it can take a while ... - verify(task, timeout(3000).times(1)).call(); + // Our task should only execute once, but it can take a while ... + verify(task, timeout(3000).times(1)).call(); - // Prevent timing issues, and wait until the result is available - asyncResult.await(); - assertTrue(asyncResult.isCompleted()); - verifyNoMoreInteractions(task); + // Prevent timing issues, and wait until the result is available + asyncResult.await(); + assertTrue(asyncResult.isCompleted()); + verifyNoMoreInteractions(task); - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } - /** - * 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 { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(task, callback); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(task, callback); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); - verifyZeroInteractions(callback); + verifyZeroInteractions(callback); - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } + try { + asyncResult.getValue(); + fail( + "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } - // Our task should only execute once, but it can take a while ... - verify(task, timeout(3000).times(1)).call(); + // Our task should only execute once, but it can take a while ... + verify(task, timeout(3000).times(1)).call(); - final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); + final ArgumentCaptor> optionalCaptor = ArgumentCaptor + .forClass((Class) Optional.class); + verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertFalse(optionalException.isPresent()); + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertFalse(optionalException.isPresent()); - // Prevent timing issues, and wait until the result is available - asyncResult.await(); - assertTrue(asyncResult.isCompleted()); - verifyNoMoreInteractions(task, callback); + // Prevent timing issues, and wait until the result is available + asyncResult.await(); + assertTrue(asyncResult.isCompleted()); + verifyNoMoreInteractions(task, callback); - // ... and the result should be exactly the same object - assertSame(result, asyncResult.getValue()); - } + // ... and the result should be exactly the same object + assertSame(result, asyncResult.getValue()); + } - /** - * 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 { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final Object result = new Object(); - final Callable task = mock(Callable.class); - when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + final Object result = new Object(); + final Callable task = mock(Callable.class); + when(task.call()).thenAnswer(i -> { + Thread.sleep(1500); + return result; + }); - final AsyncResult asyncResult = executor.startProcess(task); - assertNotNull(asyncResult); - assertFalse(asyncResult.isCompleted()); + final AsyncResult asyncResult = executor.startProcess(task); + assertNotNull(asyncResult); + assertFalse(asyncResult.isCompleted()); - try { - asyncResult.getValue(); - fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); - } catch (IllegalStateException e) { - assertNotNull(e.getMessage()); - } + try { + asyncResult.getValue(); + fail( + "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } - assertSame(result, executor.endProcess(asyncResult)); - verify(task, times(1)).call(); - assertTrue(asyncResult.isCompleted()); + assertSame(result, executor.endProcess(asyncResult)); + verify(task, times(1)).call(); + assertTrue(asyncResult.isCompleted()); - // Calling end process a second time while already finished should give the same result - assertSame(result, executor.endProcess(asyncResult)); - verifyNoMoreInteractions(task); - } + // Calling end process a second time while already finished should give the same result + assertSame(result, executor.endProcess(asyncResult)); + verifyNoMoreInteractions(task); + } - /** - * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} - * when the callable is 'null' - */ - @Test(timeout = 3000) - public void testNullTask() throws Exception { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncResult asyncResult = executor.startProcess(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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncResult asyncResult = executor.startProcess(null); - 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()); + 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()); - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } - } + } - /** - * 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 { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncCallback callback = mock(AsyncCallback.class); - final AsyncResult asyncResult = executor.startProcess(null, callback); + /** + * 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncCallback callback = mock(AsyncCallback.class); + final AsyncResult asyncResult = executor.startProcess(null, callback); - 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()); + 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> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); - verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); + final ArgumentCaptor> optionalCaptor = ArgumentCaptor + .forClass((Class) Optional.class); + verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); - final Optional optionalException = optionalCaptor.getValue(); - assertNotNull(optionalException); - assertTrue(optionalException.isPresent()); + final Optional optionalException = optionalCaptor.getValue(); + assertNotNull(optionalException); + assertTrue(optionalException.isPresent()); - final Exception exception = optionalException.get(); - assertNotNull(exception); - assertEquals(NullPointerException.class, exception.getClass()); + final Exception exception = optionalException.get(); + assertNotNull(exception); + assertEquals(NullPointerException.class, exception.getClass()); - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } - } + } - /** - * 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 { - // Instantiate a new executor and start a new 'null' task ... - final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); - final AsyncResult asyncResult = executor.startProcess(null, 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 { + // Instantiate a new executor and start a new 'null' task ... + final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); + final AsyncResult asyncResult = executor.startProcess(null, null); - 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()); + 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()); - try { - asyncResult.getValue(); - fail("Expected ExecutionException with NPE as cause"); - } catch (final ExecutionException e) { - assertNotNull(e.getMessage()); - assertNotNull(e.getCause()); - assertEquals(NullPointerException.class, e.getCause().getClass()); - } + try { + asyncResult.getValue(); + fail("Expected ExecutionException with NPE as cause"); + } catch (final ExecutionException e) { + assertNotNull(e.getMessage()); + assertNotNull(e.getCause()); + assertEquals(NullPointerException.class, e.getCause().getClass()); + } - } + } } \ No newline at end of file From 1fa617d08dd5c7d88fe0264595acd8277fec47a7 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 6 Dec 2015 22:58:16 +0100 Subject: [PATCH 010/112] Add proper unit tests for chain pattern #293 --- .../java/com/iluwatar/chain/OrcCommander.java | 1 + .../java/com/iluwatar/chain/OrcOfficer.java | 1 + .../java/com/iluwatar/chain/OrcSoldier.java | 1 + .../main/java/com/iluwatar/chain/Request.java | 66 +++++++++++++++---- .../java/com/iluwatar/chain/OrcKingTest.java | 37 +++++++++++ 5 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 chain/src/test/java/com/iluwatar/chain/OrcKingTest.java diff --git a/chain/src/main/java/com/iluwatar/chain/OrcCommander.java b/chain/src/main/java/com/iluwatar/chain/OrcCommander.java index 73de1b8b2..6cc495b99 100644 --- a/chain/src/main/java/com/iluwatar/chain/OrcCommander.java +++ b/chain/src/main/java/com/iluwatar/chain/OrcCommander.java @@ -15,6 +15,7 @@ public class OrcCommander extends RequestHandler { public void handleRequest(Request req) { if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) { printHandling(req); + req.markHandled(); } else { super.handleRequest(req); } diff --git a/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java b/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java index 68df3ec6f..e6d68c19c 100644 --- a/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java +++ b/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java @@ -15,6 +15,7 @@ public class OrcOfficer extends RequestHandler { public void handleRequest(Request req) { if (req.getRequestType().equals(RequestType.TORTURE_PRISONER)) { printHandling(req); + req.markHandled(); } else { super.handleRequest(req); } diff --git a/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java b/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java index d96f51702..bd2a8d11d 100644 --- a/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java +++ b/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java @@ -15,6 +15,7 @@ public class OrcSoldier extends RequestHandler { public void handleRequest(Request req) { if (req.getRequestType().equals(RequestType.COLLECT_TAX)) { printHandling(req); + req.markHandled(); } else { super.handleRequest(req); } diff --git a/chain/src/main/java/com/iluwatar/chain/Request.java b/chain/src/main/java/com/iluwatar/chain/Request.java index 0c62cfd43..5c3256a55 100644 --- a/chain/src/main/java/com/iluwatar/chain/Request.java +++ b/chain/src/main/java/com/iluwatar/chain/Request.java @@ -1,38 +1,78 @@ package com.iluwatar.chain; +import java.util.Objects; + /** - * * Request - * */ public class Request { - private String requestDescription; - private RequestType requestType; + /** + * The type of this request, used by each item in the chain to see if they should or can handle + * this particular request + */ + private final RequestType requestType; - public Request(RequestType requestType, String requestDescription) { - this.setRequestType(requestType); - this.setRequestDescription(requestDescription); + /** + * A description of the request + */ + private final String requestDescription; + + /** + * Indicates if the request is handled or not. A request can only switch state from unhandled to + * handled, there's no way to 'unhandle' a request + */ + private boolean handled = false; + + /** + * Create a new request of the given type and accompanied description. + * + * @param requestType The type of request + * @param requestDescription The description of the request + */ + public Request(final RequestType requestType, final String requestDescription) { + this.requestType = Objects.requireNonNull(requestType); + this.requestDescription = Objects.requireNonNull(requestDescription); } + /** + * Get a description of the request + * + * @return A human readable description of the request + */ public String getRequestDescription() { return requestDescription; } - public void setRequestDescription(String requestDescription) { - this.requestDescription = requestDescription; - } - + /** + * Get the type of this request, used by each person in the chain of command to see if they should + * or can handle this particular request + * + * @return The request type + */ public RequestType getRequestType() { return requestType; } - public void setRequestType(RequestType requestType) { - this.requestType = requestType; + /** + * Mark the request as handled + */ + public void markHandled() { + this.handled = true; + } + + /** + * Indicates if this request is handled or not + * + * @return true when the request is handled, false if not + */ + public boolean isHandled() { + return this.handled; } @Override public String toString() { return getRequestDescription(); } + } diff --git a/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java b/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java new file mode 100644 index 000000000..fd3d573b6 --- /dev/null +++ b/chain/src/test/java/com/iluwatar/chain/OrcKingTest.java @@ -0,0 +1,37 @@ +package com.iluwatar.chain; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/6/15 - 9:29 PM + * + * @author Jeroen Meulemeester + */ +public class OrcKingTest { + + /** + * All possible requests + */ + private static final Request[] REQUESTS = new Request[]{ + new Request(RequestType.DEFEND_CASTLE, "Don't let the barbarians enter my castle!!"), + new Request(RequestType.TORTURE_PRISONER, "Don't just stand there, tickle him!"), + new Request(RequestType.COLLECT_TAX, "Don't steal, the King hates competition ..."), + }; + + @Test + public void testMakeRequest() throws Exception { + final OrcKing king = new OrcKing(); + + for (final Request request : REQUESTS) { + king.makeRequest(request); + assertTrue( + "Expected all requests from King to be handled, but [" + request + "] was not!", + request.isHandled() + ); + } + + } + +} \ No newline at end of file From 875e5b872c6f31b6ca616e621446b05cfd0ba7c9 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 6 Dec 2015 23:14:07 +0100 Subject: [PATCH 011/112] Add proper unit tests for builder pattern #293 --- .../java/com/iluwatar/builder/HeroTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 builder/src/test/java/com/iluwatar/builder/HeroTest.java diff --git a/builder/src/test/java/com/iluwatar/builder/HeroTest.java b/builder/src/test/java/com/iluwatar/builder/HeroTest.java new file mode 100644 index 000000000..2bedf3ef1 --- /dev/null +++ b/builder/src/test/java/com/iluwatar/builder/HeroTest.java @@ -0,0 +1,56 @@ +package com.iluwatar.builder; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/6/15 - 11:01 PM + * + * @author Jeroen Meulemeester + */ +public class HeroTest { + + /** + * Test if we get the expected exception when trying to create a hero without a profession + */ + @Test(expected = IllegalArgumentException.class) + public void testMissingProfession() throws Exception { + new Hero.HeroBuilder(null, "Sir without a job"); + } + + /** + * Test if we get the expected exception when trying to create a hero without a name + */ + @Test(expected = IllegalArgumentException.class) + public void testMissingName() throws Exception { + new Hero.HeroBuilder(Profession.THIEF, null); + } + + /** + * Test if the hero build by the builder has the correct attributes, as requested + */ + @Test + public void testBuildHero() throws Exception { + final String heroName = "Sir Lancelot"; + + final Hero hero = new Hero.HeroBuilder(Profession.WARRIOR, heroName) + .withArmor(Armor.CHAIN_MAIL) + .withWeapon(Weapon.SWORD) + .withHairType(HairType.LONG_CURLY) + .withHairColor(HairColor.BLOND) + .build(); + + assertNotNull(hero); + assertNotNull(hero.toString()); + assertEquals(Profession.WARRIOR, hero.getProfession()); + assertEquals(heroName, hero.getName()); + assertEquals(Armor.CHAIN_MAIL, hero.getArmor()); + assertEquals(Weapon.SWORD, hero.getWeapon()); + assertEquals(HairType.LONG_CURLY, hero.getHairType()); + assertEquals(HairColor.BLOND, hero.getHairColor()); + + } + +} \ No newline at end of file From 8367c83aca702025b8124b25009e7ac9d6d2705c Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 6 Dec 2015 23:48:48 +0100 Subject: [PATCH 012/112] Add proper unit tests for bridge pattern #293 --- bridge/pom.xml | 4 ++ .../bridge/BlindingMagicWeaponTest.java | 33 +++++++++++++++ .../bridge/FlyingMagicWeaponTest.java | 33 +++++++++++++++ .../com/iluwatar/bridge/MagicWeaponTest.java | 42 +++++++++++++++++++ .../bridge/SoulEatingMagicWeaponTest.java | 33 +++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java create mode 100644 bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java create mode 100644 bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java create mode 100644 bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java diff --git a/bridge/pom.xml b/bridge/pom.xml index db2f0d340..10b763eab 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -14,5 +14,9 @@ junit test + + org.mockito + mockito-core + diff --git a/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java new file mode 100644 index 000000000..a7a2d1536 --- /dev/null +++ b/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.bridge; + +import org.junit.Test; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/6/15 - 11:15 PM + * + * @author Jeroen Meulemeester + */ +public class BlindingMagicWeaponTest extends MagicWeaponTest { + + /** + * Invoke all possible actions on the weapon and check if the actions are executed on the actual + * underlying weapon implementation. + */ + @Test + public void testExcalibur() throws Exception { + final Excalibur excalibur = spy(new Excalibur()); + final BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(excalibur); + + testBasicWeaponActions(blindingMagicWeapon, excalibur); + + blindingMagicWeapon.blind(); + verify(excalibur, times(1)).blindImp(); + verifyNoMoreInteractions(excalibur); + } + +} diff --git a/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java new file mode 100644 index 000000000..55b89bb36 --- /dev/null +++ b/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.bridge; + +import org.junit.Test; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/6/15 - 11:26 PM + * + * @author Jeroen Meulemeester + */ +public class FlyingMagicWeaponTest extends MagicWeaponTest { + + /** + * Invoke all possible actions on the weapon and check if the actions are executed on the actual + * underlying weapon implementation. + */ + @Test + public void testMjollnir() throws Exception { + final Mjollnir mjollnir = spy(new Mjollnir()); + final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir); + + testBasicWeaponActions(flyingMagicWeapon, mjollnir); + + flyingMagicWeapon.fly(); + verify(mjollnir, times(1)).flyImp(); + verifyNoMoreInteractions(mjollnir); + } + +} \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java new file mode 100644 index 000000000..eb7bfb34e --- /dev/null +++ b/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java @@ -0,0 +1,42 @@ +package com.iluwatar.bridge; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/6/15 - 11:28 PM + * + * @author Jeroen Meulemeester + */ +public abstract class MagicWeaponTest { + + /** + * Invoke the basic actions of the given weapon, and test if the underlying weapon implementation + * is invoked + * + * @param weaponImpl The spied weapon implementation where actions are bridged to + * @param weapon The weapon, handled by the app + */ + protected final void testBasicWeaponActions(final MagicWeapon weapon, + final MagicWeaponImpl weaponImpl) { + assertNotNull(weapon); + assertNotNull(weaponImpl); + assertNotNull(weapon.getImp()); + + weapon.swing(); + verify(weaponImpl, times(1)).swingImp(); + verifyNoMoreInteractions(weaponImpl); + + weapon.wield(); + verify(weaponImpl, times(1)).wieldImp(); + verifyNoMoreInteractions(weaponImpl); + + weapon.unwield(); + verify(weaponImpl, times(1)).unwieldImp(); + verifyNoMoreInteractions(weaponImpl); + + } + +} diff --git a/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java new file mode 100644 index 000000000..2d9c24083 --- /dev/null +++ b/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.bridge; + +import org.junit.Test; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/6/15 - 11:43 PM + * + * @author Jeroen Meulemeester + */ +public class SoulEatingMagicWeaponTest extends MagicWeaponTest { + + /** + * Invoke all possible actions on the weapon and check if the actions are executed on the actual + * underlying weapon implementation. + */ + @Test + public void testStormBringer() throws Exception { + final Stormbringer stormbringer = spy(new Stormbringer()); + final SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(stormbringer); + + testBasicWeaponActions(soulEatingMagicWeapon, stormbringer); + + soulEatingMagicWeapon.eatSoul(); + verify(stormbringer, times(1)).eatSoulImp(); + verifyNoMoreInteractions(stormbringer); + } + +} \ No newline at end of file From e2d8079b36f670de04d5901ed576cc9fe9ea6a3d Mon Sep 17 00:00:00 2001 From: JuhoKang Date: Mon, 7 Dec 2015 10:35:32 +0900 Subject: [PATCH 013/112] Fixed code to follow coding conventions --- .../main/java/com/iluwatar/adapter/App.java | 59 ++++++------ .../iluwatar/adapter/BattleFishingBoat.java | 4 +- .../java/com/iluwatar/adapter/BattleShip.java | 2 +- .../com/iluwatar/adapter/FishingBoat.java | 4 +- .../iluwatar/adapter/AdapterPatternTest.java | 93 +++++++------------ 5 files changed, 66 insertions(+), 96 deletions(-) diff --git a/adapter/src/main/java/com/iluwatar/adapter/App.java b/adapter/src/main/java/com/iluwatar/adapter/App.java index c33780198..d57cb91e4 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/App.java +++ b/adapter/src/main/java/com/iluwatar/adapter/App.java @@ -1,43 +1,38 @@ package com.iluwatar.adapter; /** - * An adapter helps two incompatible interfaces to work together. This is the - * real world definition for an adapter. Interfaces may be incompatible but the - * inner functionality should suit the need. The Adapter design pattern allows - * otherwise incompatible classes to work together by converting the interface - * of one class into an interface expected by the clients. - * + * An adapter helps two incompatible interfaces to work together. This is the real world definition + * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need. + * The Adapter design pattern allows otherwise incompatible classes to work together by converting + * the interface of one class into an interface expected by the clients. + * *

- * There are two variations of the Adapter pattern: The class adapter implements - * the adaptee's interface whereas the object adapter uses composition to - * contain the adaptee in the adapter object. This example uses the object - * adapter approach. - * + * There are two variations of the Adapter pattern: The class adapter implements the adaptee's + * interface whereas the object adapter uses composition to contain the adaptee in the adapter + * object. This example uses the object adapter approach. + * *

- * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee - * class ( {@link FishingBoat}) into a suitable one expected by the client ( - * {@link BattleShip} ). - * + * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee class ( + * {@link FishingBoat}) into a suitable one expected by the client ( {@link BattleShip} ). + * *

* The story of this implementation is this.
- * Pirates are coming! we need a {@link BattleShip} to fight! We have a - * {@link FishingBoat} and our captain. We have no time to make up a new ship! - * we need to reuse this {@link FishingBoat}. The captain needs a battleship - * which can fire and move. The spec is in {@link BattleShip}. We will use the - * Adapter pattern to reuse {@link FishingBoat}. - * + * Pirates are coming! we need a {@link BattleShip} to fight! We have a {@link FishingBoat} and our + * captain. We have no time to make up a new ship! we need to reuse this {@link FishingBoat}. The + * captain needs a battleship which can fire and move. The spec is in {@link BattleShip}. We will + * use the Adapter pattern to reuse {@link FishingBoat}. + * */ public class App { - /** - * Program entry point. - * - * @param args - * command line args - */ - public static void main(String[] args) { - Captain captain = new Captain(new BattleFishingBoat()); - captain.move(); - captain.fire(); - } + /** + * Program entry point. + * + * @param args command line args + */ + public static void main(String[] args) { + Captain captain = new Captain(new BattleFishingBoat()); + captain.move(); + captain.fire(); + } } diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java index ffd73de3a..3f573337f 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java @@ -1,13 +1,13 @@ package com.iluwatar.adapter; /** - * + * * Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link BattleShip} * interface expected by the client ({@link Captain}).
* In this case we added a new function fire to suit the interface. We are reusing the * {@link FishingBoat} without changing itself. The Adapter class can just map the functions of the * Adaptee or add, delete features of the Adaptee. - * + * */ public class BattleFishingBoat implements BattleShip { diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java index 90b18f758..d4f6036e6 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java @@ -3,7 +3,7 @@ package com.iluwatar.adapter; /** * The interface expected by the client.
* A Battleship can fire and move. - * + * */ public interface BattleShip { diff --git a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java index d2f9dae25..509bb8cdb 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java +++ b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java @@ -1,9 +1,9 @@ package com.iluwatar.adapter; /** - * + * * Device class (adaptee in the pattern). We want to reuse this class - * + * */ public class FishingBoat { diff --git a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java index c9a1a9bca..98c7cee2d 100644 --- a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java +++ b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java @@ -15,77 +15,52 @@ import com.iluwatar.adapter.Captain; import com.iluwatar.adapter.FishingBoat; /** - * An adapter helps two incompatible interfaces to work together. This is the - * real world definition for an adapter. Interfaces may be incompatible but the - * inner functionality should suit the need. The Adapter design pattern allows - * otherwise incompatible classes to work together by converting the interface - * of one class into an interface expected by the clients. - * - *

- * There are two variations of the Adapter pattern: The class adapter implements - * the adaptee's interface whereas the object adapter uses composition to - * contain the adaptee in the adapter object. This example uses the object - * adapter approach. - * - *

- * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee - * class ( {@link FishingBoat}) into a suitable one expected by the client ( - * {@link BattleShip} ). - * - *

- * The story of this implementation is this.
- * Pirates are coming! we need a {@link BattleShip} to fight! We have a - * {@link FishingBoat} and our captain. We have no time to make up a new ship! - * we need to reuse this {@link FishingBoat}. The captain needs a battleship - * which can fire and move. The spec is in {@link BattleShip}. We will use the - * Adapter pattern to reuse {@link FishingBoat} which operates properly + * Test class * */ public class AdapterPatternTest { - private Map beans; + private Map beans; - private static final String BATTLESHIP_BEAN = "engineer"; + private static final String BATTLESHIP_BEAN = "engineer"; - private static final String CAPTAIN_BEAN = "captain"; + private static final String CAPTAIN_BEAN = "captain"; - /** - * This method runs before the test execution and sets the bean objects in - * the beans Map. - */ - @Before - public void setup() { - beans = new HashMap<>(); + /** + * This method runs before the test execution and sets the bean objects in the beans Map. + */ + @Before + public void setup() { + beans = new HashMap<>(); - BattleFishingBoat battleFishingBoat = spy(new BattleFishingBoat()); - beans.put(BATTLESHIP_BEAN, battleFishingBoat); + BattleFishingBoat battleFishingBoat = spy(new BattleFishingBoat()); + beans.put(BATTLESHIP_BEAN, battleFishingBoat); - Captain captain = new Captain(); - captain.setBattleship((BattleFishingBoat) beans.get(BATTLESHIP_BEAN)); - beans.put(CAPTAIN_BEAN, captain); - } + Captain captain = new Captain(); + captain.setBattleship((BattleFishingBoat) beans.get(BATTLESHIP_BEAN)); + beans.put(CAPTAIN_BEAN, captain); + } - /** - * This test asserts that when we use the move() method on a captain - * bean(client), it is internally calling move method on the battleship - * object. The Adapter ({@link BattleFishingBoat}) converts the interface of - * the target class ( {@link FishingBoat}) into a suitable one expected by - * the client ({@link Captain} ). - */ - @Test - public void testAdapter() { - BattleShip captain = (BattleShip) beans.get(CAPTAIN_BEAN); + /** + * This test asserts that when we use the move() method on a captain bean(client), it is + * internally calling move method on the battleship object. The Adapter ({@link BattleFishingBoat} + * ) converts the interface of the target class ( {@link FishingBoat}) into a suitable one + * expected by the client ({@link Captain} ). + */ + @Test + public void testAdapter() { + BattleShip captain = (BattleShip) beans.get(CAPTAIN_BEAN); - // when captain moves - captain.move(); + // when captain moves + captain.move(); - // the captain internally calls the battleship object to move - BattleShip battleship = (BattleShip) beans.get(BATTLESHIP_BEAN); - verify(battleship).move(); + // the captain internally calls the battleship object to move + BattleShip battleship = (BattleShip) beans.get(BATTLESHIP_BEAN); + verify(battleship).move(); - // same with above with firing - captain.fire(); - verify(battleship).fire(); + // same with above with firing + captain.fire(); + verify(battleship).fire(); - } + } } From 10a94cc91cba699aef5f07f77631d40ccbdd1de7 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 7 Dec 2015 20:23:52 +0100 Subject: [PATCH 014/112] Add proper unit tests for decorator pattern --- decorator/pom.xml | 4 ++ .../iluwatar/decorator/SmartTrollTest.java | 38 +++++++++++ .../com/iluwatar/decorator/TrollTest.java | 66 +++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 decorator/src/test/java/com/iluwatar/decorator/SmartTrollTest.java create mode 100644 decorator/src/test/java/com/iluwatar/decorator/TrollTest.java diff --git a/decorator/pom.xml b/decorator/pom.xml index ab15f0e01..272f54a9b 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -14,5 +14,9 @@ junit test + + org.mockito + mockito-core + diff --git a/decorator/src/test/java/com/iluwatar/decorator/SmartTrollTest.java b/decorator/src/test/java/com/iluwatar/decorator/SmartTrollTest.java new file mode 100644 index 000000000..fd73d91cb --- /dev/null +++ b/decorator/src/test/java/com/iluwatar/decorator/SmartTrollTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.decorator; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/7/15 - 7:47 PM + * + * @author Jeroen Meulemeester + */ +public class SmartTrollTest { + + @Test + public void testSmartTroll() throws Exception { + // Create a normal troll first, but make sure we can spy on it later on. + final Hostile simpleTroll = spy(new Troll()); + + // Now we want to decorate the troll to make it smarter ... + final Hostile smartTroll = new SmartTroll(simpleTroll); + assertEquals(30, smartTroll.getAttackPower()); + verify(simpleTroll, times(1)).getAttackPower(); + + // Check if the smart troll actions are delegated to the decorated troll + smartTroll.attack(); + verify(simpleTroll, times(1)).attack(); + + smartTroll.fleeBattle(); + verify(simpleTroll, times(1)).fleeBattle(); + verifyNoMoreInteractions(simpleTroll); + + } + +} diff --git a/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java b/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java new file mode 100644 index 000000000..021f7ed1a --- /dev/null +++ b/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java @@ -0,0 +1,66 @@ +package com.iluwatar.decorator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/7/15 - 7:26 PM + * + * @author Jeroen Meulemeester + */ +public class TrollTest { + + /** + * The mocked standard out stream, required since the actions don't have any influence on other + * objects, except for writing to the std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + @Test + public void testTrollActions() throws Exception { + final Troll troll = new Troll(); + assertEquals(10, troll.getAttackPower()); + + troll.attack(); + verify(this.stdOutMock, times(1)).println(eq("The troll swings at you with a club!")); + + troll.fleeBattle(); + verify(this.stdOutMock, times(1)).println(eq("The troll shrieks in horror and runs away!")); + + verifyNoMoreInteractions(this.stdOutMock); + } + +} \ No newline at end of file From 6e59d9554f18ab3a1abcf7649222d52cb7bfb949 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Tue, 8 Dec 2015 23:25:05 +0200 Subject: [PATCH 015/112] Functional approach to Strategy pattern #310 --- .../main/java/com/iluwatar/strategy/App.java | 19 +++++++++++++++++++ .../strategy/DragonSlayingStrategy.java | 1 + 2 files changed, 20 insertions(+) diff --git a/strategy/src/main/java/com/iluwatar/strategy/App.java b/strategy/src/main/java/com/iluwatar/strategy/App.java index 272e56cf9..e2bcfef8a 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/App.java +++ b/strategy/src/main/java/com/iluwatar/strategy/App.java @@ -5,6 +5,10 @@ package com.iluwatar.strategy; * The Strategy pattern (also known as the policy pattern) is a software design pattern that enables * an algorithm's behavior to be selected at runtime. *

+ * Before Java 8 the Strategies needed to be separate classes forcing the developer + * to write lots of boilerplate code. With modern Java it is easy to pass behavior + * with method references and lambdas making the code shorter and more readable. + *

* In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing object * ({@link DragonSlayer}) can alter its behavior by changing its strategy. * @@ -17,6 +21,7 @@ public class App { * @param args command line args */ public static void main(String[] args) { + // GoF Strategy pattern System.out.println("Green dragon spotted ahead!"); DragonSlayer dragonSlayer = new DragonSlayer(new MeleeStrategy()); dragonSlayer.goToBattle(); @@ -26,5 +31,19 @@ public class App { System.out.println("Black dragon lands before you."); dragonSlayer.changeStrategy(new SpellStrategy()); dragonSlayer.goToBattle(); + + // Java 8 Strategy pattern + System.out.println("Green dragon spotted ahead!"); + dragonSlayer = new DragonSlayer( + () -> System.out.println("With your Excalibur you severe the dragon's head!")); + dragonSlayer.goToBattle(); + System.out.println("Red dragon emerges."); + dragonSlayer.changeStrategy(() -> System.out.println( + "You shoot the dragon with the magical crossbow and it falls dead on the ground!")); + dragonSlayer.goToBattle(); + System.out.println("Black dragon lands before you."); + dragonSlayer.changeStrategy(() -> System.out.println( + "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!")); + dragonSlayer.goToBattle(); } } diff --git a/strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java index e17e5fbf0..aa57c34f0 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java +++ b/strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java @@ -5,6 +5,7 @@ package com.iluwatar.strategy; * Strategy interface. * */ +@FunctionalInterface public interface DragonSlayingStrategy { void execute(); From 7df65adbfcb6edb2da323a326b2a2e9a01bc136c Mon Sep 17 00:00:00 2001 From: Carlos Romero Date: Fri, 11 Dec 2015 13:54:32 +0100 Subject: [PATCH 016/112] Just Just a quick fix for the Front-controller pattern. --- .../java/com/iluwatar/front/controller/FrontController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java index 5a6dc2a78..0c6c132f2 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java @@ -25,7 +25,7 @@ public class FrontController { private Class getCommandClass(String request) { Class result; try { - result = Class.forName("com.iluwatar." + request + "Command"); + result = Class.forName("com.iluwatar.front.controller." + request + "Command"); } catch (ClassNotFoundException e) { result = UnknownCommand.class; } From 2c0a5e87030adaca9ebde00501d6b071a5bb1b51 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 9 Dec 2015 22:16:33 +0100 Subject: [PATCH 017/112] Add proper unit tests for facade pattern --- facade/pom.xml | 4 + .../facade/DwarvenGoldmineFacadeTest.java | 103 ++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java diff --git a/facade/pom.xml b/facade/pom.xml index ea51c2138..4932a42d4 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -14,5 +14,9 @@ junit test + + org.mockito + mockito-core + diff --git a/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java b/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java new file mode 100644 index 000000000..9a9bc5d66 --- /dev/null +++ b/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java @@ -0,0 +1,103 @@ +package com.iluwatar.facade; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +/** + * Date: 12/9/15 - 9:40 PM + * + * @author Jeroen Meulemeester + */ +public class DwarvenGoldmineFacadeTest { + + /** + * The mocked standard out {@link PrintStream}, required since the actions on the gold mine facade + * don't have any influence on any other accessible objects, except for writing to std-out using + * {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Test a complete day cycle in the gold mine by executing all three different steps: {@link + * DwarvenGoldmineFacade#startNewDay()}, {@link DwarvenGoldmineFacade#digOutGold()} and {@link + * DwarvenGoldmineFacade#endDay()}. + * + * See if the workers are doing what's expected from them on each step. + */ + @Test + public void testFullWorkDay() { + final DwarvenGoldmineFacade goldMine = new DwarvenGoldmineFacade(); + goldMine.startNewDay(); + + // On the start of a day, all workers should wake up ... + verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger wakes up.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator wakes up.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger wakes up.")); + + // ... and go to the mine + verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes to the mine.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes to the mine.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes to the mine.")); + + // No other actions were invoked, so the workers shouldn't have done (printed) anything else + verifyNoMoreInteractions(this.stdOutMock); + + // Now do some actual work, start digging gold! + goldMine.digOutGold(); + + // Since we gave the dig command, every worker should be doing it's job ... + verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger digs for gold.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator moves gold chunks out of the mine.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger creates another promising tunnel.")); + + // Again, they shouldn't be doing anything else. + verifyNoMoreInteractions(this.stdOutMock); + + // Enough gold, lets end the day. + goldMine.endDay(); + + // Check if the workers go home ... + verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes home.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes home.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes home.")); + + // ... and go to sleep. We need well rested workers the next day :) + verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes to sleep.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes to sleep.")); + verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes to sleep.")); + + // Every worker should be sleeping now, no other actions allowed + verifyNoMoreInteractions(this.stdOutMock); + } + +} From 0643289c7407be17511534847398f756d0242b0d Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Thu, 10 Dec 2015 20:33:32 +0100 Subject: [PATCH 018/112] Dependency org.mockito:mockito-core should have scope 'test' --- bridge/pom.xml | 1 + decorator/pom.xml | 1 + facade/pom.xml | 1 + 3 files changed, 3 insertions(+) diff --git a/bridge/pom.xml b/bridge/pom.xml index 10b763eab..26ca50bec 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -17,6 +17,7 @@ org.mockito mockito-core + test diff --git a/decorator/pom.xml b/decorator/pom.xml index 272f54a9b..384c03aa4 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -17,6 +17,7 @@ org.mockito mockito-core + test diff --git a/facade/pom.xml b/facade/pom.xml index 4932a42d4..5fec5216e 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -17,6 +17,7 @@ org.mockito mockito-core + test From 29fc56002a88ea6b09de60bb275972bf58c56afa Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Thu, 10 Dec 2015 21:18:16 +0100 Subject: [PATCH 019/112] Add proper unit tests for dependency-injection pattern --- dependency-injection/pom.xml | 5 ++ .../injection/AdvancedWizardTest.java | 40 ++++++++++ .../dependency/injection/GuiceWizardTest.java | 78 +++++++++++++++++++ .../injection/SimpleWizardTest.java | 33 ++++++++ .../dependency/injection/StdOutTest.java | 53 +++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java create mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java create mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java create mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index 40970e130..4746d5835 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -13,6 +13,11 @@ junit junit test + + + org.mockito + mockito-core + test com.google.inject diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java new file mode 100644 index 000000000..5f7733a99 --- /dev/null +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java @@ -0,0 +1,40 @@ +package com.iluwatar.dependency.injection; + +import org.junit.Test; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/10/15 - 8:40 PM + * + * @author Jeroen Meulemeester + */ +public class AdvancedWizardTest extends StdOutTest { + + /** + * Test if the {@link AdvancedWizard} smokes whatever instance of {@link Tobacco} is passed to him + * through the constructor parameter + */ + @Test + public void testSmokeEveryThing() throws Exception { + + final Tobacco[] tobaccos = { + new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco() + }; + + for (final Tobacco tobacco : tobaccos) { + final AdvancedWizard advancedWizard = new AdvancedWizard(tobacco); + advancedWizard.smoke(); + + // Verify if the wizard is smoking the correct tobacco ... + verify(getStdOutMock(), times(1)).println("AdvancedWizard smoking " + tobacco.getClass().getSimpleName()); + + // ... and nothing else is happening. + verifyNoMoreInteractions(getStdOutMock()); + } + + } + +} \ No newline at end of file diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java new file mode 100644 index 000000000..d84ffad84 --- /dev/null +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java @@ -0,0 +1,78 @@ +package com.iluwatar.dependency.injection; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +import org.junit.Test; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/10/15 - 8:57 PM + * + * @author Jeroen Meulemeester + */ +public class GuiceWizardTest extends StdOutTest { + + /** + * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him + * through the constructor parameter + */ + @Test + public void testSmokeEveryThingThroughConstructor() throws Exception { + + final Tobacco[] tobaccos = { + new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco() + }; + + for (final Tobacco tobacco : tobaccos) { + final GuiceWizard guiceWizard = new GuiceWizard(tobacco); + guiceWizard.smoke(); + + // Verify if the wizard is smoking the correct tobacco ... + verify(getStdOutMock(), times(1)).println("GuiceWizard smoking " + tobacco.getClass().getSimpleName()); + + // ... and nothing else is happening. + verifyNoMoreInteractions(getStdOutMock()); + } + + } + + /** + * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him + * through the Guice google inject framework + */ + @Test + public void testSmokeEveryThingThroughInjectionFramework() throws Exception { + + @SuppressWarnings("unchecked") + final Class[] tobaccos = new Class[]{ + OldTobyTobacco.class, RivendellTobacco.class, SecondBreakfastTobacco.class + }; + + for (final Class tobaccoClass : tobaccos) { + // Configure the tobacco in the injection framework ... + final Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(Tobacco.class).to(tobaccoClass); + } + }); + + // ... and create a new wizard with it + final GuiceWizard guiceWizard = injector.getInstance(GuiceWizard.class); + guiceWizard.smoke(); + + // Verify if the wizard is smoking the correct tobacco ... + verify(getStdOutMock(), times(1)).println("GuiceWizard smoking " + tobaccoClass.getSimpleName()); + + // ... and nothing else is happening. + verifyNoMoreInteractions(getStdOutMock()); + } + + } + +} \ No newline at end of file diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java new file mode 100644 index 000000000..69895a493 --- /dev/null +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.dependency.injection; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/10/15 - 8:26 PM + * + * @author Jeroen Meulemeester + */ +public class SimpleWizardTest extends StdOutTest { + + /** + * Test if the {@link SimpleWizard} does the only thing it can do: Smoke it's {@link + * OldTobyTobacco} + */ + @Test + public void testSmoke() { + final SimpleWizard simpleWizard = new SimpleWizard(); + simpleWizard.smoke(); + verify(getStdOutMock(), times(1)).println("SimpleWizard smoking OldTobyTobacco"); + verifyNoMoreInteractions(getStdOutMock()); + } + +} \ No newline at end of file diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java new file mode 100644 index 000000000..13c18fcd1 --- /dev/null +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.dependency.injection; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since the actions of the wizard don't + * have any influence on any other accessible objects, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } +} From 2edc1898b10c27803fea9a7372257d17434d3c6a Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Thu, 10 Dec 2015 22:11:21 +0100 Subject: [PATCH 020/112] Add proper unit tests for double-checked-locking pattern --- double-checked-locking/pom.xml | 5 + .../doublechecked/locking/Inventory.java | 11 ++ .../doublechecked/locking/InventoryTest.java | 110 ++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index 7ad651339..9b87d6859 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -12,5 +12,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java index b51e000a7..0a17ac13d 100644 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java +++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java @@ -1,6 +1,7 @@ package com.iluwatar.doublechecked.locking; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -38,4 +39,14 @@ public class Inventory { } return false; } + + /** + * Get all the items in the inventory + * + * @return All the items of the inventory, as an unmodifiable list + */ + public final List getItems() { + return Collections.unmodifiableList(items); + } + } diff --git a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java new file mode 100644 index 000000000..1bc43263f --- /dev/null +++ b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java @@ -0,0 +1,110 @@ +package com.iluwatar.doublechecked.locking; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.io.PrintStream; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/10/15 - 9:34 PM + * + * @author Jeroen Meulemeester + */ +public class InventoryTest { + + /** + * The mocked standard out {@link PrintStream}, used to verify a steady increasing size of the + * {@link Inventory} while adding items from multiple threads concurrently + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * The number of threads used to stress test the locking of the {@link Inventory#addItem(Item)} + * method + */ + private static final int THREAD_COUNT = 8; + + /** + * The maximum number of {@link Item}s allowed in the {@link Inventory} + */ + private static final int INVENTORY_SIZE = 1000; + + /** + * Concurrently add multiple items to the inventory, and check if the items were added in order by + * checking the stdOut for continuous growth of the inventory. When 'items.size()=xx' shows up out + * of order, it means that the locking is not ok, increasing the risk of going over the inventory + * item limit. + */ + @Test(timeout = 10000) + public void testAddItem() throws Exception { + // Create a new inventory with a limit of 1000 items and put some load on the add method + final Inventory inventory = new Inventory(INVENTORY_SIZE); + final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT); + for (int i = 0; i < THREAD_COUNT; i++) { + executorService.execute(() -> { + while (inventory.addItem(new Item())) ; + }); + } + + // Wait until all threads have finished + executorService.shutdown(); + executorService.awaitTermination(5, TimeUnit.SECONDS); + + // Check the number of items in the inventory. It should not have exceeded the allowed maximum + final List items = inventory.getItems(); + assertNotNull(items); + assertEquals(INVENTORY_SIZE, items.size()); + + // Capture all stdOut messages ... + final ArgumentCaptor stdOutCaptor = ArgumentCaptor.forClass(String.class); + verify(this.stdOutMock, times(INVENTORY_SIZE)).println(stdOutCaptor.capture()); + + // ... verify if we got all 1000 + final List values = stdOutCaptor.getAllValues(); + assertEquals(INVENTORY_SIZE, values.size()); + + // ... and check if the inventory size is increasing continuously + for (int i = 0; i < values.size(); i++) { + assertNotNull(values.get(i)); + assertTrue(values.get(i).contains("items.size()=" + (i + 1))); + } + + verifyNoMoreInteractions(this.stdOutMock); + } + +} \ No newline at end of file From c837ffe234e0b6352125d3a07b5db296355877d1 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Fri, 11 Dec 2015 20:14:52 +0100 Subject: [PATCH 021/112] Add proper unit tests for double-dispatch pattern --- double-dispatch/pom.xml | 5 + .../doubledispatch/CollisionTest.java | 136 ++++++++++++++++++ .../doubledispatch/FlamingAsteroidTest.java | 88 ++++++++++++ .../doubledispatch/MeteoroidTest.java | 87 +++++++++++ .../doubledispatch/RectangleTest.java | 43 ++++-- .../doubledispatch/SpaceStationIssTest.java | 87 +++++++++++ .../doubledispatch/SpaceStationMirTest.java | 87 +++++++++++ 7 files changed, 524 insertions(+), 9 deletions(-) create mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java create mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java create mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java create mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java create mode 100644 double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index bc78a8a31..8c5db3b6b 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java new file mode 100644 index 000000000..5a3366e4e --- /dev/null +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java @@ -0,0 +1,136 @@ +package com.iluwatar.doubledispatch; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; +import java.util.Objects; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class CollisionTest { + + /** + * The mocked standard out {@link PrintStream}, required if some of the actions on the tested + * object don't have a direct influence on any other accessible objects, except for writing to + * std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + + /** + * Get the tested object + * + * @return The tested object, should never return 'null' + */ + abstract O getTestedObject(); + + /** + * Collide the tested item with the other given item and verify if the damage and fire state is as + * expected + * + * @param other The other object we have to collide with + * @param otherDamaged Indicates if the other object should be damaged after the collision + * @param otherOnFire Indicates if the other object should be burning after the collision + * @param thisDamaged Indicates if the test object should be damaged after the collision + * @param thisOnFire Indicates if the other object should be burning after the collision + * @param description The expected description of the collision + */ + void testCollision(final GameObject other, final boolean otherDamaged, final boolean otherOnFire, + final boolean thisDamaged, final boolean thisOnFire, final String description) { + + Objects.requireNonNull(other); + Objects.requireNonNull(getTestedObject()); + + final O tested = getTestedObject(); + + tested.collision(other); + + verify(getStdOutMock(), times(1)).println(description); + verifyNoMoreInteractions(getStdOutMock()); + + testOnFire(other, tested, otherOnFire); + testDamaged(other, tested, otherDamaged); + + testOnFire(tested, other, thisOnFire); + testDamaged(tested, other, thisDamaged); + + } + + /** + * Test if the fire state of the target matches the expected state after colliding with the given + * object + * + * @param target The target object + * @param other The other object + * @param expectTargetOnFire The expected state of fire on the target object + */ + private void testOnFire(final GameObject target, final GameObject other, final boolean expectTargetOnFire) { + 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!"; + + assertEquals(errorMessage, expectTargetOnFire, target.isOnFire()); + } + + /** + * Test if the damage state of the target matches the expected state after colliding with the + * given object + * + * @param target The target object + * @param other The other object + * @param expectedDamage The expected state of damage on the target object + */ + private void testDamaged(final GameObject target, final GameObject other, final boolean expectedDamage) { + 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!"; + + assertEquals(errorMessage, expectedDamage, target.isDamaged()); + } + +} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java new file mode 100644 index 000000000..4cbc052c7 --- /dev/null +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java @@ -0,0 +1,88 @@ +package com.iluwatar.doubledispatch; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/10/15 - 11:31 PM + * + * @author Jeroen Meulemeester + */ +public class FlamingAsteroidTest extends CollisionTest { + + @Override + final FlamingAsteroid getTestedObject() { + return new FlamingAsteroid(1, 2, 3, 4); + } + + /** + * Test the constructor parameters + */ + @Test + public void testConstructor() { + final FlamingAsteroid asteroid = new FlamingAsteroid(1, 2, 3, 4); + assertEquals(1, asteroid.getLeft()); + assertEquals(2, asteroid.getTop()); + assertEquals(3, asteroid.getRight()); + assertEquals(4, asteroid.getBottom()); + assertTrue(asteroid.isOnFire()); + assertFalse(asteroid.isDamaged()); + assertEquals("FlamingAsteroid at [1,2,3,4] damaged=false onFire=true", asteroid.toString()); + } + + /** + * Test what happens we collide with an asteroid + */ + @Test + public void testCollideFlamingAsteroid() { + testCollision( + new FlamingAsteroid(1, 2, 3, 4), + false, true, + false, true, + "FlamingAsteroid hits FlamingAsteroid." + ); + } + + /** + * Test what happens we collide with an meteoroid + */ + @Test + public void testCollideMeteoroid() { + testCollision( + new Meteoroid(1, 1, 3, 4), + false, false, + false, true, + "FlamingAsteroid hits Meteoroid." + ); + } + + /** + * Test what happens we collide with ISS + */ + @Test + public void testCollideSpaceStationIss() { + testCollision( + new SpaceStationIss(1, 1, 3, 4), + true, true, + false, true, + "FlamingAsteroid hits SpaceStationIss. SpaceStationIss is damaged! SpaceStationIss is set on fire!" + ); + } + + /** + * Test what happens we collide with MIR + */ + @Test + public void testCollideSpaceStationMir() { + testCollision( + new SpaceStationMir(1, 1, 3, 4), + true, true, + false, true, + "FlamingAsteroid hits SpaceStationMir. SpaceStationMir is damaged! SpaceStationMir is set on fire!" + ); + } + +} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java new file mode 100644 index 000000000..6f90fbaab --- /dev/null +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java @@ -0,0 +1,87 @@ +package com.iluwatar.doubledispatch; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Date: 12/10/15 - 11:31 PM + * + * @author Jeroen Meulemeester + */ +public class MeteoroidTest extends CollisionTest { + + @Override + final Meteoroid getTestedObject() { + return new Meteoroid(1, 2, 3, 4); + } + + /** + * Test the constructor parameters + */ + @Test + public void testConstructor() { + final Meteoroid meteoroid = new Meteoroid(1, 2, 3, 4); + assertEquals(1, meteoroid.getLeft()); + assertEquals(2, meteoroid.getTop()); + assertEquals(3, meteoroid.getRight()); + assertEquals(4, meteoroid.getBottom()); + assertFalse(meteoroid.isOnFire()); + assertFalse(meteoroid.isDamaged()); + assertEquals("Meteoroid at [1,2,3,4] damaged=false onFire=false", meteoroid.toString()); + } + + /** + * Test what happens we collide with an asteroid + */ + @Test + public void testCollideFlamingAsteroid() { + testCollision( + new FlamingAsteroid(1, 1, 3, 4), + false, true, + false, false, + "Meteoroid hits FlamingAsteroid." + ); + } + + /** + * Test what happens we collide with an meteoroid + */ + @Test + public void testCollideMeteoroid() { + testCollision( + new Meteoroid(1, 1, 3, 4), + false, false, + false, false, + "Meteoroid hits Meteoroid." + ); + } + + /** + * Test what happens we collide with ISS + */ + @Test + public void testCollideSpaceStationIss() { + testCollision( + new SpaceStationIss(1, 1, 3, 4), + true, false, + false, false, + "Meteoroid hits SpaceStationIss. SpaceStationIss is damaged!" + ); + } + + /** + * Test what happens we collide with MIR + */ + @Test + public void testCollideSpaceStationMir() { + testCollision( + new SpaceStationMir(1, 1, 3, 4), + true, false, + false, false, + "Meteoroid hits SpaceStationMir. SpaceStationMir is damaged!" + ); + } + +} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java index fad10c490..e2563f7db 100644 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java @@ -1,22 +1,47 @@ package com.iluwatar.doubledispatch; -import org.junit.Assert; import org.junit.Test; -import com.iluwatar.doubledispatch.Rectangle; +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** - * * Unit test for Rectangle - * */ public class RectangleTest { + /** + * Test if the values passed through the constructor matches the values fetched from the getters + */ @Test - public void test() { - Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1))); - Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8))); - Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3))); - Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1))); + public void testConstructor() { + final Rectangle rectangle = new Rectangle(1, 2, 3, 4); + assertEquals(1, rectangle.getLeft()); + assertEquals(2, rectangle.getTop()); + assertEquals(3, rectangle.getRight()); + assertEquals(4, rectangle.getBottom()); } + + /** + * Test if the values passed through the constructor matches the values in the {@link + * #toString()} + */ + @Test + public void testToString() throws Exception { + final Rectangle rectangle = new Rectangle(1, 2, 3, 4); + assertEquals("[1,2,3,4]", rectangle.toString()); + } + + /** + * Test if the {@link Rectangle} class can detect if it intersects with another rectangle. + */ + @Test + public void testIntersection() { + assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1))); + assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8))); + assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3))); + assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1))); + } + } diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java new file mode 100644 index 000000000..f3ce24e9c --- /dev/null +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java @@ -0,0 +1,87 @@ +package com.iluwatar.doubledispatch; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Date: 12/10/15 - 11:31 PM + * + * @author Jeroen Meulemeester + */ +public class SpaceStationIssTest extends CollisionTest { + + @Override + final SpaceStationIss getTestedObject() { + return new SpaceStationIss(1, 2, 3, 4); + } + + /** + * Test the constructor parameters + */ + @Test + public void testConstructor() { + final SpaceStationIss iss = new SpaceStationIss(1, 2, 3, 4); + assertEquals(1, iss.getLeft()); + assertEquals(2, iss.getTop()); + assertEquals(3, iss.getRight()); + assertEquals(4, iss.getBottom()); + assertFalse(iss.isOnFire()); + assertFalse(iss.isDamaged()); + assertEquals("SpaceStationIss at [1,2,3,4] damaged=false onFire=false", iss.toString()); + } + + /** + * Test what happens we collide with an asteroid + */ + @Test + public void testCollideFlamingAsteroid() { + testCollision( + new FlamingAsteroid(1, 1, 3, 4), + false, true, + false, false, + "SpaceStationIss hits FlamingAsteroid." + ); + } + + /** + * Test what happens we collide with an meteoroid + */ + @Test + public void testCollideMeteoroid() { + testCollision( + new Meteoroid(1, 1, 3, 4), + false, false, + false, false, + "SpaceStationIss hits Meteoroid." + ); + } + + /** + * Test what happens we collide with ISS + */ + @Test + public void testCollideSpaceStationIss() { + testCollision( + new SpaceStationIss(1, 1, 3, 4), + true, false, + false, false, + "SpaceStationIss hits SpaceStationIss. SpaceStationIss is damaged!" + ); + } + + /** + * Test what happens we collide with MIR + */ + @Test + public void testCollideSpaceStationMir() { + testCollision( + new SpaceStationMir(1, 1, 3, 4), + true, false, + false, false, + "SpaceStationIss hits SpaceStationMir. SpaceStationMir is damaged!" + ); + } + +} \ No newline at end of file diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java new file mode 100644 index 000000000..7d557dd30 --- /dev/null +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java @@ -0,0 +1,87 @@ +package com.iluwatar.doubledispatch; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Date: 12/10/15 - 11:31 PM + * + * @author Jeroen Meulemeester + */ +public class SpaceStationMirTest extends CollisionTest { + + @Override + final SpaceStationMir getTestedObject() { + return new SpaceStationMir(1, 2, 3, 4); + } + + /** + * Test the constructor parameters + */ + @Test + public void testConstructor() { + final SpaceStationMir mir = new SpaceStationMir(1, 2, 3, 4); + assertEquals(1, mir.getLeft()); + assertEquals(2, mir.getTop()); + assertEquals(3, mir.getRight()); + assertEquals(4, mir.getBottom()); + assertFalse(mir.isOnFire()); + assertFalse(mir.isDamaged()); + assertEquals("SpaceStationMir at [1,2,3,4] damaged=false onFire=false", mir.toString()); + } + + /** + * Test what happens we collide with an asteroid + */ + @Test + public void testCollideFlamingAsteroid() { + testCollision( + new FlamingAsteroid(1, 1, 3, 4), + false, true, + false, false, + "SpaceStationMir hits FlamingAsteroid." + ); + } + + /** + * Test what happens we collide with an meteoroid + */ + @Test + public void testCollideMeteoroid() { + testCollision( + new Meteoroid(1, 1, 3, 4), + false, false, + false, false, + "SpaceStationMir hits Meteoroid." + ); + } + + /** + * Test what happens we collide with ISS + */ + @Test + public void testCollideSpaceStationIss() { + testCollision( + new SpaceStationIss(1, 1, 3, 4), + true, false, + false, false, + "SpaceStationMir hits SpaceStationIss. SpaceStationIss is damaged!" + ); + } + + /** + * Test what happens we collide with MIR + */ + @Test + public void testCollideSpaceStationMir() { + testCollision( + new SpaceStationMir(1, 1, 3, 4), + true, false, + false, false, + "SpaceStationMir hits SpaceStationMir. SpaceStationMir is damaged!" + ); + } + +} \ No newline at end of file From 94f80d1868bc2554e6d7cda052456811512b6ffa Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Fri, 11 Dec 2015 20:17:21 +0100 Subject: [PATCH 022/112] Add proper unit tests for composite pattern --- .../com/iluwatar/composite/MessengerTest.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 composite/src/test/java/com/iluwatar/composite/MessengerTest.java diff --git a/composite/src/test/java/com/iluwatar/composite/MessengerTest.java b/composite/src/test/java/com/iluwatar/composite/MessengerTest.java new file mode 100644 index 000000000..9d0b158cc --- /dev/null +++ b/composite/src/test/java/com/iluwatar/composite/MessengerTest.java @@ -0,0 +1,90 @@ +package com.iluwatar.composite; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/11/15 - 8:12 PM + * + * @author Jeroen Meulemeester + */ +public class MessengerTest { + + /** + * The buffer used to capture every write to {@link System#out} + */ + private ByteArrayOutputStream stdOutBuffer = new ByteArrayOutputStream(); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream realStdOut = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + this.stdOutBuffer = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOutBuffer)); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(realStdOut); + } + + /** + * Test the message from the orcs + */ + @Test + public void testMessageFromOrcs() { + final Messenger messenger = new Messenger(); + testMessage( + messenger.messageFromOrcs(), + "Where there is a whip there is a way." + ); + } + + /** + * Test the message from the elves + */ + @Test + public void testMessageFromElves() { + final Messenger messenger = new Messenger(); + testMessage( + messenger.messageFromElves(), + "Much wind pours from your mouth." + ); + } + + /** + * Test if the given composed message matches the expected message + * + * @param composedMessage The composed message, received from the messenger + * @param message The expected message + */ + private void testMessage(final LetterComposite composedMessage, final String message) { + // Test is the composed message has the correct number of words + final String[] words = message.split(" "); + assertNotNull(composedMessage); + assertEquals(words.length, composedMessage.count()); + + // Print the message to the mocked stdOut ... + composedMessage.print(); + + // ... and verify if the message matches with the expected one + assertEquals(message, new String(this.stdOutBuffer.toByteArray()).trim()); + } + +} From 885d5bb7dd9db505a5c70a8aca8583caae684d52 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 12 Dec 2015 20:13:25 +0100 Subject: [PATCH 023/112] Add proper unit tests for event-aggregator pattern --- event-aggregator/pom.xml | 5 + .../event/aggregator/EventEmitterTest.java | 133 ++++++++++++++++++ .../iluwatar/event/aggregator/EventTest.java | 27 ++++ .../event/aggregator/KingJoffreyTest.java | 67 +++++++++ .../event/aggregator/KingsHandTest.java | 48 +++++++ .../event/aggregator/LordBaelishTest.java | 17 +++ .../event/aggregator/LordVarysTest.java | 17 +++ .../iluwatar/event/aggregator/ScoutTest.java | 17 +++ .../event/aggregator/WeekdayTest.java | 24 ++++ 9 files changed, 355 insertions(+) create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java create mode 100644 event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index 62c6adf14..94873472f 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -13,5 +13,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java new file mode 100644 index 000000000..09acf7442 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java @@ -0,0 +1,133 @@ +package com.iluwatar.event.aggregator; + +import org.junit.Test; + +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/12/15 - 10:58 PM + * + * @author Jeroen Meulemeester + */ +public abstract class EventEmitterTest { + + /** + * Factory used to create a new instance of the test object with a default observer + */ + private final Function factoryWithDefaultObserver; + + /** + * Factory used to create a new instance of the test object without passing a default observer + */ + private final Supplier factoryWithoutDefaultObserver; + + /** + * The day of the week an event is expected + */ + private final Weekday specialDay; + + /** + * The expected event, emitted on the special day + */ + private final Event event; + + /** + * Create a new event emitter test, using the given test object factories, special day and event + */ + EventEmitterTest(final Weekday specialDay, final Event event, + final Function factoryWithDefaultObserver, + final Supplier factoryWithoutDefaultObserver) { + + this.specialDay = specialDay; + this.event = event; + this.factoryWithDefaultObserver = Objects.requireNonNull(factoryWithDefaultObserver); + this.factoryWithoutDefaultObserver = Objects.requireNonNull(factoryWithoutDefaultObserver); + } + + /** + * Go over every day of the month, and check if the event is emitted on the given day. This test + * is executed twice, once without a default emitter and once with + */ + @Test + public void testAllDays() { + testAllDaysWithoutDefaultObserver(specialDay, event); + testAllDaysWithDefaultObserver(specialDay, event); + } + + /** + * 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 + * + * @param specialDay The special day on which an event is emitted + * @param event The expected event emitted by the test object + */ + private void testAllDaysWithoutDefaultObserver(final Weekday specialDay, final Event event) { + final EventObserver observer1 = mock(EventObserver.class); + final EventObserver observer2 = mock(EventObserver.class); + + final E emitter = this.factoryWithoutDefaultObserver.get(); + emitter.registerObserver(observer1); + emitter.registerObserver(observer2); + + testAllDays(specialDay, event, emitter, observer1, observer2); + } + + /** + * Go over every day of the month, and check if the event is emitted on the given day. + * + * @param specialDay The special day on which an event is emitted + * @param event The expected event emitted by the test object + */ + private void testAllDaysWithDefaultObserver(final Weekday specialDay, final Event event) { + final EventObserver defaultObserver = mock(EventObserver.class); + final EventObserver observer1 = mock(EventObserver.class); + final EventObserver observer2 = mock(EventObserver.class); + + final E emitter = this.factoryWithDefaultObserver.apply(defaultObserver); + emitter.registerObserver(observer1); + emitter.registerObserver(observer2); + + 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); + } + +} diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java new file mode 100644 index 000000000..3f2cdb0fe --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java @@ -0,0 +1,27 @@ +package com.iluwatar.event.aggregator; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/12/15 - 2:52 PM + * + * @author Jeroen Meulemeester + */ +public class EventTest { + + /** + * Verify if every event has a non-null, non-empty description + */ + @Test + public void testToString() { + for (final Event event : Event.values()) { + final String toString = event.toString(); + assertNotNull(toString); + assertFalse(toString.trim().isEmpty()); + } + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java new file mode 100644 index 000000000..1dd4e5c63 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java @@ -0,0 +1,67 @@ +package com.iluwatar.event.aggregator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/12/15 - 3:04 PM + * + * @author Jeroen Meulemeester + */ +public class KingJoffreyTest { + + /** + * The mocked standard out {@link PrintStream}, required since {@link KingJoffrey} does nothing + * except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Test if {@link KingJoffrey} tells us what event he received + */ + @Test + public void testOnEvent() { + final KingJoffrey kingJoffrey = new KingJoffrey(); + + for (final Event event : Event.values()) { + verifyZeroInteractions(this.stdOutMock); + kingJoffrey.onEvent(event); + + final String expectedMessage = "Received event from the King's Hand: " + event.toString(); + verify(this.stdOutMock, times(1)).println(expectedMessage); + verifyNoMoreInteractions(this.stdOutMock); + } + + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java new file mode 100644 index 000000000..992ee4cf5 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java @@ -0,0 +1,48 @@ +package com.iluwatar.event.aggregator; + +import org.junit.Test; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/12/15 - 10:57 AM + * + * @author Jeroen Meulemeester + */ +public class KingsHandTest extends EventEmitterTest { + + /** + * Create a new test instance, using the correct object factory + */ + public KingsHandTest() { + super(null, null, KingsHand::new, KingsHand::new); + } + + /** + * The {@link KingsHand} is both an {@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. + */ + @Test + public void testPassThrough() throws Exception { + final EventObserver observer = mock(EventObserver.class); + final KingsHand kingsHand = new KingsHand(observer); + + // The kings hand should not pass any events before he received one + verifyZeroInteractions(observer); + + // Verify if each event is passed on to the observer, nothing less, nothing more. + for (final Event event : Event.values()) { + kingsHand.onEvent(event); + verify(observer, times(1)).onEvent(eq(event)); + verifyNoMoreInteractions(observer); + } + + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java new file mode 100644 index 000000000..dbc867859 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.event.aggregator; + +/** + * Date: 12/12/15 - 10:57 AM + * + * @author Jeroen Meulemeester + */ +public class LordBaelishTest extends EventEmitterTest { + + /** + * Create a new test instance, using the correct object factory + */ + public LordBaelishTest() { + super(Weekday.FRIDAY, Event.STARK_SIGHTED, LordBaelish::new, LordBaelish::new); + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java new file mode 100644 index 000000000..050af5576 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.event.aggregator; + +/** + * Date: 12/12/15 - 10:57 AM + * + * @author Jeroen Meulemeester + */ +public class LordVarysTest extends EventEmitterTest { + + /** + * Create a new test instance, using the correct object factory + */ + public LordVarysTest() { + super(Weekday.SATURDAY, Event.TRAITOR_DETECTED, LordVarys::new, LordVarys::new); + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java new file mode 100644 index 000000000..435e07821 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.event.aggregator; + +/** + * Date: 12/12/15 - 10:57 AM + * + * @author Jeroen Meulemeester + */ +public class ScoutTest extends EventEmitterTest { + + /** + * Create a new test instance, using the correct object factory + */ + public ScoutTest() { + super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new); + } + +} \ No newline at end of file diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java new file mode 100644 index 000000000..37b300851 --- /dev/null +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.event.aggregator; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/12/15 - 2:12 PM + * + * @author Jeroen Meulemeester + */ +public class WeekdayTest { + + @Test + public void testToString() throws Exception { + for (final Weekday weekday : Weekday.values()) { + final String toString = weekday.toString(); + assertNotNull(toString); + assertEquals(weekday.name(), toString.toUpperCase()); + } + } + +} \ No newline at end of file From df69a8f9869346d528a8fd189b2e8acb43ab6188 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 12 Dec 2015 20:14:59 +0100 Subject: [PATCH 024/112] Add proper tests for execute-around pattern --- .../execute/around/SimpleFileWriterTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java diff --git a/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java b/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java new file mode 100644 index 000000000..168026b65 --- /dev/null +++ b/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java @@ -0,0 +1,75 @@ +package com.iluwatar.execute.around; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/12/15 - 3:21 PM + * + * @author Jeroen Meulemeester + */ +public class SimpleFileWriterTest { + + /** + * Create a temporary folder, used to generate files in during this test + */ + @Rule + public final TemporaryFolder testFolder = new TemporaryFolder(); + + /** + * Verify if the given writer is not 'null' + */ + @Test + public void testWriterNotNull() throws Exception { + final File temporaryFile = this.testFolder.newFile(); + new SimpleFileWriter(temporaryFile.getPath(), Assert::assertNotNull); + } + + /** + * Test if the {@link SimpleFileWriter} creates a file if it doesn't exist + */ + @Test + public void testNonExistentFile() throws Exception { + final File nonExistingFile = new File(this.testFolder.getRoot(), "non-existing-file"); + assertFalse(nonExistingFile.exists()); + + new SimpleFileWriter(nonExistingFile.getPath(), Assert::assertNotNull); + assertTrue(nonExistingFile.exists()); + } + + /** + * Test if the data written to the file writer actually gets in the file + */ + @Test + public void testActualWrite() throws Exception { + final String testMessage = "Test message"; + + final File temporaryFile = this.testFolder.newFile(); + assertTrue(temporaryFile.exists()); + + new SimpleFileWriter(temporaryFile.getPath(), writer -> writer.write(testMessage)); + assertTrue(Files.lines(temporaryFile.toPath()).allMatch(testMessage::equals)); + } + + /** + * Verify if an {@link IOException} during the write ripples through + */ + @Test(expected = IOException.class) + public void testIOException() throws Exception { + final File temporaryFile = this.testFolder.newFile(); + new SimpleFileWriter(temporaryFile.getPath(), writer -> { + throw new IOException(""); + }); + } + +} From 4181514c6520aee1437ba27d08ef665d0f1a9b4d Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 12 Dec 2015 20:16:10 +0100 Subject: [PATCH 025/112] Add proper tests for fluent-interface pattern and fixed a little bug --- fluentinterface/pom.xml | 5 + .../lazy/LazyFluentIterable.java | 2 +- .../fluentiterable/FluentIterableTest.java | 180 ++++++++++++++++++ .../lazy/LazyFluentIterableTest.java | 18 ++ .../simple/SimpleFluentIterableTest.java | 18 ++ 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java create mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java create mode 100644 fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index d549d5216..ff10a3814 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -16,5 +16,10 @@ junit test + + org.mockito + mockito-core + test + \ No newline at end of file diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java index 560b10189..44f095289 100644 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java @@ -215,7 +215,7 @@ public class LazyFluentIterable implements FluentIterable { return new DecoratingIterator(iterable.iterator()) { @Override public TYPE computeNext() { - return fromIterator.next(); + return fromIterator.hasNext() ? fromIterator.next() : null; } }; } diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java new file mode 100644 index 000000000..7d4cb0530 --- /dev/null +++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java @@ -0,0 +1,180 @@ +package com.iluwatar.fluentinterface.fluentiterable; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Spliterator; +import java.util.function.Consumer; + +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 static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/12/15 - 7:00 PM + * + * @author Jeroen Meulemeester + */ +public abstract class FluentIterableTest { + + /** + * Create a new {@link FluentIterable} from the given integers + * + * @param integers The integers + * @return The new iterable, use for testing + */ + protected abstract FluentIterable createFluentIterable(final Iterable integers); + + @Test + public void testFirst() throws Exception { + final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); + final Optional first = createFluentIterable(integers).first(); + assertNotNull(first); + assertTrue(first.isPresent()); + assertEquals(integers.get(0), first.get()); + } + + @Test + public void testFirstEmptyCollection() throws Exception { + final List integers = Collections.emptyList(); + final Optional first = createFluentIterable(integers).first(); + assertNotNull(first); + assertFalse(first.isPresent()); + } + + @Test + public void testFirstCount() throws Exception { + final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); + final List first4 = createFluentIterable(integers) + .first(4) + .asList(); + + assertNotNull(first4); + assertEquals(4, first4.size()); + + assertEquals(integers.get(0), first4.get(0)); + assertEquals(integers.get(1), first4.get(1)); + assertEquals(integers.get(2), first4.get(2)); + assertEquals(integers.get(3), first4.get(3)); + } + + @Test + public void testFirstCountLessItems() throws Exception { + final List integers = Arrays.asList(1, 2, 3); + final List first4 = createFluentIterable(integers) + .first(4) + .asList(); + + assertNotNull(first4); + assertEquals(3, first4.size()); + + assertEquals(integers.get(0), first4.get(0)); + assertEquals(integers.get(1), first4.get(1)); + assertEquals(integers.get(2), first4.get(2)); + } + + @Test + public void testLast() throws Exception { + final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); + final Optional last = createFluentIterable(integers).last(); + assertNotNull(last); + assertTrue(last.isPresent()); + assertEquals(integers.get(integers.size() - 1), last.get()); + } + + @Test + public void testLastEmptyCollection() throws Exception { + final List integers = Collections.emptyList(); + final Optional last = createFluentIterable(integers).last(); + assertNotNull(last); + assertFalse(last.isPresent()); + } + + @Test + public void testLastCount() throws Exception { + final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); + final List last4 = createFluentIterable(integers) + .last(4) + .asList(); + + assertNotNull(last4); + assertEquals(4, last4.size()); + assertEquals(Integer.valueOf(3), last4.get(0)); + assertEquals(Integer.valueOf(10), last4.get(1)); + assertEquals(Integer.valueOf(9), last4.get(2)); + assertEquals(Integer.valueOf(8), last4.get(3)); + } + + @Test + public void testLastCountLessItems() throws Exception { + final List integers = Arrays.asList(1, 2, 3); + final List last4 = createFluentIterable(integers) + .last(4) + .asList(); + + assertNotNull(last4); + assertEquals(3, last4.size()); + + assertEquals(Integer.valueOf(1), last4.get(0)); + assertEquals(Integer.valueOf(2), last4.get(1)); + assertEquals(Integer.valueOf(3), last4.get(2)); + } + + @Test + public void testFilter() throws Exception { + final List integers = Arrays.asList(1, 2, 3, 10, 9, 8); + final List evenItems = createFluentIterable(integers) + .filter(i -> i % 2 == 0) + .asList(); + + assertNotNull(evenItems); + assertEquals(3, evenItems.size()); + assertEquals(Integer.valueOf(2), evenItems.get(0)); + assertEquals(Integer.valueOf(10), evenItems.get(1)); + assertEquals(Integer.valueOf(8), evenItems.get(2)); + } + + @Test + public void testMap() throws Exception { + final List integers = Arrays.asList(1, 2, 3); + final List longs = createFluentIterable(integers) + .map(Integer::longValue) + .asList(); + + assertNotNull(longs); + assertEquals(integers.size(), longs.size()); + assertEquals(Long.valueOf(1), longs.get(0)); + assertEquals(Long.valueOf(2), longs.get(1)); + assertEquals(Long.valueOf(3), longs.get(2)); + } + + @Test + public void testForEach() throws Exception { + final List integers = Arrays.asList(1, 2, 3); + + final Consumer consumer = mock(Consumer.class); + createFluentIterable(integers).forEach(consumer); + + verify(consumer, times(1)).accept(Integer.valueOf(1)); + verify(consumer, times(1)).accept(Integer.valueOf(2)); + verify(consumer, times(1)).accept(Integer.valueOf(3)); + verifyNoMoreInteractions(consumer); + + } + + @Test + public void testSpliterator() throws Exception { + final List integers = Arrays.asList(1, 2, 3); + final Spliterator split = createFluentIterable(integers).spliterator(); + assertNotNull(split); + } + +} \ No newline at end of file diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java new file mode 100644 index 000000000..aa51327e3 --- /dev/null +++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.fluentinterface.fluentiterable.lazy; + +import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; +import com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest; + +/** + * Date: 12/12/15 - 7:56 PM + * + * @author Jeroen Meulemeester + */ +public class LazyFluentIterableTest extends FluentIterableTest { + + @Override + protected FluentIterable createFluentIterable(Iterable integers) { + return LazyFluentIterable.from(integers); + } + +} diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java new file mode 100644 index 000000000..360d6e222 --- /dev/null +++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.fluentinterface.fluentiterable.simple; + +import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; +import com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest; + +/** + * Date: 12/12/15 - 7:56 PM + * + * @author Jeroen Meulemeester + */ +public class SimpleFluentIterableTest extends FluentIterableTest { + + @Override + protected FluentIterable createFluentIterable(Iterable integers) { + return SimpleFluentIterable.fromCopyOf(integers); + } + +} From 3dc370e2d17677419b3c7f824210876ecb22fce4 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 12 Dec 2015 22:43:47 +0100 Subject: [PATCH 026/112] Add proper tests for flux pattern --- flux/pom.xml | 5 + .../com/iluwatar/flux/action/ContentTest.java | 24 +++++ .../iluwatar/flux/action/MenuItemTest.java | 24 +++++ .../flux/dispatcher/DispatcherTest.java | 92 +++++++++++++++++++ .../iluwatar/flux/store/ContentStoreTest.java | 47 ++++++++++ .../iluwatar/flux/store/MenuStoreTest.java | 47 ++++++++++ .../iluwatar/flux/view/ContentViewTest.java | 33 +++++++ .../com/iluwatar/flux/view/MenuViewTest.java | 50 ++++++++++ 8 files changed, 322 insertions(+) create mode 100644 flux/src/test/java/com/iluwatar/flux/action/ContentTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java create mode 100644 flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java diff --git a/flux/pom.xml b/flux/pom.xml index 3b06d299c..7b0afd626 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java b/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java new file mode 100644 index 000000000..7781c1d90 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/action/ContentTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.flux.action; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/12/15 - 10:11 PM + * + * @author Jeroen Meulemeester + */ +public class ContentTest { + + @Test + public void testToString() throws Exception { + for (final Content content : Content.values()) { + final String toString = content.toString(); + assertNotNull(toString); + assertFalse(toString.trim().isEmpty()); + } + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java b/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java new file mode 100644 index 000000000..02fa781e6 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.flux.action; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/12/15 - 10:15 PM + * + * @author Jeroen Meulemeester + */ +public class MenuItemTest { + + @Test + public void testToString() throws Exception { + for (final MenuItem menuItem : MenuItem.values()) { + final String toString = menuItem.toString(); + assertNotNull(toString); + assertFalse(toString.trim().isEmpty()); + } + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java b/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java new file mode 100644 index 000000000..8e1977dd8 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java @@ -0,0 +1,92 @@ +package com.iluwatar.flux.dispatcher; + +import com.iluwatar.flux.action.Action; +import com.iluwatar.flux.action.ActionType; +import com.iluwatar.flux.action.Content; +import com.iluwatar.flux.action.ContentAction; +import com.iluwatar.flux.action.MenuAction; +import com.iluwatar.flux.action.MenuItem; +import com.iluwatar.flux.store.Store; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/12/15 - 8:22 PM + * + * @author Jeroen Meulemeester + */ +public class DispatcherTest { + + /** + * Dispatcher is a singleton with no way to reset it's internal state back to the beginning. + * Replace the instance with a fresh one before each test to make sure test cases have no + * influence on each other. + */ + @Before + public void setUp() throws Exception { + final Constructor constructor; + constructor = Dispatcher.class.getDeclaredConstructor(); + constructor.setAccessible(true); + + final Field field = Dispatcher.class.getDeclaredField("instance"); + field.setAccessible(true); + field.set(Dispatcher.getInstance(), constructor.newInstance()); + } + + @Test + public void testGetInstance() throws Exception { + assertNotNull(Dispatcher.getInstance()); + assertSame(Dispatcher.getInstance(), Dispatcher.getInstance()); + } + + @Test + public void testMenuItemSelected() throws Exception { + final Dispatcher dispatcher = Dispatcher.getInstance(); + + final Store store = mock(Store.class); + dispatcher.registerStore(store); + dispatcher.menuItemSelected(MenuItem.HOME); + dispatcher.menuItemSelected(MenuItem.COMPANY); + + // We expect 4 events, 2 menu selections and 2 content change actions + final ArgumentCaptor actionCaptor = ArgumentCaptor.forClass(Action.class); + verify(store, times(4)).onAction(actionCaptor.capture()); + verifyNoMoreInteractions(store); + + final List actions = actionCaptor.getAllValues(); + final List menuActions = actions.stream() + .filter(a -> a.getType().equals(ActionType.MENU_ITEM_SELECTED)) + .map(a -> (MenuAction) a) + .collect(Collectors.toList()); + + final List contentActions = actions.stream() + .filter(a -> a.getType().equals(ActionType.CONTENT_CHANGED)) + .map(a -> (ContentAction) a) + .collect(Collectors.toList()); + + assertEquals(2, menuActions.size()); + assertEquals(1, menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.HOME::equals).count()); + assertEquals(1, menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.COMPANY::equals).count()); + + assertEquals(2, contentActions.size()); + assertEquals(1, contentActions.stream().map(ContentAction::getContent).filter(Content.PRODUCTS::equals).count()); + assertEquals(1, contentActions.stream().map(ContentAction::getContent).filter(Content.COMPANY::equals).count()); + + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java b/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java new file mode 100644 index 000000000..7c9ce0a69 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java @@ -0,0 +1,47 @@ +package com.iluwatar.flux.store; + +import com.iluwatar.flux.action.Content; +import com.iluwatar.flux.action.ContentAction; +import com.iluwatar.flux.action.MenuAction; +import com.iluwatar.flux.action.MenuItem; +import com.iluwatar.flux.view.View; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/12/15 - 10:18 PM + * + * @author Jeroen Meulemeester + */ +public class ContentStoreTest { + + @Test + public void testOnAction() throws Exception { + final ContentStore contentStore = new ContentStore(); + + final View view = mock(View.class); + contentStore.registerView(view); + + verifyZeroInteractions(view); + + // Content should not react on menu action ... + contentStore.onAction(new MenuAction(MenuItem.PRODUCTS)); + verifyZeroInteractions(view); + + // ... but it should react on a content action + contentStore.onAction(new ContentAction(Content.COMPANY)); + verify(view, times(1)).storeChanged(eq(contentStore)); + verifyNoMoreInteractions(view); + assertEquals(Content.COMPANY, contentStore.getContent()); + + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java b/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java new file mode 100644 index 000000000..2e7f80590 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java @@ -0,0 +1,47 @@ +package com.iluwatar.flux.store; + +import com.iluwatar.flux.action.Content; +import com.iluwatar.flux.action.ContentAction; +import com.iluwatar.flux.action.MenuAction; +import com.iluwatar.flux.action.MenuItem; +import com.iluwatar.flux.view.View; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/12/15 - 10:18 PM + * + * @author Jeroen Meulemeester + */ +public class MenuStoreTest { + + @Test + public void testOnAction() throws Exception { + final MenuStore menuStore = new MenuStore(); + + final View view = mock(View.class); + menuStore.registerView(view); + + verifyZeroInteractions(view); + + // Menu should not react on content action ... + menuStore.onAction(new ContentAction(Content.COMPANY)); + verifyZeroInteractions(view); + + // ... but it should react on a menu action + menuStore.onAction(new MenuAction(MenuItem.PRODUCTS)); + verify(view, times(1)).storeChanged(eq(menuStore)); + verifyNoMoreInteractions(view); + assertEquals(MenuItem.PRODUCTS, menuStore.getSelected()); + + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java b/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java new file mode 100644 index 000000000..49cecd24a --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.flux.view; + +import com.iluwatar.flux.action.Content; +import com.iluwatar.flux.store.ContentStore; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/12/15 - 10:31 PM + * + * @author Jeroen Meulemeester + */ +public class ContentViewTest { + + @Test + public void testStoreChanged() throws Exception { + final ContentStore store = mock(ContentStore.class); + when(store.getContent()).thenReturn(Content.PRODUCTS); + + final ContentView view = new ContentView(); + view.storeChanged(store); + + verify(store, times(1)).getContent(); + verifyNoMoreInteractions(store); + } + +} diff --git a/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java b/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java new file mode 100644 index 000000000..2534515b0 --- /dev/null +++ b/flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java @@ -0,0 +1,50 @@ +package com.iluwatar.flux.view; + +import com.iluwatar.flux.action.Action; +import com.iluwatar.flux.action.MenuItem; +import com.iluwatar.flux.dispatcher.Dispatcher; +import com.iluwatar.flux.store.MenuStore; +import com.iluwatar.flux.store.Store; + +import org.junit.Test; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/12/15 - 10:31 PM + * + * @author Jeroen Meulemeester + */ +public class MenuViewTest { + + @Test + public void testStoreChanged() throws Exception { + final MenuStore store = mock(MenuStore.class); + when(store.getSelected()).thenReturn(MenuItem.HOME); + + final MenuView view = new MenuView(); + view.storeChanged(store); + + verify(store, times(1)).getSelected(); + verifyNoMoreInteractions(store); + } + + @Test + public void testItemClicked() throws Exception { + final Store store = mock(Store.class); + Dispatcher.getInstance().registerStore(store); + + final MenuView view = new MenuView(); + view.itemClicked(MenuItem.PRODUCTS); + + // We should receive a menu click action and a content changed action + verify(store, times(2)).onAction(any(Action.class)); + + } + +} From ca14e8ddad2cf84224ad740d86e1b0f34a4fc228 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 13 Dec 2015 11:42:25 +0100 Subject: [PATCH 027/112] Add proper tests for flyweight pattern --- .../com/iluwatar/flyweight/AlchemistShop.java | 19 +++++++++ .../iluwatar/flyweight/AlchemistShopTest.java | 40 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java index 15206a84a..a48abbcb0 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java @@ -1,6 +1,7 @@ package com.iluwatar.flyweight; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -39,6 +40,24 @@ public class AlchemistShop { bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER)); } + /** + * Get a read-only list of all the items on the top shelf + * + * @return The top shelf potions + */ + public final List getTopShelf() { + return Collections.unmodifiableList(this.topShelf); + } + + /** + * Get a read-only list of all the items on the bottom shelf + * + * @return The bottom shelf potions + */ + public final List getBottomShelf() { + return Collections.unmodifiableList(this.bottomShelf); + } + public void enumerate() { System.out.println("Enumerating top shelf potions\n"); diff --git a/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java b/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java new file mode 100644 index 000000000..d99a98cf9 --- /dev/null +++ b/flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java @@ -0,0 +1,40 @@ +package com.iluwatar.flyweight; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/12/15 - 10:54 PM + * + * @author Jeroen Meulemeester + */ +public class AlchemistShopTest { + + @Test + public void testShop() throws Exception { + final AlchemistShop shop = new AlchemistShop(); + + final List bottomShelf = shop.getBottomShelf(); + assertNotNull(bottomShelf); + assertEquals(5, bottomShelf.size()); + + final List topShelf = shop.getTopShelf(); + assertNotNull(topShelf); + assertEquals(8, topShelf.size()); + + final List allPotions = new ArrayList<>(); + allPotions.addAll(topShelf); + allPotions.addAll(bottomShelf); + + // There are 13 potion instances, but only 5 unique instance types + assertEquals(13, allPotions.size()); + assertEquals(5, allPotions.stream().map(System::identityHashCode).distinct().count()); + + } + +} From dbca06a9e7bdcddafbc842ddef3f2b0b9b760b59 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 13 Dec 2015 12:55:13 +0100 Subject: [PATCH 028/112] Added proper tests for half-sync-half-async --- half-sync-half-async/pom.xml | 5 ++ .../AsynchronousService.java | 1 + .../AsynchronousServiceTest.java | 79 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 2490e9214..ce8689cee 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java index 457dffa20..3be340c02 100644 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java +++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java @@ -50,6 +50,7 @@ public class AsynchronousService { task.onPreCall(); } catch (Exception e) { task.onError(e); + return; } service.submit(new FutureTask(task) { diff --git a/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java b/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java new file mode 100644 index 000000000..01c905039 --- /dev/null +++ b/half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java @@ -0,0 +1,79 @@ +package com.iluwatar.halfsynchalfasync; + +import org.junit.Test; +import org.mockito.InOrder; + +import java.io.IOException; +import java.util.concurrent.LinkedBlockingQueue; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/12/15 - 11:15 PM + * + * @author Jeroen Meulemeester + */ +public class AsynchronousServiceTest { + + @Test + public void testPerfectExecution() throws Exception { + final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); + final AsyncTask task = mock(AsyncTask.class); + final Object result = new Object(); + when(task.call()).thenReturn(result); + service.execute(task); + + verify(task, timeout(2000)).onPostCall(eq(result)); + + final InOrder inOrder = inOrder(task); + inOrder.verify(task, times(1)).onPreCall(); + inOrder.verify(task, times(1)).call(); + inOrder.verify(task, times(1)).onPostCall(eq(result)); + + verifyNoMoreInteractions(task); + } + + @Test + public void testCallException() throws Exception { + final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); + final AsyncTask task = mock(AsyncTask.class); + final IOException exception = new IOException(); + when(task.call()).thenThrow(exception); + service.execute(task); + + verify(task, timeout(2000)).onError(eq(exception)); + + final InOrder inOrder = inOrder(task); + inOrder.verify(task, times(1)).onPreCall(); + inOrder.verify(task, times(1)).call(); + inOrder.verify(task, times(1)).onError(exception); + + verifyNoMoreInteractions(task); + } + + @Test + public void testPreCallException() throws Exception { + final AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>()); + final AsyncTask task = mock(AsyncTask.class); + final IllegalStateException exception = new IllegalStateException(); + doThrow(exception).when(task).onPreCall(); + service.execute(task); + + verify(task, timeout(2000)).onError(eq(exception)); + + final InOrder inOrder = inOrder(task); + inOrder.verify(task, times(1)).onPreCall(); + inOrder.verify(task, times(1)).onError(exception); + + verifyNoMoreInteractions(task); + } + +} \ No newline at end of file From 9059d2b96cff7bf39ac5aa8afca47a3f83abff9d Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 13 Dec 2015 13:58:39 +0100 Subject: [PATCH 029/112] Added proper tests for front-controller pattern --- front-controller/pom.xml | 5 ++ .../controller/ApplicationExceptionTest.java | 20 ++++++ .../front/controller/CommandTest.java | 62 +++++++++++++++++++ .../front/controller/FrontControllerTest.java | 61 ++++++++++++++++++ .../iluwatar/front/controller/StdOutTest.java | 54 ++++++++++++++++ .../iluwatar/front/controller/ViewTest.java | 61 ++++++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 33a30c258..91ad6c1ab 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -15,5 +15,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java new file mode 100644 index 000000000..18bdf0d13 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java @@ -0,0 +1,20 @@ +package com.iluwatar.front.controller; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Date: 12/13/15 - 1:35 PM + * + * @author Jeroen Meulemeester + */ +public class ApplicationExceptionTest { + + @Test + public void testCause() throws Exception { + final Exception cause = new Exception(); + assertSame(cause, new ApplicationException(cause).getCause()); + } + +} \ No newline at end of file diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java new file mode 100644 index 000000000..fa85caa39 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java @@ -0,0 +1,62 @@ +package com.iluwatar.front.controller; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/13/15 - 1:39 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class CommandTest extends StdOutTest { + + @Parameters + public static List data() { + final List parameters = new ArrayList<>(); + parameters.add(new Object[]{"Archer", "Displaying archers"}); + parameters.add(new Object[]{"Catapult", "Displaying catapults"}); + parameters.add(new Object[]{"NonExistentCommand", "Error 500"}); + return parameters; + } + + /** + * The view that's been tested + */ + private final String request; + + /** + * The expected display message + */ + private final String displayMessage; + + /** + * Create a new instance of the {@link CommandTest} with the given view and expected message + * + * @param request The request that's been tested + * @param displayMessage The expected display message + */ + public CommandTest(final String request, final String displayMessage) { + this.displayMessage = displayMessage; + this.request = request; + } + + @Test + public void testDisplay() { + final FrontController frontController = new FrontController(); + verifyZeroInteractions(getStdOutMock()); + frontController.handleRequest(request); + verify(getStdOutMock()).println(displayMessage); + verifyNoMoreInteractions(getStdOutMock()); + } + +} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java new file mode 100644 index 000000000..9bc4253c0 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java @@ -0,0 +1,61 @@ +package com.iluwatar.front.controller; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/13/15 - 1:39 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class FrontControllerTest extends StdOutTest { + + @Parameters + public static List data() { + final List parameters = new ArrayList<>(); + parameters.add(new Object[]{new ArcherCommand(), "Displaying archers"}); + parameters.add(new Object[]{new CatapultCommand(), "Displaying catapults"}); + parameters.add(new Object[]{new UnknownCommand(), "Error 500"}); + return parameters; + } + + /** + * The view that's been tested + */ + private final Command command; + + /** + * The expected display message + */ + private final String displayMessage; + + /** + * Create a new instance of the {@link FrontControllerTest} with the given view and expected message + * + * @param command The command that's been tested + * @param displayMessage The expected display message + */ + public FrontControllerTest(final Command command, final String displayMessage) { + this.displayMessage = displayMessage; + this.command = command; + } + + @Test + public void testDisplay() { + verifyZeroInteractions(getStdOutMock()); + this.command.process(); + verify(getStdOutMock()).println(displayMessage); + verifyNoMoreInteractions(getStdOutMock()); + } + +} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java new file mode 100644 index 000000000..31d061b08 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java @@ -0,0 +1,54 @@ +package com.iluwatar.front.controller; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since the actions of the views don't have + * any influence on any other accessible objects, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java new file mode 100644 index 000000000..fb2df1c60 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java @@ -0,0 +1,61 @@ +package com.iluwatar.front.controller; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/13/15 - 1:39 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class ViewTest extends StdOutTest { + + @Parameters + public static List data() { + final List parameters = new ArrayList<>(); + parameters.add(new Object[]{new ArcherView(), "Displaying archers"}); + parameters.add(new Object[]{new CatapultView(), "Displaying catapults"}); + parameters.add(new Object[]{new ErrorView(), "Error 500"}); + return parameters; + } + + /** + * The view that's been tested + */ + private final View view; + + /** + * The expected display message + */ + private final String displayMessage; + + /** + * Create a new instance of the {@link ViewTest} with the given view and expected message + * + * @param view The view that's been tested + * @param displayMessage The expected display message + */ + public ViewTest(final View view, final String displayMessage) { + this.displayMessage = displayMessage; + this.view = view; + } + + @Test + public void testDisplay() { + verifyZeroInteractions(getStdOutMock()); + this.view.display(); + verify(getStdOutMock()).println(displayMessage); + verifyNoMoreInteractions(getStdOutMock()); + } + +} \ No newline at end of file From de78490d29879936dea373087a5cf400158db830 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 13 Dec 2015 15:18:13 +0100 Subject: [PATCH 030/112] Added tests for intercepting-filter pattern --- intercepting-filter/pom.xml | 5 + .../intercepting/filter/NameFilter.java | 2 +- .../filter/FilterManagerTest.java | 46 +++++++++ .../intercepting/filter/FilterTest.java | 95 +++++++++++++++++++ .../intercepting/filter/OrderTest.java | 51 ++++++++++ 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java create mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java create mode 100644 intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index c69f40ee5..2c10af5d0 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java index a458e475b..2f431caad 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java @@ -14,7 +14,7 @@ public class NameFilter extends AbstractFilter { String result = super.execute(order); if (order.getName() == null || order.getName().isEmpty() || order.getName().matches(".*[^\\w|\\s]+.*")) { - return result + "Invalid order! "; + return result + "Invalid name! "; } else { return result; } diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java new file mode 100644 index 000000000..6806cd70a --- /dev/null +++ b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java @@ -0,0 +1,46 @@ +package com.iluwatar.intercepting.filter; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/13/15 - 3:01 PM + * + * @author Jeroen Meulemeester + */ +public class FilterManagerTest { + + @Test + public void testFilterRequest() throws Exception { + final Target target = mock(Target.class); + final FilterManager filterManager = new FilterManager(target); + assertEquals("RUNNING...", filterManager.filterRequest(mock(Order.class))); + verifyZeroInteractions(target); + } + + @Test + public void testAddFilter() throws Exception { + final Target target = mock(Target.class); + final FilterManager filterManager = new FilterManager(target); + + verifyZeroInteractions(target); + + final Filter filter = mock(Filter.class); + when(filter.execute(any(Order.class))).thenReturn("filter"); + + filterManager.addFilter(filter); + + final Order order = mock(Order.class); + assertEquals("filter", filterManager.filterRequest(order)); + + verify(filter, times(1)).execute(any(Order.class)); + verifyZeroInteractions(target, filter, order); + } +} \ No newline at end of file diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java new file mode 100644 index 000000000..f15760f08 --- /dev/null +++ b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java @@ -0,0 +1,95 @@ +package com.iluwatar.intercepting.filter; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.TestCase.assertSame; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Date: 12/13/15 - 2:17 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class FilterTest { + + private static final Order PERFECT_ORDER = new Order("name", "12345678901", "addr", "dep", "order"); + private static final Order WRONG_ORDER = new Order("name", "12345678901", "addr", "dep", ""); + private static final Order WRONG_DEPOSIT = new Order("name", "12345678901", "addr", "", "order"); + private static final Order WRONG_ADDRESS = new Order("name", "12345678901", "", "dep", "order"); + private static final Order WRONG_CONTACT = new Order("name", "", "addr", "dep", "order"); + private static final Order WRONG_NAME = new Order("", "12345678901", "addr", "dep", "order"); + + @Parameters + public static List getTestData() { + final List testData = new ArrayList<>(); + testData.add(new Object[]{new NameFilter(), PERFECT_ORDER, ""}); + testData.add(new Object[]{new NameFilter(), WRONG_NAME, "Invalid name!"}); + testData.add(new Object[]{new NameFilter(), WRONG_CONTACT, ""}); + testData.add(new Object[]{new NameFilter(), WRONG_ADDRESS, ""}); + testData.add(new Object[]{new NameFilter(), WRONG_DEPOSIT, ""}); + testData.add(new Object[]{new NameFilter(), WRONG_ORDER, ""}); + + testData.add(new Object[]{new ContactFilter(), PERFECT_ORDER, ""}); + testData.add(new Object[]{new ContactFilter(), WRONG_NAME, ""}); + testData.add(new Object[]{new ContactFilter(), WRONG_CONTACT, "Invalid contact number!"}); + testData.add(new Object[]{new ContactFilter(), WRONG_ADDRESS, ""}); + testData.add(new Object[]{new ContactFilter(), WRONG_DEPOSIT, ""}); + testData.add(new Object[]{new ContactFilter(), WRONG_ORDER, ""}); + + testData.add(new Object[]{new AddressFilter(), PERFECT_ORDER, ""}); + testData.add(new Object[]{new AddressFilter(), WRONG_NAME, ""}); + testData.add(new Object[]{new AddressFilter(), WRONG_CONTACT, ""}); + testData.add(new Object[]{new AddressFilter(), WRONG_ADDRESS, "Invalid address!"}); + testData.add(new Object[]{new AddressFilter(), WRONG_DEPOSIT, ""}); + testData.add(new Object[]{new AddressFilter(), WRONG_ORDER, ""}); + + testData.add(new Object[]{new DepositFilter(), PERFECT_ORDER, ""}); + testData.add(new Object[]{new DepositFilter(), WRONG_NAME, ""}); + testData.add(new Object[]{new DepositFilter(), WRONG_CONTACT, ""}); + testData.add(new Object[]{new DepositFilter(), WRONG_ADDRESS, ""}); + testData.add(new Object[]{new DepositFilter(), WRONG_DEPOSIT, "Invalid deposit number!"}); + testData.add(new Object[]{new DepositFilter(), WRONG_ORDER, ""}); + + testData.add(new Object[]{new OrderFilter(), PERFECT_ORDER, ""}); + testData.add(new Object[]{new OrderFilter(), WRONG_NAME, ""}); + testData.add(new Object[]{new OrderFilter(), WRONG_CONTACT, ""}); + testData.add(new Object[]{new OrderFilter(), WRONG_ADDRESS, ""}); + testData.add(new Object[]{new OrderFilter(), WRONG_DEPOSIT, ""}); + testData.add(new Object[]{new OrderFilter(), WRONG_ORDER, "Invalid order!"}); + + return testData; + } + + private final Filter filter; + private final Order order; + private final String result; + + public FilterTest(Filter filter, Order order, String result) { + this.filter = filter; + this.order = order; + this.result = result; + } + + @Test + public void testExecute() throws Exception { + final String result = this.filter.execute(this.order); + assertNotNull(result); + assertEquals(this.result, result.trim()); + } + + @Test + public void testNext() throws Exception { + assertNull(this.filter.getNext()); + assertSame(this.filter, this.filter.getLast()); + } + +} diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java new file mode 100644 index 000000000..70862ed0f --- /dev/null +++ b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java @@ -0,0 +1,51 @@ +package com.iluwatar.intercepting.filter; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/13/15 - 2:57 PM + * + * @author Jeroen Meulemeester + */ +public class OrderTest { + + private static final String EXPECTED_VALUE = "test"; + + @Test + public void testSetName() throws Exception { + final Order order = new Order(); + order.setName(EXPECTED_VALUE); + assertEquals(EXPECTED_VALUE, order.getName()); + } + + @Test + public void testSetContactNumber() throws Exception { + final Order order = new Order(); + order.setContactNumber(EXPECTED_VALUE); + assertEquals(EXPECTED_VALUE, order.getContactNumber()); + } + + @Test + public void testSetAddress() throws Exception { + final Order order = new Order(); + order.setAddress(EXPECTED_VALUE); + assertEquals(EXPECTED_VALUE, order.getAddress()); + } + + @Test + public void testSetDepositNumber() throws Exception { + final Order order = new Order(); + order.setDepositNumber(EXPECTED_VALUE); + assertEquals(EXPECTED_VALUE, order.getDepositNumber()); + } + + @Test + public void testSetOrder() throws Exception { + final Order order = new Order(); + order.setOrder(EXPECTED_VALUE); + assertEquals(EXPECTED_VALUE, order.getOrder()); + } + +} From 323e4c87515ddf96e36d767f530e5f1ea97818de Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 14 Dec 2015 12:46:07 +0100 Subject: [PATCH 031/112] Added tests for interpreter pattern --- .../iluwatar/interpreter/ExpressionTest.java | 111 ++++++++++++++++++ .../interpreter/MinusExpressionTest.java | 38 ++++++ .../interpreter/MultiplyExpressionTest.java | 38 ++++++ .../interpreter/NumberExpressionTest.java | 52 ++++++++ .../interpreter/PlusExpressionTest.java | 38 ++++++ 5 files changed, 277 insertions(+) create mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java create mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java create mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java create mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java create mode 100644 interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java new file mode 100644 index 000000000..2cdee9966 --- /dev/null +++ b/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java @@ -0,0 +1,111 @@ +package com.iluwatar.interpreter; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/14/15 - 11:48 AM + * + * @author Jeroen Meulemeester + */ +public abstract class ExpressionTest { + + /** + * Generate inputs ranging from -10 to 10 for both input params and calculate the expected result + * + * @param resultCalc The function used to calculate the expected result + * @return A data set with test entries + */ + static List prepareParameters(final BiFunction resultCalc) { + final List testData = new ArrayList<>(); + for (int i = -10; i < 10; i++) { + for (int j = -10; j < 10; j++) { + testData.add(new Object[]{ + new NumberExpression(i), + new NumberExpression(j), + resultCalc.apply(i, j) + }); + } + } + return testData; + } + + /** + * The input used as first parameter during the test + */ + private final NumberExpression first; + + /** + * The input used as second parameter during the test + */ + private final NumberExpression second; + + /** + * The expected result of the calculation, taking the first and second parameter in account + */ + private final int result; + + /** + * The expected {@link E#toString()} response + */ + private final String expectedToString; + + /** + * Factory, used to create a new test object instance with the correct first and second parameter + */ + private final BiFunction factory; + + /** + * Create a new test instance with the given parameters and expected results + * + * @param first The input used as first parameter during the test + * @param second The input used as second parameter during the test + * @param result The expected result of the tested expression + * @param expectedToString The expected {@link E#toString()} response + * @param factory Factory, used to create a new test object instance + */ + ExpressionTest(final NumberExpression first, final NumberExpression second, final int result, + final String expectedToString, final BiFunction factory) { + + this.first = first; + this.second = second; + this.result = result; + this.expectedToString = expectedToString; + this.factory = factory; + } + + /** + * Get the first parameter + * + * @return The first parameter + */ + final NumberExpression getFirst() { + return this.first; + } + + /** + * Verify if the expression calculates the correct result when calling {@link E#interpret()} + */ + @Test + public void testInterpret() { + final E expression = this.factory.apply(this.first, this.second); + assertNotNull(expression); + assertEquals(this.result, expression.interpret()); + } + + /** + * Verify if the expression has the expected {@link E#toString()} value + */ + @Test + public void testToString() { + final E expression = this.factory.apply(this.first, this.second); + assertNotNull(expression); + assertEquals(expectedToString, expression.toString()); + } +} diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java new file mode 100644 index 000000000..3b6d322fe --- /dev/null +++ b/interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.interpreter; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.List; + +/** + * Date: 12/14/15 - 12:08 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class MinusExpressionTest extends ExpressionTest { + + /** + * Create a new set of test entries with the expected result + * + * @return The list of parameters used during this test + */ + @Parameters + public static List data() { + return prepareParameters((f, s) -> f - s); + } + + /** + * Create a new test instance using the given test parameters and expected result + * + * @param first The first expression parameter + * @param second The second expression parameter + * @param result The expected result + */ + public MinusExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { + super(first, second, result, "-", MinusExpression::new); + } + +} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java new file mode 100644 index 000000000..91ecdb008 --- /dev/null +++ b/interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.interpreter; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.List; + +/** + * Date: 12/14/15 - 12:08 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class MultiplyExpressionTest extends ExpressionTest { + + /** + * Create a new set of test entries with the expected result + * + * @return The list of parameters used during this test + */ + @Parameters + public static List data() { + return prepareParameters((f, s) -> f * s); + } + + /** + * Create a new test instance using the given test parameters and expected result + * + * @param first The first expression parameter + * @param second The second expression parameter + * @param result The expected result + */ + public MultiplyExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { + super(first, second, result, "*", MultiplyExpression::new); + } + +} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java new file mode 100644 index 000000000..2c4a35be7 --- /dev/null +++ b/interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java @@ -0,0 +1,52 @@ +package com.iluwatar.interpreter; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/14/15 - 12:08 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class NumberExpressionTest extends ExpressionTest { + + /** + * Create a new set of test entries with the expected result + * + * @return The list of parameters used during this test + */ + @Parameters + public static List data() { + return prepareParameters((f, s) -> f); + } + + /** + * Create a new test instance using the given test parameters and expected result + * + * @param first The first expression parameter + * @param second The second expression parameter + * @param result The expected result + */ + public NumberExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { + super(first, second, result, "number", (f, s) -> f); + } + + /** + * Verify if the {@link NumberExpression#NumberExpression(String)} constructor works as expected + */ + @Test + public void testFromString() throws Exception { + final int expectedValue = getFirst().interpret(); + final String testStingValue = String.valueOf(expectedValue); + final NumberExpression numberExpression = new NumberExpression(testStingValue); + assertEquals(expectedValue, numberExpression.interpret()); + } + +} \ No newline at end of file diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java new file mode 100644 index 000000000..065213631 --- /dev/null +++ b/interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.interpreter; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.List; + +/** + * Date: 12/14/15 - 12:08 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class PlusExpressionTest extends ExpressionTest { + + /** + * Create a new set of test entries with the expected result + * + * @return The list of parameters used during this test + */ + @Parameters + public static List data() { + return prepareParameters((f, s) -> f + s); + } + + /** + * Create a new test instance using the given test parameters and expected result + * + * @param first The first expression parameter + * @param second The second expression parameter + * @param result The expected result + */ + public PlusExpressionTest(final NumberExpression first, final NumberExpression second, final int result) { + super(first, second, result, "+", PlusExpression::new); + } + +} \ No newline at end of file From 25cacdbbc9cde921a2836ecac05996a524f14c6b Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 14 Dec 2015 15:14:48 +0100 Subject: [PATCH 032/112] Added tests for iterator pattern --- .../iluwatar/iterator/TreasureChestTest.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java diff --git a/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java b/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java new file mode 100644 index 000000000..a32066ea8 --- /dev/null +++ b/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java @@ -0,0 +1,108 @@ +package com.iluwatar.iterator; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +/** + * Date: 12/14/15 - 2:58 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class TreasureChestTest { + + /** + * Create a list of all expected items in the chest. + * + * @return The set of all expected items in the chest + */ + @Parameterized.Parameters + public static List data() { + final List parameters = new ArrayList<>(); + parameters.add(new Object[]{new Item(ItemType.POTION, "Potion of courage")}); + parameters.add(new Object[]{new Item(ItemType.RING, "Ring of shadows")}); + parameters.add(new Object[]{new Item(ItemType.POTION, "Potion of wisdom")}); + parameters.add(new Object[]{new Item(ItemType.POTION, "Potion of blood")}); + parameters.add(new Object[]{new Item(ItemType.WEAPON, "Sword of silver +1")}); + parameters.add(new Object[]{new Item(ItemType.POTION, "Potion of rust")}); + parameters.add(new Object[]{new Item(ItemType.POTION, "Potion of healing")}); + parameters.add(new Object[]{new Item(ItemType.RING, "Ring of armor")}); + parameters.add(new Object[]{new Item(ItemType.WEAPON, "Steel halberd")}); + parameters.add(new Object[]{new Item(ItemType.WEAPON, "Dagger of poison")}); + return parameters; + } + + /** + * One of the expected items in the chest + */ + private final Item expectedItem; + + /** + * Create a new test instance, test if the given expected item can be retrieved from the chest + * + * @param expectedItem One of the items that should be in the chest + */ + public TreasureChestTest(final Item expectedItem) { + this.expectedItem = expectedItem; + } + + /** + * Test if the expected item can be retrieved from the chest using the {@link ItemIterator} + */ + @Test + public void testIterator() { + final TreasureChest chest = new TreasureChest(); + final ItemIterator iterator = chest.Iterator(expectedItem.getType()); + assertNotNull(iterator); + + while (iterator.hasNext()) { + final Item item = iterator.next(); + assertNotNull(item); + assertEquals(this.expectedItem.getType(), item.getType()); + + final String name = item.toString(); + assertNotNull(name); + if (this.expectedItem.toString().equals(name)) { + return; + } + } + + fail("Expected to find item [" + this.expectedItem + "] using iterator, but we didn't."); + + } + + /** + * Test if the expected item can be retrieved from the chest using the {@link + * TreasureChest#getItems()} method + */ + @Test + public void testGetItems() throws Exception { + final TreasureChest chest = new TreasureChest(); + final List items = chest.getItems(); + assertNotNull(items); + + for (final Item item : items) { + assertNotNull(item); + assertNotNull(item.getType()); + assertNotNull(item.toString()); + + final boolean sameType = this.expectedItem.getType() == item.getType(); + final boolean sameName = this.expectedItem.toString().equals(item.toString()); + if (sameType && sameName) { + return; + } + } + + fail("Expected to find item [" + this.expectedItem + "] in the item list, but we didn't."); + + } + +} \ No newline at end of file From a0151826add1e96c46592466407dc4b9ef7eca8e Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 19 Dec 2015 17:35:49 +0100 Subject: [PATCH 033/112] Changed page-index to 1 for a better structured navbar --- faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/faq.md b/faq.md index b98bc7589..69f7b795e 100644 --- a/faq.md +++ b/faq.md @@ -3,7 +3,7 @@ layout: page title: FAQ permalink: /faq/ icon: fa-question -page-index: 2 +page-index: 1 --- ### Q1: What is the difference between State and Strategy patterns? {#Q1} @@ -64,4 +64,4 @@ Flyweight. ### Q7: What are the differences between FluentInterface and Builder patterns? {#Q7} -Fluent interfaces are sometimes confused with the Builder pattern, because they share method chaining and a fluent usage. However, fluent interfaces are not primarily used to create shared (mutable) objects, but to configure complex objects without having to respecify the target object on every property change. \ No newline at end of file +Fluent interfaces are sometimes confused with the Builder pattern, because they share method chaining and a fluent usage. However, fluent interfaces are not primarily used to create shared (mutable) objects, but to configure complex objects without having to respecify the target object on every property change. From 5948a82cf2b39bb74bde5b58a217924a2da8c6e5 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 19 Dec 2015 11:52:20 +0100 Subject: [PATCH 034/112] Added tests for layers pattern --- layers/pom.xml | 5 + .../layers/CakeBakingServiceImpl.java | 8 +- .../java/com/iluwatar/layers/CakeInfo.java | 2 +- .../com/iluwatar/layers/CakeLayerInfo.java | 2 +- .../java/com/iluwatar/layers/CakeTopping.java | 2 +- .../com/iluwatar/layers/CakeToppingInfo.java | 2 +- .../layers/CakeBakingExceptionTest.java | 30 ++++ .../layers/CakeBakingServiceImplTest.java | 159 ++++++++++++++++++ .../java/com/iluwatar/layers/CakeTest.java | 97 +++++++++++ .../com/iluwatar/layers/CakeViewImplTest.java | 48 ++++++ .../java/com/iluwatar/layers/StdOutTest.java | 54 ++++++ 11 files changed, 401 insertions(+), 8 deletions(-) create mode 100644 layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java create mode 100644 layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java create mode 100644 layers/src/test/java/com/iluwatar/layers/CakeTest.java create mode 100644 layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java create mode 100644 layers/src/test/java/com/iluwatar/layers/StdOutTest.java diff --git a/layers/pom.xml b/layers/pom.xml index 23b1db192..438c6c5d4 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -32,5 +32,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java b/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java index a519ec2ce..79917842d 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java @@ -30,9 +30,9 @@ public class CakeBakingServiceImpl implements CakeBakingService { @Override public void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException { - List allToppings = getAvailableToppings(); - List matchingToppings = - allToppings.stream().filter((t) -> t.name.equals(cakeInfo.cakeToppingInfo.name)) + List allToppings = getAvailableToppingEntities(); + List matchingToppings = + allToppings.stream().filter((t) -> t.getName().equals(cakeInfo.cakeToppingInfo.name)) .collect(Collectors.toList()); if (matchingToppings.isEmpty()) { throw new CakeBakingException(String.format("Topping %s is not available", @@ -50,7 +50,7 @@ public class CakeBakingServiceImpl implements CakeBakingService { } } CakeToppingDao toppingBean = context.getBean(CakeToppingDao.class); - CakeTopping topping = toppingBean.findOne(matchingToppings.iterator().next().id.get()); + CakeTopping topping = toppingBean.findOne(matchingToppings.iterator().next().getId()); CakeDao cakeBean = context.getBean(CakeDao.class); Cake cake = new Cake(); cake.setTopping(topping); diff --git a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeInfo.java index f60ee9a14..21b7d9ed8 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeInfo.java @@ -34,7 +34,7 @@ public class CakeInfo { @Override public String toString() { - return String.format("CakeInfo id=%d topping=%s layers=%s totalCalories=%d", id.get(), + return String.format("CakeInfo id=%d topping=%s layers=%s totalCalories=%d", id.orElse(-1L), cakeToppingInfo, cakeLayerInfos, calculateTotalCalories()); } } diff --git a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java index 3dff379da..dca81faaa 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java @@ -27,6 +27,6 @@ public class CakeLayerInfo { @Override public String toString() { - return String.format("CakeLayerInfo id=%d name=%s calories=%d", id.get(), name, calories); + return String.format("CakeLayerInfo id=%d name=%s calories=%d", id.orElse(-1L), name, calories); } } diff --git a/layers/src/main/java/com/iluwatar/layers/CakeTopping.java b/layers/src/main/java/com/iluwatar/layers/CakeTopping.java index 6dc9c45fc..9f2107f1e 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeTopping.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeTopping.java @@ -58,7 +58,7 @@ public class CakeTopping { @Override public String toString() { - return String.format("id=%s name=%s calories=%d", name, calories); + return String.format("id=%s name=%s calories=%d", id, name, calories); } public Cake getCake() { diff --git a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java index 4e432ec44..befebc8fe 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java @@ -27,6 +27,6 @@ public class CakeToppingInfo { @Override public String toString() { - return String.format("CakeToppingInfo id=%d name=%s calories=%d", id.get(), name, calories); + return String.format("CakeToppingInfo id=%d name=%s calories=%d", id.orElse(-1L), name, calories); } } diff --git a/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java b/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java new file mode 100644 index 000000000..87381a309 --- /dev/null +++ b/layers/src/test/java/com/iluwatar/layers/CakeBakingExceptionTest.java @@ -0,0 +1,30 @@ +package com.iluwatar.layers; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Date: 12/15/15 - 7:57 PM + * + * @author Jeroen Meulemeester + */ +public class CakeBakingExceptionTest { + + @Test + public void testConstructor() throws Exception { + final CakeBakingException exception = new CakeBakingException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testConstructorWithMessage() throws Exception { + final String expectedMessage = "message"; + final CakeBakingException exception = new CakeBakingException(expectedMessage); + assertEquals(expectedMessage, exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java b/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java new file mode 100644 index 000000000..11caab9ea --- /dev/null +++ b/layers/src/test/java/com/iluwatar/layers/CakeBakingServiceImplTest.java @@ -0,0 +1,159 @@ +package com.iluwatar.layers; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/15/15 - 9:55 PM + * + * @author Jeroen Meulemeester + */ +public class CakeBakingServiceImplTest { + + @Test + public void testLayers() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final List initialLayers = service.getAvailableLayers(); + assertNotNull(initialLayers); + assertTrue(initialLayers.isEmpty()); + + service.saveNewLayer(new CakeLayerInfo("Layer1", 1000)); + service.saveNewLayer(new CakeLayerInfo("Layer2", 2000)); + + final List availableLayers = service.getAvailableLayers(); + assertNotNull(availableLayers); + assertEquals(2, availableLayers.size()); + for (final CakeLayerInfo layer : availableLayers) { + assertNotNull(layer.id); + assertNotNull(layer.name); + assertNotNull(layer.toString()); + assertTrue(layer.calories > 0); + } + + } + + @Test + public void testToppings() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final List initialToppings = service.getAvailableToppings(); + assertNotNull(initialToppings); + assertTrue(initialToppings.isEmpty()); + + service.saveNewTopping(new CakeToppingInfo("Topping1", 1000)); + service.saveNewTopping(new CakeToppingInfo("Topping2", 2000)); + + final List availableToppings = service.getAvailableToppings(); + assertNotNull(availableToppings); + assertEquals(2, availableToppings.size()); + for (final CakeToppingInfo topping : availableToppings) { + assertNotNull(topping.id); + assertNotNull(topping.name); + assertNotNull(topping.toString()); + assertTrue(topping.calories > 0); + } + + } + + @Test + public void testBakeCakes() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final List initialCakes = service.getAllCakes(); + assertNotNull(initialCakes); + assertTrue(initialCakes.isEmpty()); + + final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); + final CakeToppingInfo topping2 = new CakeToppingInfo("Topping2", 2000); + service.saveNewTopping(topping1); + service.saveNewTopping(topping2); + + final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); + final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); + final CakeLayerInfo layer3 = new CakeLayerInfo("Layer3", 2000); + service.saveNewLayer(layer1); + service.saveNewLayer(layer2); + service.saveNewLayer(layer3); + + service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, layer2))); + service.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer3))); + + final List allCakes = service.getAllCakes(); + assertNotNull(allCakes); + assertEquals(2, allCakes.size()); + for (final CakeInfo cakeInfo : allCakes) { + assertNotNull(cakeInfo.id); + assertNotNull(cakeInfo.cakeToppingInfo); + assertNotNull(cakeInfo.cakeLayerInfos); + assertNotNull(cakeInfo.toString()); + assertFalse(cakeInfo.cakeLayerInfos.isEmpty()); + assertTrue(cakeInfo.calculateTotalCalories() > 0); + } + + } + + @Test(expected = CakeBakingException.class) + public void testBakeCakeMissingTopping() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); + final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); + service.saveNewLayer(layer1); + service.saveNewLayer(layer2); + + final CakeToppingInfo missingTopping = new CakeToppingInfo("Topping1", 1000); + service.bakeNewCake(new CakeInfo(missingTopping, Arrays.asList(layer1, layer2))); + } + + @Test(expected = CakeBakingException.class) + public void testBakeCakeMissingLayer() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final List initialCakes = service.getAllCakes(); + assertNotNull(initialCakes); + assertTrue(initialCakes.isEmpty()); + + final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); + service.saveNewTopping(topping1); + + final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); + service.saveNewLayer(layer1); + + final CakeLayerInfo missingLayer = new CakeLayerInfo("Layer2", 2000); + service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, missingLayer))); + + } + + @Test(expected = CakeBakingException.class) + public void testBakeCakesUsedLayer() throws CakeBakingException { + final CakeBakingServiceImpl service = new CakeBakingServiceImpl(); + + final List initialCakes = service.getAllCakes(); + assertNotNull(initialCakes); + assertTrue(initialCakes.isEmpty()); + + final CakeToppingInfo topping1 = new CakeToppingInfo("Topping1", 1000); + final CakeToppingInfo topping2 = new CakeToppingInfo("Topping2", 2000); + service.saveNewTopping(topping1); + service.saveNewTopping(topping2); + + final CakeLayerInfo layer1 = new CakeLayerInfo("Layer1", 1000); + final CakeLayerInfo layer2 = new CakeLayerInfo("Layer2", 2000); + service.saveNewLayer(layer1); + service.saveNewLayer(layer2); + + service.bakeNewCake(new CakeInfo(topping1, Arrays.asList(layer1, layer2))); + service.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer2))); + + } + +} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeTest.java b/layers/src/test/java/com/iluwatar/layers/CakeTest.java new file mode 100644 index 000000000..30d1df0fc --- /dev/null +++ b/layers/src/test/java/com/iluwatar/layers/CakeTest.java @@ -0,0 +1,97 @@ +package com.iluwatar.layers; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/15/15 - 8:02 PM + * + * @author Jeroen Meulemeester + */ +public class CakeTest { + + @Test + public void testSetId() { + final Cake cake = new Cake(); + assertNull(cake.getId()); + + final Long expectedId = Long.valueOf(1234L); + cake.setId(expectedId); + assertEquals(expectedId, cake.getId()); + } + + @Test + public void testSetTopping() { + final Cake cake = new Cake(); + assertNull(cake.getTopping()); + + final CakeTopping expectedTopping = new CakeTopping("DummyTopping", 1000); + cake.setTopping(expectedTopping); + assertEquals(expectedTopping, cake.getTopping()); + } + + @Test + public void testSetLayers() { + final Cake cake = new Cake(); + assertNotNull(cake.getLayers()); + assertTrue(cake.getLayers().isEmpty()); + + final Set expectedLayers = new HashSet<>(); + expectedLayers.add(new CakeLayer("layer1", 1000)); + expectedLayers.add(new CakeLayer("layer2", 2000)); + expectedLayers.add(new CakeLayer("layer3", 3000)); + + cake.setLayers(expectedLayers); + assertEquals(expectedLayers, cake.getLayers()); + } + + @Test + public void testAddLayer() { + final Cake cake = new Cake(); + assertNotNull(cake.getLayers()); + assertTrue(cake.getLayers().isEmpty()); + + final Set initialLayers = new HashSet<>(); + initialLayers.add(new CakeLayer("layer1", 1000)); + initialLayers.add(new CakeLayer("layer2", 2000)); + + cake.setLayers(initialLayers); + assertEquals(initialLayers, cake.getLayers()); + + final CakeLayer newLayer = new CakeLayer("layer3", 3000); + cake.addLayer(newLayer); + + final Set expectedLayers = new HashSet<>(); + expectedLayers.addAll(initialLayers); + expectedLayers.addAll(initialLayers); + expectedLayers.add(newLayer); + assertEquals(expectedLayers, cake.getLayers()); + } + + @Test + public void testToString() { + final CakeTopping topping = new CakeTopping("topping", 20); + topping.setId(2345L); + + final CakeLayer layer = new CakeLayer("layer", 100); + layer.setId(3456L); + + final Cake cake = new Cake(); + cake.setId(1234L); + cake.setTopping(topping); + cake.addLayer(layer); + + final String expected = "id=1234 topping=id=2345 name=topping calories=20 " + + "layers=[id=3456 name=layer calories=100]"; + assertEquals(expected, cake.toString()); + + } + +} diff --git a/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java b/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java new file mode 100644 index 000000000..1dc9a4d01 --- /dev/null +++ b/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java @@ -0,0 +1,48 @@ +package com.iluwatar.layers; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/15/15 - 10:04 PM + * + * @author Jeroen Meulemeester + */ +public class CakeViewImplTest extends StdOutTest { + + /** + * Verify if the cake view renders the expected result + */ + @Test + public void testRender() { + + final List layers = new ArrayList<>(); + layers.add(new CakeLayerInfo("layer1", 1000)); + layers.add(new CakeLayerInfo("layer2", 2000)); + layers.add(new CakeLayerInfo("layer3", 3000)); + + final List cakes = new ArrayList<>(); + final CakeInfo cake = new CakeInfo(new CakeToppingInfo("topping", 1000), layers); + cakes.add(cake); + + final CakeBakingService bakingService = mock(CakeBakingService.class); + when(bakingService.getAllCakes()).thenReturn(cakes); + + final CakeViewImpl cakeView = new CakeViewImpl(bakingService); + + verifyZeroInteractions(getStdOutMock()); + + cakeView.render(); + verify(getStdOutMock(), times(1)).println(cake); + + } + +} diff --git a/layers/src/test/java/com/iluwatar/layers/StdOutTest.java b/layers/src/test/java/com/iluwatar/layers/StdOutTest.java new file mode 100644 index 000000000..fe72bbb8a --- /dev/null +++ b/layers/src/test/java/com/iluwatar/layers/StdOutTest.java @@ -0,0 +1,54 @@ +package com.iluwatar.layers; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since the actions of the views don't have + * any influence on any other accessible objects, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} From 2c82bd945096184309750ab212603fe16d20dad4 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 19 Dec 2015 13:17:28 +0100 Subject: [PATCH 035/112] Added tests for lazy-loading pattern --- .../lazy/loading/AbstractHolderTest.java | 41 +++++++++++++++ .../lazy/loading/HolderNaiveTest.java | 26 ++++++++++ .../lazy/loading/HolderThreadSafeTest.java | 51 ++++++------------- .../lazy/loading/Java8HolderTest.java | 40 +++++++++++++++ 4 files changed, 123 insertions(+), 35 deletions(-) create mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java create mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java create mode 100644 lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java new file mode 100644 index 000000000..99523cd0a --- /dev/null +++ b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java @@ -0,0 +1,41 @@ +package com.iluwatar.lazy.loading; + +import org.junit.Test; + +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertSame; +import static junit.framework.TestCase.assertNull; + +/** + * Date: 12/19/15 - 11:58 AM + * + * @author Jeroen Meulemeester + */ +public abstract class AbstractHolderTest { + + /** + * Get the internal state of the holder value + * + * @return The internal value + */ + abstract Heavy getInternalHeavyValue() throws Exception; + + /** + * Request a lazy loaded {@link Heavy} object from the holder. + * + * @return The lazy loaded {@link Heavy} object + */ + abstract Heavy getHeavy() throws Exception; + + /** + * This test shows that the heavy field is not instantiated until the method getHeavy is called + */ + @Test(timeout = 3000) + public void testGetHeavy() throws Exception { + assertNull(getInternalHeavyValue()); + assertNotNull(getHeavy()); + assertNotNull(getInternalHeavyValue()); + assertSame(getHeavy(), getInternalHeavyValue()); + } + +} diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java new file mode 100644 index 000000000..2c539e8ca --- /dev/null +++ b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java @@ -0,0 +1,26 @@ +package com.iluwatar.lazy.loading; + +import java.lang.reflect.Field; + +/** + * Date: 12/19/15 - 12:05 PM + * + * @author Jeroen Meulemeester + */ +public class HolderNaiveTest extends AbstractHolderTest { + + private final HolderNaive holder = new HolderNaive(); + + @Override + Heavy getInternalHeavyValue() throws Exception { + final Field holderField = HolderNaive.class.getDeclaredField("heavy"); + holderField.setAccessible(true); + return (Heavy) holderField.get(this.holder); + } + + @Override + Heavy getHeavy() { + return holder.getHeavy(); + } + +} \ No newline at end of file diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java index d827f186b..f6aed73b7 100644 --- a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java +++ b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java @@ -1,45 +1,26 @@ package com.iluwatar.lazy.loading; -import org.junit.Test; - import java.lang.reflect.Field; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - /** - * Using reflection this test shows that the heavy field is not instantiated until the method - * getHeavy is called + * Date: 12/19/15 - 12:19 PM * - * Created by jones on 11/10/2015. + * @author Jeroen Meulemeester */ -public class HolderThreadSafeTest { +public class HolderThreadSafeTest extends AbstractHolderTest { - @Test - public void test() throws IllegalAccessException { - HolderThreadSafe hts = new HolderThreadSafe(); + private final HolderThreadSafe holder = new HolderThreadSafe(); - { - // first call is null - Field[] ff = HolderThreadSafe.class.getDeclaredFields(); - for (Field f : ff) { - f.setAccessible(true); - } - - assertNull(ff[0].get(hts)); - } - - // now it is lazily loaded - hts.getHeavy(); - - { - // now it is not null - call via reflection so that the test is the same before and after - Field[] ff = HolderThreadSafe.class.getDeclaredFields(); - for (Field f : ff) { - f.setAccessible(true); - } - - assertNotNull(ff[0].get(hts)); - } + @Override + Heavy getInternalHeavyValue() throws Exception { + final Field holderField = HolderThreadSafe.class.getDeclaredField("heavy"); + holderField.setAccessible(true); + return (Heavy) holderField.get(this.holder); } -} + + @Override + Heavy getHeavy() throws Exception { + return this.holder.getHeavy(); + } + +} \ No newline at end of file diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java new file mode 100644 index 000000000..aed9a054e --- /dev/null +++ b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java @@ -0,0 +1,40 @@ +package com.iluwatar.lazy.loading; + +import java.lang.reflect.Field; +import java.util.function.Supplier; + +/** + * Date: 12/19/15 - 12:27 PM + * + * @author Jeroen Meulemeester + */ +public class Java8HolderTest extends AbstractHolderTest { + + private final Java8Holder holder = new Java8Holder(); + + + @Override + Heavy getInternalHeavyValue() throws Exception { + final Field holderField = Java8Holder.class.getDeclaredField("heavy"); + holderField.setAccessible(true); + + final Supplier supplier = (Supplier) holderField.get(this.holder); + final Class supplierClass = supplier.getClass(); + + // This is a little fishy, but I don't know another way to test this: + // The lazy holder is at first a lambda, but gets replaced with a new supplier after loading ... + if (supplierClass.isLocalClass()) { + final Field instanceField = supplierClass.getDeclaredField("heavyInstance"); + instanceField.setAccessible(true); + return (Heavy) instanceField.get(supplier); + } else { + return null; + } + } + + @Override + Heavy getHeavy() throws Exception { + return holder.getHeavy(); + } + +} \ No newline at end of file From 719f80a0d66e3e5977b21bb7f057037fe7323041 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 20 Dec 2015 00:00:07 +0100 Subject: [PATCH 036/112] Added tests for mediator pattern --- mediator/pom.xml | 5 + .../com/iluwatar/mediator/PartyImplTest.java | 41 ++++++ .../iluwatar/mediator/PartyMemberTest.java | 128 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java create mode 100644 mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java diff --git a/mediator/pom.xml b/mediator/pom.xml index 0e9bff5d1..58fb73628 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java new file mode 100644 index 000000000..992662fb2 --- /dev/null +++ b/mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java @@ -0,0 +1,41 @@ +package com.iluwatar.mediator; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/19/15 - 10:00 PM + * + * @author Jeroen Meulemeester + */ +public class PartyImplTest { + + /** + * Verify if a member is notified when it's joining a party. Generate an action and see if the + * other member gets it. Also check members don't get their own actions. + */ + @Test + public void testPartyAction() { + final PartyMember partyMember1 = mock(PartyMember.class); + final PartyMember partyMember2 = mock(PartyMember.class); + + final PartyImpl party = new PartyImpl(); + party.addMember(partyMember1); + party.addMember(partyMember2); + + verify(partyMember1).joinedParty(party); + verify(partyMember2).joinedParty(party); + + party.act(partyMember1, Action.GOLD); + verifyZeroInteractions(partyMember1); + verify(partyMember2).partyAction(Action.GOLD); + + verifyNoMoreInteractions(partyMember1, partyMember2); + + } + +} diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java new file mode 100644 index 000000000..31b7222e9 --- /dev/null +++ b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java @@ -0,0 +1,128 @@ +package com.iluwatar.mediator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.function.Supplier; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/19/15 - 10:13 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class PartyMemberTest { + + @Parameterized.Parameters + public static Collection[]> data() { + return Arrays.asList( + new Supplier[]{Hobbit::new}, + new Supplier[]{Hunter::new}, + new Supplier[]{Rogue::new}, + new Supplier[]{Wizard::new} + ); + } + + /** + * The mocked standard out {@link PrintStream}, required since some actions on a {@link + * PartyMember} have any influence on any other accessible objects, except for writing to std-out + * using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * The factory, used to create a new instance of the tested party member + */ + private final Supplier memberSupplier; + + /** + * Create a new test instance, using the given {@link PartyMember} factory + * + * @param memberSupplier The party member factory + */ + public PartyMemberTest(final Supplier memberSupplier) { + this.memberSupplier = memberSupplier; + } + + /** + * Verify if a party action triggers the correct output to the std-Out + */ + @Test + public void testPartyAction() { + final PartyMember member = this.memberSupplier.get(); + + for (final Action action : Action.values()) { + member.partyAction(action); + verify(this.stdOutMock).println(member.toString() + " " + action.getDescription()); + } + + verifyNoMoreInteractions(this.stdOutMock); + } + + /** + * Verify if a member action triggers the expected interactions with the party class + */ + @Test + public void testAct() { + final PartyMember member = this.memberSupplier.get(); + + member.act(Action.GOLD); + verifyZeroInteractions(this.stdOutMock); + + final Party party = mock(Party.class); + member.joinedParty(party); + verify(this.stdOutMock).println(member.toString() + " joins the party"); + + for (final Action action : Action.values()) { + member.act(action); + verify(this.stdOutMock).println(member.toString() + " " + action.toString()); + verify(party).act(member, action); + } + + verifyNoMoreInteractions(party, this.stdOutMock); + } + + /** + * Verify if {@link PartyMember#toString()} generate the expected output + */ + @Test + public void testToString() throws Exception { + final PartyMember member = this.memberSupplier.get(); + final Class memberClass = member.getClass(); + assertEquals(memberClass.getSimpleName(), member.toString()); + } + +} From a57a71b09c63ba9a24c89b00ae7192176914ac3d Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 20 Dec 2015 10:39:02 +0100 Subject: [PATCH 037/112] Added tests for memento pattern --- .../java/com/iluwatar/memento/StarTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 memento/src/test/java/com/iluwatar/memento/StarTest.java diff --git a/memento/src/test/java/com/iluwatar/memento/StarTest.java b/memento/src/test/java/com/iluwatar/memento/StarTest.java new file mode 100644 index 000000000..b5c7d9be0 --- /dev/null +++ b/memento/src/test/java/com/iluwatar/memento/StarTest.java @@ -0,0 +1,75 @@ +package com.iluwatar.memento; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/20/15 - 10:08 AM + * + * @author Jeroen Meulemeester + */ +public class StarTest { + + /** + * Verify the stages of a dying sun, without going back in time + */ + @Test + public void testTimePasses() { + final Star star = new Star(StarType.SUN, 1, 2); + assertEquals("sun age: 1 years mass: 2 tons", star.toString()); + + star.timePasses(); + assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); + + star.timePasses(); + assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); + + star.timePasses(); + assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); + + star.timePasses(); + assertEquals("dead star age: 16 years mass: 8192 tons", star.toString()); + + star.timePasses(); + assertEquals("dead star age: 64 years mass: 0 tons", star.toString()); + + star.timePasses(); + assertEquals("dead star age: 256 years mass: 0 tons", star.toString()); + } + + /** + * Verify some stage of a dying sun, but go back in time to test the memento + */ + @Test + public void testSetMemento() { + final Star star = new Star(StarType.SUN, 1, 2); + final StarMemento firstMemento = star.getMemento(); + assertEquals("sun age: 1 years mass: 2 tons", star.toString()); + + star.timePasses(); + final StarMemento secondMemento = star.getMemento(); + assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); + + star.timePasses(); + final StarMemento thirdMemento = star.getMemento(); + assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); + + star.timePasses(); + assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); + + star.setMemento(thirdMemento); + assertEquals("white dwarf age: 4 years mass: 128 tons", star.toString()); + + star.timePasses(); + assertEquals("supernova age: 8 years mass: 1024 tons", star.toString()); + + star.setMemento(secondMemento); + assertEquals("red giant age: 2 years mass: 16 tons", star.toString()); + + star.setMemento(firstMemento); + assertEquals("sun age: 1 years mass: 2 tons", star.toString()); + + } + +} From 69c93746692a1bc3a1d0ec060f9b8ee650878cee Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 20 Dec 2015 14:31:36 +0100 Subject: [PATCH 038/112] Added tests for model-view-controller pattern --- model-view-controller/pom.xml | 5 + .../view/controller/GiantControllerTest.java | 100 ++++++++++++++++++ .../model/view/controller/GiantModelTest.java | 56 ++++++++++ .../model/view/controller/GiantViewTest.java | 64 +++++++++++ 4 files changed, 225 insertions(+) create mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java create mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java create mode 100644 model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 8e5d3d9e2..a892f836e 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java new file mode 100644 index 000000000..0090f2d1d --- /dev/null +++ b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java @@ -0,0 +1,100 @@ +package com.iluwatar.model.view.controller; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/20/15 - 2:19 PM + * + * @author Jeroen Meulemeester + */ +public class GiantControllerTest { + + /** + * Verify if the controller passes the health level through to the model and vice versa + */ + @Test + public void testSetHealth() { + final GiantModel model = mock(GiantModel.class); + final GiantView view = mock(GiantView.class); + final GiantController controller = new GiantController(model, view); + + verifyZeroInteractions(model, view); + + for (final Health health : Health.values()) { + controller.setHealth(health); + verify(model).setHealth(health); + verifyZeroInteractions(view); + } + + controller.getHealth(); + verify(model).getHealth(); + + verifyNoMoreInteractions(model, view); + } + + /** + * Verify if the controller passes the fatigue level through to the model and vice versa + */ + @Test + public void testSetFatigue() { + final GiantModel model = mock(GiantModel.class); + final GiantView view = mock(GiantView.class); + final GiantController controller = new GiantController(model, view); + + verifyZeroInteractions(model, view); + + for (final Fatigue fatigue : Fatigue.values()) { + controller.setFatigue(fatigue); + verify(model).setFatigue(fatigue); + verifyZeroInteractions(view); + } + + controller.getFatigue(); + verify(model).getFatigue(); + + verifyNoMoreInteractions(model, view); + } + + /** + * Verify if the controller passes the nourishment level through to the model and vice versa + */ + @Test + public void testSetNourishment() { + final GiantModel model = mock(GiantModel.class); + final GiantView view = mock(GiantView.class); + final GiantController controller = new GiantController(model, view); + + verifyZeroInteractions(model, view); + + for (final Nourishment nourishment : Nourishment.values()) { + controller.setNourishment(nourishment); + verify(model).setNourishment(nourishment); + verifyZeroInteractions(view); + } + + controller.getNourishment(); + verify(model).getNourishment(); + + verifyNoMoreInteractions(model, view); + } + + @Test + public void testUpdateView() { + final GiantModel model = mock(GiantModel.class); + final GiantView view = mock(GiantView.class); + final GiantController controller = new GiantController(model, view); + + verifyZeroInteractions(model, view); + + controller.updateView(); + verify(view).displayGiant(model); + + verifyNoMoreInteractions(model, view); + } + +} \ No newline at end of file diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java new file mode 100644 index 000000000..9513a62ec --- /dev/null +++ b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java @@ -0,0 +1,56 @@ +package com.iluwatar.model.view.controller; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/20/15 - 2:10 PM + * + * @author Jeroen Meulemeester + */ +public class GiantModelTest { + + /** + * Verify if the health value is set properly though the constructor and setter + */ + @Test + public void testSetHealth() { + final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); + assertEquals(Health.HEALTHY, model.getHealth()); + for (final Health health : Health.values()) { + model.setHealth(health); + assertEquals(health, model.getHealth()); + assertEquals("The giant looks " + health.toString() + ", alert and saturated.", model.toString()); + } + } + + /** + * Verify if the fatigue level is set properly though the constructor and setter + */ + @Test + public void testSetFatigue() { + final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); + assertEquals(Fatigue.ALERT, model.getFatigue()); + for (final Fatigue fatigue : Fatigue.values()) { + model.setFatigue(fatigue); + assertEquals(fatigue, model.getFatigue()); + assertEquals("The giant looks healthy, " + fatigue.toString() + " and saturated.", model.toString()); + } + } + + /** + * Verify if the nourishment level is set properly though the constructor and setter + */ + @Test + public void testSetNourishment() { + final GiantModel model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED); + assertEquals(Nourishment.SATURATED, model.getNourishment()); + for (final Nourishment nourishment : Nourishment.values()) { + model.setNourishment(nourishment); + assertEquals(nourishment, model.getNourishment()); + assertEquals("The giant looks healthy, alert and " + nourishment.toString() + ".", model.toString()); + } + } + +} diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java new file mode 100644 index 000000000..8d7a7dfbf --- /dev/null +++ b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java @@ -0,0 +1,64 @@ +package com.iluwatar.model.view.controller; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/20/15 - 2:04 PM + * + * @author Jeroen Meulemeester + */ +public class GiantViewTest { + + /** + * The mocked standard out {@link PrintStream}, required since the actions of the views don't have + * any influence on any other accessible objects, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Verify if the {@link GiantView} does what it has to do: Print the {@link GiantModel} to the + * standard out stream, nothing more, nothing less. + */ + @Test + public void testDisplayGiant() { + final GiantView view = new GiantView(); + + final GiantModel model = mock(GiantModel.class); + view.displayGiant(model); + + verify(this.stdOutMock).println(model); + verifyNoMoreInteractions(model, this.stdOutMock); + + } + +} \ No newline at end of file From 6fe01e73b2b32c5c92a696e2e466c77a2a67eed4 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 21 Dec 2015 12:17:20 +0100 Subject: [PATCH 039/112] Add additional tests for model-view-presenter pattern --- .../model/view/presenter/AppTest.java | 18 ++++++++++++++ .../model/view/presenter/FileLoaderTest.java | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java create mode 100644 model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java new file mode 100644 index 000000000..9b4aabc4d --- /dev/null +++ b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.model.view.presenter; + +import org.junit.Test; + +/** + * + * Application test + * + */ +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } + +} diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java new file mode 100644 index 000000000..7fa4a9186 --- /dev/null +++ b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.model.view.presenter; + +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import static org.junit.Assert.*; + +/** + * Date: 12/21/15 - 12:12 PM + * + * @author Jeroen Meulemeester + */ +public class FileLoaderTest { + + @Test + public void testLoadData() throws Exception { + final FileLoader fileLoader = new FileLoader(); + fileLoader.setFileName("non-existing-file"); + assertNull(fileLoader.loadData()); + } + +} \ No newline at end of file From 531158c83610d2ffb6fb4655189212a2122a7e95 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 21 Dec 2015 13:29:25 +0100 Subject: [PATCH 040/112] Added tests for monostate pattern --- monostate/pom.xml | 5 ++ .../main/java/com/iluwatar/monostate/App.java | 4 +- .../com/iluwatar/monostate/LoadBalancer.java | 2 +- .../java/com/iluwatar/monostate/Server.java | 2 +- .../java/com/iluwatar/monostate/AppTest.java | 11 ----- .../iluwatar/monostate/LoadBalancerTest.java | 49 +++++++++++++++++++ 6 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java diff --git a/monostate/pom.xml b/monostate/pom.xml index 2f253084d..72e2231f1 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/monostate/src/main/java/com/iluwatar/monostate/App.java b/monostate/src/main/java/com/iluwatar/monostate/App.java index 0daad5b67..5c61371fa 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/App.java +++ b/monostate/src/main/java/com/iluwatar/monostate/App.java @@ -28,8 +28,8 @@ public class App { public static void main(String[] args) { LoadBalancer loadBalancer1 = new LoadBalancer(); LoadBalancer loadBalancer2 = new LoadBalancer(); - loadBalancer1.serverequest(new Request("Hello")); - loadBalancer2.serverequest(new Request("Hello World")); + loadBalancer1.serverRequest(new Request("Hello")); + loadBalancer2.serverRequest(new Request("Hello World")); } } diff --git a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java index b81e44251..5870ca0a7 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java +++ b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java @@ -39,7 +39,7 @@ public class LoadBalancer { return lastServedId; } - public void serverequest(Request request) { + public void serverRequest(Request request) { if (lastServedId >= servers.size()) { lastServedId = 0; } diff --git a/monostate/src/main/java/com/iluwatar/monostate/Server.java b/monostate/src/main/java/com/iluwatar/monostate/Server.java index f48f4ad0f..e0b3f850a 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/Server.java +++ b/monostate/src/main/java/com/iluwatar/monostate/Server.java @@ -25,7 +25,7 @@ public class Server { return port; } - public final void serve(Request request) { + public void serve(Request request) { System.out.println("Server ID " + id + " associated to host : " + getHost() + " and Port " + getPort() + " Processed request with value " + request.value); } diff --git a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java index c502dd14a..e216ae242 100644 --- a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java +++ b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java @@ -5,17 +5,6 @@ import org.junit.Test; public class AppTest { - @Test - public void testSameStateAmonstAllInstances() { - LoadBalancer balancer = new LoadBalancer(); - LoadBalancer balancer2 = new LoadBalancer(); - balancer.addServer(new Server("localhost", 8085, 6)); - // Both should have the same number of servers. - Assert.assertTrue(balancer.getNoOfServers() == balancer2.getNoOfServers()); - // Both Should have the same LastServedId - Assert.assertTrue(balancer.getLastServedId() == balancer2.getLastServedId()); - } - @Test public void testMain() { String[] args = {}; diff --git a/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java b/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java new file mode 100644 index 000000000..130adae14 --- /dev/null +++ b/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java @@ -0,0 +1,49 @@ +package com.iluwatar.monostate; + +import org.junit.Assert; +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/21/15 - 12:26 PM + * + * @author Jeroen Meulemeester + */ +public class LoadBalancerTest { + + @Test + public void testSameStateAmongstAllInstances() { + final LoadBalancer firstBalancer = new LoadBalancer(); + final LoadBalancer secondBalancer = new LoadBalancer(); + firstBalancer.addServer(new Server("localhost", 8085, 6)); + // Both should have the same number of servers. + Assert.assertTrue(firstBalancer.getNoOfServers() == secondBalancer.getNoOfServers()); + // Both Should have the same LastServedId + Assert.assertTrue(firstBalancer.getLastServedId() == secondBalancer.getLastServedId()); + } + + @Test + public void testServe() { + final Server server = mock(Server.class); + + final LoadBalancer loadBalancer = new LoadBalancer(); + loadBalancer.addServer(server); + + verifyZeroInteractions(server); + + final Request request = new Request("test"); + for (int i = 0; i < loadBalancer.getNoOfServers() * 2; i++) { + loadBalancer.serverRequest(request); + } + + verify(server, times(2)).serve(request); + verifyNoMoreInteractions(server); + + } + +} From e3e0e32e92b97590088a9f47a88b222c1b5a384e Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 21 Dec 2015 14:35:36 +0100 Subject: [PATCH 041/112] Fixed failing unit test LoadBalancer has several static fields, this could cause problems since JUnit tests are executed concurrently. --- monostate/src/test/java/com/iluwatar/monostate/AppTest.java | 1 - .../test/java/com/iluwatar/monostate/LoadBalancerTest.java | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java index e216ae242..72341e3ff 100644 --- a/monostate/src/test/java/com/iluwatar/monostate/AppTest.java +++ b/monostate/src/test/java/com/iluwatar/monostate/AppTest.java @@ -9,7 +9,6 @@ public class AppTest { public void testMain() { String[] args = {}; App.main(args); - Assert.assertTrue(LoadBalancer.getLastServedId() == 2); } } diff --git a/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java b/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java index 130adae14..816443fbc 100644 --- a/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java +++ b/monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java @@ -3,11 +3,14 @@ package com.iluwatar.monostate; import org.junit.Assert; import org.junit.Test; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; /** * Date: 12/21/15 - 12:26 PM @@ -30,6 +33,9 @@ public class LoadBalancerTest { @Test public void testServe() { final Server server = mock(Server.class); + when(server.getHost()).thenReturn("testhost"); + when(server.getPort()).thenReturn(1234); + doNothing().when(server).serve(any(Request.class)); final LoadBalancer loadBalancer = new LoadBalancer(); loadBalancer.addServer(server); From 6e496e7c8682f15b0181c95d84b7054952ac4b2c Mon Sep 17 00:00:00 2001 From: Kirill Vlasov Date: Tue, 22 Dec 2015 14:48:24 +0500 Subject: [PATCH 042/112] Fixing squid:S1854 - Dead stores should be removed --- .../src/main/java/com/iluwatar/caching/App.java | 14 +++++++------- .../tolerantreader/RainbowFishSerializer.java | 3 +-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index c7f55db70..0d674f1ca 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -65,8 +65,8 @@ public class App { AppManager.save(userAccount1); System.out.println(AppManager.printCacheContent()); - userAccount1 = AppManager.find("001"); - userAccount1 = AppManager.find("001"); + AppManager.find("001"); + AppManager.find("001"); } /** @@ -80,15 +80,15 @@ public class App { AppManager.save(userAccount2); System.out.println(AppManager.printCacheContent()); - userAccount2 = AppManager.find("002"); + AppManager.find("002"); System.out.println(AppManager.printCacheContent()); userAccount2 = AppManager.find("002"); userAccount2.setUserName("Jane G."); AppManager.save(userAccount2); System.out.println(AppManager.printCacheContent()); - userAccount2 = AppManager.find("002"); + AppManager.find("002"); System.out.println(AppManager.printCacheContent()); - userAccount2 = AppManager.find("002"); + AppManager.find("002"); } /** @@ -106,12 +106,12 @@ public class App { AppManager.save(userAccount4); AppManager.save(userAccount5); System.out.println(AppManager.printCacheContent()); - userAccount3 = AppManager.find("003"); + AppManager.find("003"); System.out.println(AppManager.printCacheContent()); UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child."); AppManager.save(userAccount6); System.out.println(AppManager.printCacheContent()); - userAccount4 = AppManager.find("004"); + AppManager.find("004"); System.out.println(AppManager.printCacheContent()); } } diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java index 3929e06e7..8c4aa9e8f 100644 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java +++ b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java @@ -70,10 +70,9 @@ public class RainbowFishSerializer { * @throws ClassNotFoundException */ public static RainbowFish readV1(String filename) throws IOException, ClassNotFoundException { - Map map = null; FileInputStream fileIn = new FileInputStream(filename); ObjectInputStream objIn = new ObjectInputStream(fileIn); - map = (Map) objIn.readObject(); + Map map = (Map) objIn.readObject(); objIn.close(); fileIn.close(); return new RainbowFish(map.get("name"), Integer.parseInt(map.get("age")), Integer.parseInt(map From 9fbb085985e092fc5d7f631e154b66d2ade7a15b Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Wed, 23 Dec 2015 13:20:39 +0200 Subject: [PATCH 043/112] Checkstyle fails the build when violations are detected --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9fa150dd4..724b058f1 100644 --- a/pom.xml +++ b/pom.xml @@ -255,8 +255,8 @@ checkstyle.xml UTF-8 - false - false + true + true From cec9a99410a0544ff0f1a5853443ef9dcff0a9e7 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Fri, 25 Dec 2015 23:49:28 +0200 Subject: [PATCH 044/112] Adjust checkstyle rules. Make checkstyle fail the build when violations are found. Correct all current checkstyle violations. --- .../com/iluwatar/abstractfactory/App.java | 85 +++++---- .../iluwatar/async/method/invocation/App.java | 47 ++--- .../async/method/invocation/AsyncResult.java | 2 - .../invocation/ThreadAsyncExecutor.java | 24 +-- .../invocation/ThreadAsyncExecutorTest.java | 76 ++++---- .../main/java/com/iluwatar/builder/Hero.java | 3 + .../business/delegate/BusinessDelegate.java | 26 +-- .../main/java/com/iluwatar/caching/App.java | 4 +- .../java/com/iluwatar/caching/AppManager.java | 23 ++- .../java/com/iluwatar/caching/CacheStore.java | 89 +++++---- .../{DBManager.java => DbManager.java} | 53 ++++-- .../caching/{LRUCache.java => LruCache.java} | 65 ++++--- .../com/iluwatar/caching/UserAccount.java | 19 +- .../java/com/iluwatar/caching/AppTest.java | 2 +- .../main/java/com/iluwatar/callback/App.java | 3 + .../main/java/com/iluwatar/callback/Task.java | 3 + .../com/iluwatar/chain/RequestHandler.java | 3 + checkstyle.xml | 75 ++------ .../java/com/iluwatar/command/Target.java | 3 + .../java/com/iluwatar/command/Wizard.java | 9 + .../iluwatar/composite/LetterComposite.java | 3 + .../java/com/iluwatar/composite/Sentence.java | 3 + .../java/com/iluwatar/composite/Word.java | 3 + dao/src/main/java/com/iluwatar/dao/App.java | 12 +- .../main/java/com/iluwatar/dao/Customer.java | 6 +- dao/src/main/resources/log4j.xml | 20 +-- .../iluwatar/doublechecked/locking/App.java | 2 +- .../doublechecked/locking/Inventory.java | 6 + .../doublechecked/locking/InventoryTest.java | 4 +- .../java/com/iluwatar/doubledispatch/App.java | 30 ++-- .../iluwatar/doubledispatch/Rectangle.java | 3 + .../doubledispatch/CollisionTest.java | 12 +- .../event/aggregator/EventEmitterTest.java | 62 +++---- .../event/aggregator/KingsHandTest.java | 2 +- .../java/com/iluwatar/execute/around/App.java | 3 - .../execute/around/SimpleFileWriter.java | 3 + .../execute/around/SimpleFileWriterTest.java | 6 +- .../facade/DwarvenGoldmineFacade.java | 3 + .../iluwatar/facade/DwarvenMineWorker.java | 3 + .../com/iluwatar/fluentinterface/app/App.java | 19 +- .../lazy/DecoratingIterator.java | 4 - .../simple/SimpleFluentIterable.java | 10 +- .../fluentiterable/FluentIterableTest.java | 2 +- .../iluwatar/flux/dispatcher/Dispatcher.java | 3 + .../com/iluwatar/flyweight/AlchemistShop.java | 6 + .../com/iluwatar/front/controller/App.java | 40 +++-- .../controller/ApplicationException.java | 8 +- .../front/controller/ArcherCommand.java | 8 +- .../iluwatar/front/controller/ArcherView.java | 8 +- .../front/controller/CatapultCommand.java | 8 +- .../front/controller/CatapultView.java | 8 +- .../iluwatar/front/controller/Command.java | 4 +- .../iluwatar/front/controller/ErrorView.java | 8 +- .../front/controller/FrontController.java | 52 +++--- .../front/controller/UnknownCommand.java | 8 +- .../com/iluwatar/front/controller/View.java | 2 +- .../iluwatar/front/controller/AppTest.java | 12 +- .../controller/ApplicationExceptionTest.java | 4 +- .../com/iluwatar/halfsynchalfasync/App.java | 15 +- .../intercepting/filter/AddressFilter.java | 3 +- .../iluwatar/intercepting/filter/Client.java | 6 +- .../iluwatar/intercepting/filter/Filter.java | 9 - .../intercepting/filter/FilterChain.java | 9 + .../iluwatar/intercepting/filter/Order.java | 3 + .../iluwatar/intercepting/filter/Target.java | 6 +- .../intercepting/filter/FilterTest.java | 3 + .../java/com/iluwatar/interpreter/App.java | 6 +- .../iluwatar/interpreter/ExpressionTest.java | 6 +- .../main/java/com/iluwatar/iterator/App.java | 8 +- .../com/iluwatar/iterator/TreasureChest.java | 10 +- .../iterator/TreasureChestItemIterator.java | 3 + .../iluwatar/iterator/TreasureChestTest.java | 2 +- .../main/java/com/iluwatar/layers/App.java | 42 +++-- .../iluwatar/layers/CakeBakingService.java | 13 -- .../java/com/iluwatar/layers/CakeInfo.java | 9 + .../com/iluwatar/layers/CakeLayerInfo.java | 6 + .../com/iluwatar/layers/CakeToppingInfo.java | 6 + .../main/resources/META-INF/persistence.xml | 6 +- .../src/main/resources/applicationContext.xml | 67 ++++--- .../java/com/iluwatar/lazy/loading/Heavy.java | 3 + .../iluwatar/lazy/loading/HolderNaive.java | 6 + .../lazy/loading/HolderThreadSafe.java | 6 + .../iluwatar/lazy/loading/Java8Holder.java | 2 +- .../main/java/com/iluwatar/memento/App.java | 3 + .../main/java/com/iluwatar/memento/Star.java | 6 + .../com/iluwatar/message/channel/App.java | 3 - .../model/view/presenter/FileLoader.java | 4 +- .../view/presenter/FileSelectorJFrame.java | 16 +- .../view/presenter/FileSelectorPresenter.java | 7 +- .../presenter/FileSelectorPresenterTest.java | 15 +- .../com/iluwatar/monostate/LoadBalancer.java | 6 + .../java/com/iluwatar/monostate/Server.java | 3 + .../dom/app/homepage/HomePageService.java | 4 +- .../dom/modules/simple/SimpleObjects.java | 5 +- .../modules/simple/SimpleObjectCreate.java | 2 - .../scenarios/RecreateSimpleObjects.java | 8 +- .../bootstrap/SimpleAppSystemInitializer.java | 3 + .../modules/simple/SimpleObjectGlue.java | 4 +- .../integtests/tests/SimpleAppIntegTest.java | 14 +- .../modules/simple/SimpleObjectIntegTest.java | 153 ++++++++-------- .../simple/SimpleObjectsIntegTest.java | 170 +++++++++--------- .../domainapp/webapp/SimpleApplication.java | 3 +- .../com/iluwatar/nullobject/NodeImpl.java | 3 + .../com/iluwatar/object/pool/ObjectPool.java | 5 +- .../com/iluwatar/object/pool/Oliphaunt.java | 3 + .../java/com/iluwatar/observer/Weather.java | 3 + .../iluwatar/observer/generic/GWeather.java | 3 + .../iluwatar/observer/generic/Observable.java | 3 + .../iluwatar/observer/generic/Observer.java | 4 - .../com/iluwatar/poison/pill/Consumer.java | 7 +- .../iluwatar/poison/pill/MessageQueue.java | 2 +- ...QPublishPoint.java => MqPublishPoint.java} | 2 +- ...scribePoint.java => MqSubscribePoint.java} | 2 +- .../com/iluwatar/poison/pill/Producer.java | 13 +- pom.xml | 2 +- .../privateclassdata/ImmutableStew.java | 3 + .../com/iluwatar/privateclassdata/Stew.java | 9 + .../iluwatar/privateclassdata/StewData.java | 3 + .../com/iluwatar/producer/consumer/App.java | 17 +- .../iluwatar/producer/consumer/Consumer.java | 3 + .../iluwatar/producer/consumer/Producer.java | 3 + .../java/com/iluwatar/property/Character.java | 6 + .../iluwatar/prototype/HeroFactoryImpl.java | 12 ++ .../src/main/java/com/iluwatar/proxy/App.java | 3 + .../com/iluwatar/publish/subscribe/App.java | 4 - .../java/com/iluwatar/reactor/app/App.java | 2 - .../com/iluwatar/reactor/app/AppClient.java | 16 +- .../reactor/framework/AbstractNioChannel.java | 1 + .../reactor/framework/NioReactor.java | 81 +++++---- .../com/iluwatar/repository/AppConfig.java | 7 +- .../java/com/iluwatar/repository/Person.java | 33 ++-- .../repository/PersonSpecifications.java | 7 + .../main/resources/META-INF/persistence.xml | 6 +- .../src/main/resources/applicationContext.xml | 66 ++++--- .../AnnotationBasedRepositoryTest.java | 4 +- .../iluwatar/repository/AppConfigTest.java | 5 +- .../iluwatar/repository/RepositoryTest.java | 4 +- .../acquisition/is/initialization/App.java | 3 - .../main/java/com/iluwatar/servant/App.java | 14 +- .../main/java/com/iluwatar/servant/King.java | 6 +- .../main/java/com/iluwatar/servant/Queen.java | 3 +- .../java/com/iluwatar/servant/Servant.java | 14 +- .../com/iluwatar/servicelayer/app/App.java | 6 + .../servicelayer/common/DaoBaseImpl.java | 15 +- .../servicelayer/hibernate/HibernateUtil.java | 6 +- .../servicelayer/magic/MagicServiceImpl.java | 3 + .../servicelayer/spell/SpellDaoImpl.java | 3 +- .../spellbook/SpellbookDaoImpl.java | 3 +- .../servicelayer/wizard/WizardDaoImpl.java | 3 +- .../iluwatar/servicelocator/ServiceImpl.java | 3 + .../com/iluwatar/singleton/IvoryTower.java | 4 +- .../ThreadSafeDoubleCheckLocking.java | 10 +- .../ThreadSafeLazyLoadedIvoryTower.java | 2 +- .../LazyLoadedSingletonThreadSafetyTest.java | 20 ++- .../com/iluwatar/specification/app/App.java | 3 + .../creature/AbstractCreature.java | 3 + .../src/main/java/com/iluwatar/state/App.java | 3 + .../main/java/com/iluwatar/state/Mammoth.java | 3 + .../java/com/iluwatar/stepbuilder/App.java | 2 +- .../templatemethod/StealingMethod.java | 3 + .../java/com/iluwatar/tolerantreader/App.java | 3 + .../iluwatar/tolerantreader/RainbowFish.java | 3 + .../tolerantreader/RainbowFishSerializer.java | 13 -- .../tolerantreader/RainbowFishV2.java | 3 + .../java/com/iluwatar/twin/BallThread.java | 3 + .../main/java/com/iluwatar/twin/GameItem.java | 3 - .../main/java/com/iluwatar/visitor/Unit.java | 3 + 167 files changed, 1242 insertions(+), 969 deletions(-) rename caching/src/main/java/com/iluwatar/caching/{DBManager.java => DbManager.java} (73%) rename caching/src/main/java/com/iluwatar/caching/{LRUCache.java => LruCache.java} (70%) rename poison-pill/src/main/java/com/iluwatar/poison/pill/{MQPublishPoint.java => MqPublishPoint.java} (81%) rename poison-pill/src/main/java/com/iluwatar/poison/pill/{MQSubscribePoint.java => MqSubscribePoint.java} (80%) diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java index 9a32a091a..cdde3bd8f 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java @@ -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. *

- * The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and - * its implementations ({@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both - * concrete implementations to create a king, a castle and an army. + * The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and its implementations ( + * {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both concrete implementations to create a + * king, a castle and an army. * */ public class App { @@ -23,11 +21,8 @@ public class App { private Castle castle; private Army army; - /** * Creates kingdom - * - * @param factory */ public void createKingdom(final KingdomFactory factory) { setKing(factory.createKing()); @@ -47,14 +42,6 @@ public class App { return factory.createKing(); } - Castle getCastle(final KingdomFactory factory) { - return factory.createCastle(); - } - - Army getArmy(final KingdomFactory factory) { - return factory.createArmy(); - } - public King getKing() { return king; } @@ -62,6 +49,10 @@ public class App { private void setKing(final King king) { this.king = king; } + + Castle getCastle(final KingdomFactory factory) { + return factory.createCastle(); + } public Castle getCastle() { return castle; @@ -70,6 +61,10 @@ public class App { private void setCastle(final Castle castle) { this.castle = castle; } + + Army getArmy(final KingdomFactory factory) { + return factory.createArmy(); + } public Army getArmy() { return army; @@ -79,32 +74,32 @@ public class App { this.army = army; } - /** * Program entry point * - * @param args command line args + * @param args + * command line args */ public static void main(String[] args) { - - App app = new App(); - - System.out.println("Elf Kingdom"); - KingdomFactory elfKingdomFactory; - elfKingdomFactory = app.getElfKingdomFactory(); - app.createKingdom(elfKingdomFactory); - System.out.println(app.getArmy().getDescription()); - System.out.println(app.getCastle().getDescription()); - System.out.println(app.getKing().getDescription()); - - System.out.println("\nOrc Kingdom"); - KingdomFactory orcKingdomFactory; - orcKingdomFactory = app.getOrcKingdomFactory(); - app.createKingdom(orcKingdomFactory); - System.out.println(app.getArmy().getDescription()); - System.out.println(app.getCastle().getDescription()); - System.out.println(app.getKing().getDescription()); - + + App app = new App(); + + System.out.println("Elf Kingdom"); + KingdomFactory elfKingdomFactory; + elfKingdomFactory = app.getElfKingdomFactory(); + app.createKingdom(elfKingdomFactory); + System.out.println(app.getArmy().getDescription()); + System.out.println(app.getCastle().getDescription()); + System.out.println(app.getKing().getDescription()); + + System.out.println("\nOrc Kingdom"); + KingdomFactory orcKingdomFactory; + orcKingdomFactory = app.getOrcKingdomFactory(); + app.createKingdom(orcKingdomFactory); + System.out.println(app.getArmy().getDescription()); + System.out.println(app.getCastle().getDescription()); + System.out.println(app.getKing().getDescription()); + } - + } diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java index 0b8ee3649..6f2d4a8fc 100644 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java +++ b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java @@ -4,24 +4,23 @@ import java.util.concurrent.Callable; /** * This application demonstrates the async method invocation pattern. Key parts of the pattern are - * AsyncResult which is an intermediate container for an asynchronously evaluated - * value, AsyncCallback which can be provided to be executed on task completion and - * AsyncExecutor that manages the execution of the async tasks. + * AsyncResult which is an intermediate container for an asynchronously evaluated value, + * AsyncCallback which can be provided to be executed on task completion and AsyncExecutor + * that manages the execution of the async tasks. *

- * 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. *

- * 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. *

- * 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 asyncResult1 = executor.startProcess(lazyval(10, 500)); AsyncResult asyncResult2 = executor.startProcess(lazyval("test", 300)); AsyncResult asyncResult3 = executor.startProcess(lazyval(50L, 700)); - AsyncResult asyncResult4 = - executor.startProcess(lazyval(20, 400), callback("Callback result 4")); - AsyncResult asyncResult5 = - executor.startProcess(lazyval("callback", 600), callback("Callback result 5")); + AsyncResult asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4")); + AsyncResult 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 Callable 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 AsyncCallback callback(String name) { diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java index 6d77df8ec..d64180dad 100644 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java +++ b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java @@ -5,8 +5,6 @@ import java.util.concurrent.ExecutionException; /** * * AsyncResult interface - * - * @param */ public interface AsyncResult { diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java index 300934562..e935f9626 100644 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java +++ b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java @@ -29,13 +29,12 @@ public class ThreadAsyncExecutor implements AsyncExecutor { } catch (Exception ex) { result.setException(ex); } - }, "executor-" + idx.incrementAndGet()).start(); + } , "executor-" + idx.incrementAndGet()).start(); return result; } @Override - public T endProcess(AsyncResult asyncResult) throws ExecutionException, - InterruptedException { + public T endProcess(AsyncResult 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; diff --git a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java index 440e47552..f5727b1e8 100644 --- a/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java +++ b/async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java @@ -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> optionalCaptor = ArgumentCaptor - .forClass((Class) Optional.class); + final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); final Optional optionalException = optionalCaptor.getValue(); @@ -90,8 +88,8 @@ public class ThreadAsyncExecutorTest { } /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a - * task takes a while to execute + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while + * to execute */ @Test(timeout = 5000) public void testLongRunningTaskWithoutCallback() throws Exception { @@ -101,9 +99,9 @@ public class ThreadAsyncExecutorTest { final Object result = new Object(); final Callable task = mock(Callable.class); when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + Thread.sleep(1500); + return result; + }); final AsyncResult asyncResult = executor.startProcess(task); assertNotNull(asyncResult); @@ -111,8 +109,7 @@ public class ThreadAsyncExecutorTest { try { asyncResult.getValue(); - fail( - "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); } catch (IllegalStateException e) { assertNotNull(e.getMessage()); } @@ -130,9 +127,8 @@ public class ThreadAsyncExecutorTest { } /** - * Test used to verify the happy path of - * {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task takes a while to - * execute + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task + * takes a while to execute */ @Test(timeout = 5000) public void testLongRunningTaskWithCallback() throws Exception { @@ -142,9 +138,9 @@ public class ThreadAsyncExecutorTest { final Object result = new Object(); final Callable task = mock(Callable.class); when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + Thread.sleep(1500); + return result; + }); final AsyncCallback callback = mock(AsyncCallback.class); final AsyncResult asyncResult = executor.startProcess(task, callback); @@ -155,8 +151,7 @@ public class ThreadAsyncExecutorTest { try { asyncResult.getValue(); - fail( - "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); } catch (IllegalStateException e) { assertNotNull(e.getMessage()); } @@ -164,8 +159,7 @@ public class ThreadAsyncExecutorTest { // Our task should only execute once, but it can take a while ... verify(task, timeout(3000).times(1)).call(); - final ArgumentCaptor> optionalCaptor = ArgumentCaptor - .forClass((Class) Optional.class); + final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); final Optional optionalException = optionalCaptor.getValue(); @@ -182,9 +176,8 @@ public class ThreadAsyncExecutorTest { } /** - * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a - * task takes a while to execute, while waiting on the result using - * {@link ThreadAsyncExecutor#endProcess(AsyncResult)} + * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while + * to execute, while waiting on the result using {@link ThreadAsyncExecutor#endProcess(AsyncResult)} */ @Test(timeout = 5000) public void testEndProcess() throws Exception { @@ -194,9 +187,9 @@ public class ThreadAsyncExecutorTest { final Object result = new Object(); final Callable task = mock(Callable.class); when(task.call()).thenAnswer(i -> { - Thread.sleep(1500); - return result; - }); + Thread.sleep(1500); + return result; + }); final AsyncResult asyncResult = executor.startProcess(task); assertNotNull(asyncResult); @@ -204,8 +197,7 @@ public class ThreadAsyncExecutorTest { try { asyncResult.getValue(); - fail( - "Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); + fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); } catch (IllegalStateException e) { assertNotNull(e.getMessage()); } @@ -220,8 +212,7 @@ public class ThreadAsyncExecutorTest { } /** - * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when - * the callable is 'null' + * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when the callable is 'null' */ @Test(timeout = 3000) public void testNullTask() throws Exception { @@ -229,8 +220,7 @@ public class ThreadAsyncExecutorTest { final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); final AsyncResult 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 callback = mock(AsyncCallback.class); final AsyncResult 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> optionalCaptor = ArgumentCaptor - .forClass((Class) Optional.class); + final ArgumentCaptor> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); final Optional 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 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()); diff --git a/builder/src/main/java/com/iluwatar/builder/Hero.java b/builder/src/main/java/com/iluwatar/builder/Hero.java index 54be11ea3..cf7289d51 100644 --- a/builder/src/main/java/com/iluwatar/builder/Hero.java +++ b/builder/src/main/java/com/iluwatar/builder/Hero.java @@ -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"); diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java index a3c9a00e7..7fb709bcf 100644 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java +++ b/business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java @@ -5,20 +5,20 @@ package com.iluwatar.business.delegate; */ public class BusinessDelegate { - private BusinessLookup lookupService; - private BusinessService businessService; - private ServiceType serviceType; + private BusinessLookup lookupService; + private BusinessService businessService; + private ServiceType serviceType; - public void setLookupService(BusinessLookup businessLookup) { - this.lookupService = businessLookup; - } + public void setLookupService(BusinessLookup businessLookup) { + this.lookupService = businessLookup; + } - public void setServiceType(ServiceType serviceType) { - this.serviceType = serviceType; - } + public void setServiceType(ServiceType serviceType) { + this.serviceType = serviceType; + } - public void doTask() { - businessService = lookupService.getBusinessService(serviceType); - businessService.doProcessing(); - } + public void doTask() { + businessService = lookupService.getBusinessService(serviceType); + businessService.doProcessing(); + } } diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index c7f55db70..8dcef95ce 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -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). diff --git a/caching/src/main/java/com/iluwatar/caching/AppManager.java b/caching/src/main/java/com/iluwatar/caching/AppManager.java index 08132e327..925320cd6 100644 --- a/caching/src/main/java/com/iluwatar/caching/AppManager.java +++ b/caching/src/main/java/com/iluwatar/caching/AppManager.java @@ -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); diff --git a/caching/src/main/java/com/iluwatar/caching/CacheStore.java b/caching/src/main/java/com/iluwatar/caching/CacheStore.java index 2041ac14f..95278c746 100644 --- a/caching/src/main/java/com/iluwatar/caching/CacheStore.java +++ b/caching/src/main/java/com/iluwatar/caching/CacheStore.java @@ -9,73 +9,96 @@ import java.util.ArrayList; */ public class CacheStore { - static LRUCache cache = null; + static LruCache cache = null; + /** + * Init cache capacity + */ public static void initCapacity(int capacity) { - if (null == cache) - cache = new LRUCache(capacity); - else + if (null == cache) { + cache = new LruCache(capacity); + } else { cache.setCapacity(capacity); + } } - public static UserAccount readThrough(String userID) { - if (cache.contains(userID)) { + /** + * Get user account using read-through cache + */ + public static UserAccount readThrough(String userId) { + if (cache.contains(userId)) { System.out.println("# Cache Hit!"); - return cache.get(userID); + return cache.get(userId); } System.out.println("# Cache Miss!"); - UserAccount userAccount = DBManager.readFromDB(userID); - cache.set(userID, userAccount); + UserAccount userAccount = DbManager.readFromDb(userId); + cache.set(userId, userAccount); return userAccount; } + /** + * Get user account using write-through cache + */ public static void writeThrough(UserAccount userAccount) { - if (cache.contains(userAccount.getUserID())) { - DBManager.updateDB(userAccount); + if (cache.contains(userAccount.getUserId())) { + DbManager.updateDb(userAccount); } else { - DBManager.writeToDB(userAccount); + DbManager.writeToDb(userAccount); } - cache.set(userAccount.getUserID(), userAccount); + cache.set(userAccount.getUserId(), userAccount); } + /** + * Get user account using write-around cache + */ public static void writeAround(UserAccount userAccount) { - if (cache.contains(userAccount.getUserID())) { - DBManager.updateDB(userAccount); - cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older + if (cache.contains(userAccount.getUserId())) { + DbManager.updateDb(userAccount); + cache.invalidate(userAccount.getUserId()); // Cache data has been updated -- remove older // version from cache. } else { - DBManager.writeToDB(userAccount); + DbManager.writeToDb(userAccount); } } - public static UserAccount readThroughWithWriteBackPolicy(String userID) { - if (cache.contains(userID)) { + /** + * Get user account using read-through cache with write-back policy + */ + public static UserAccount readThroughWithWriteBackPolicy(String userId) { + if (cache.contains(userId)) { System.out.println("# Cache Hit!"); - return cache.get(userID); + return cache.get(userId); } System.out.println("# Cache Miss!"); - UserAccount userAccount = DBManager.readFromDB(userID); + UserAccount userAccount = DbManager.readFromDb(userId); if (cache.isFull()) { System.out.println("# Cache is FULL! Writing LRU data to DB..."); - UserAccount toBeWrittenToDB = cache.getLRUData(); - DBManager.upsertDB(toBeWrittenToDB); + UserAccount toBeWrittenToDb = cache.getLruData(); + DbManager.upsertDb(toBeWrittenToDb); } - cache.set(userID, userAccount); + cache.set(userId, userAccount); return userAccount; } + /** + * Set user account + */ public static void writeBehind(UserAccount userAccount) { - if (cache.isFull() && !cache.contains(userAccount.getUserID())) { + if (cache.isFull() && !cache.contains(userAccount.getUserId())) { System.out.println("# Cache is FULL! Writing LRU data to DB..."); - UserAccount toBeWrittenToDB = cache.getLRUData(); - DBManager.upsertDB(toBeWrittenToDB); + UserAccount toBeWrittenToDb = cache.getLruData(); + DbManager.upsertDb(toBeWrittenToDb); } - cache.set(userAccount.getUserID(), userAccount); + cache.set(userAccount.getUserId(), userAccount); } + /** + * Clears cache + */ public static void clearCache() { - if (null != cache) + if (null != cache) { cache.clear(); + } } /** @@ -83,14 +106,18 @@ public class CacheStore { */ public static void flushCache() { System.out.println("# flushCache..."); - if (null == cache) + if (null == cache) { return; + } ArrayList listOfUserAccounts = cache.getCacheDataInListForm(); for (UserAccount userAccount : listOfUserAccounts) { - DBManager.upsertDB(userAccount); + DbManager.upsertDb(userAccount); } } + /** + * Print user accounts + */ public static String print() { ArrayList listOfUserAccounts = cache.getCacheDataInListForm(); StringBuilder sb = new StringBuilder(); diff --git a/caching/src/main/java/com/iluwatar/caching/DBManager.java b/caching/src/main/java/com/iluwatar/caching/DbManager.java similarity index 73% rename from caching/src/main/java/com/iluwatar/caching/DBManager.java rename to caching/src/main/java/com/iluwatar/caching/DbManager.java index 07a5daeac..499ad5c3c 100644 --- a/caching/src/main/java/com/iluwatar/caching/DBManager.java +++ b/caching/src/main/java/com/iluwatar/caching/DbManager.java @@ -21,7 +21,7 @@ import com.mongodb.client.model.UpdateOptions; * during runtime (createVirtualDB()).

* */ -public class DBManager { +public class DbManager { private static MongoClient mongoClient; private static MongoDatabase db; @@ -29,21 +29,31 @@ public class DBManager { private static HashMap virtualDB; - public static void createVirtualDB() { + /** + * Create DB + */ + public static void createVirtualDb() { useMongoDB = false; virtualDB = new HashMap(); } + /** + * 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 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)); } diff --git a/caching/src/main/java/com/iluwatar/caching/LRUCache.java b/caching/src/main/java/com/iluwatar/caching/LruCache.java similarity index 70% rename from caching/src/main/java/com/iluwatar/caching/LRUCache.java rename to caching/src/main/java/com/iluwatar/caching/LruCache.java index 872f97256..e20275a40 100644 --- a/caching/src/main/java/com/iluwatar/caching/LRUCache.java +++ b/caching/src/main/java/com/iluwatar/caching/LruCache.java @@ -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 diff --git a/caching/src/main/java/com/iluwatar/caching/UserAccount.java b/caching/src/main/java/com/iluwatar/caching/UserAccount.java index eff0878ad..0e281c429 100644 --- a/caching/src/main/java/com/iluwatar/caching/UserAccount.java +++ b/caching/src/main/java/com/iluwatar/caching/UserAccount.java @@ -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; } } diff --git a/caching/src/test/java/com/iluwatar/caching/AppTest.java b/caching/src/test/java/com/iluwatar/caching/AppTest.java index ce5cddf08..35917da1c 100644 --- a/caching/src/test/java/com/iluwatar/caching/AppTest.java +++ b/caching/src/test/java/com/iluwatar/caching/AppTest.java @@ -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). diff --git a/callback/src/main/java/com/iluwatar/callback/App.java b/callback/src/main/java/com/iluwatar/callback/App.java index 81cb16f73..bc8b08cf0 100644 --- a/callback/src/main/java/com/iluwatar/callback/App.java +++ b/callback/src/main/java/com/iluwatar/callback/App.java @@ -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() { diff --git a/callback/src/main/java/com/iluwatar/callback/Task.java b/callback/src/main/java/com/iluwatar/callback/Task.java index d3be6c7a0..83e2cd4df 100644 --- a/callback/src/main/java/com/iluwatar/callback/Task.java +++ b/callback/src/main/java/com/iluwatar/callback/Task.java @@ -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) { diff --git a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java b/chain/src/main/java/com/iluwatar/chain/RequestHandler.java index fd58b9ea8..12db1f51c 100644 --- a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java +++ b/chain/src/main/java/com/iluwatar/chain/RequestHandler.java @@ -13,6 +13,9 @@ public abstract class RequestHandler { this.next = next; } + /** + * Request handler + */ public void handleRequest(Request req) { if (next != null) { next.handleRequest(req); diff --git a/checkstyle.xml b/checkstyle.xml index 0ff943d95..6d969afde 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -25,8 +25,10 @@ + + - + @@ -48,7 +50,7 @@ - + @@ -61,7 +63,7 @@ - + @@ -86,9 +88,6 @@ - - - @@ -97,42 +96,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - @@ -180,11 +148,6 @@ - - - - @@ -195,7 +158,7 @@ - + diff --git a/command/src/main/java/com/iluwatar/command/Target.java b/command/src/main/java/com/iluwatar/command/Target.java index e12f758ff..731fe4d1f 100644 --- a/command/src/main/java/com/iluwatar/command/Target.java +++ b/command/src/main/java/com/iluwatar/command/Target.java @@ -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())); diff --git a/command/src/main/java/com/iluwatar/command/Wizard.java b/command/src/main/java/com/iluwatar/command/Wizard.java index edef8d3a9..fb6407c74 100644 --- a/command/src/main/java/com/iluwatar/command/Wizard.java +++ b/command/src/main/java/com/iluwatar/command/Wizard.java @@ -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(); diff --git a/composite/src/main/java/com/iluwatar/composite/LetterComposite.java b/composite/src/main/java/com/iluwatar/composite/LetterComposite.java index 1fdf4fdb6..39655fa37 100644 --- a/composite/src/main/java/com/iluwatar/composite/LetterComposite.java +++ b/composite/src/main/java/com/iluwatar/composite/LetterComposite.java @@ -24,6 +24,9 @@ public abstract class LetterComposite { protected abstract void printThisAfter(); + /** + * Print + */ public void print() { printThisBefore(); for (LetterComposite letter : children) { diff --git a/composite/src/main/java/com/iluwatar/composite/Sentence.java b/composite/src/main/java/com/iluwatar/composite/Sentence.java index e6c626ea2..03f0c6949 100644 --- a/composite/src/main/java/com/iluwatar/composite/Sentence.java +++ b/composite/src/main/java/com/iluwatar/composite/Sentence.java @@ -9,6 +9,9 @@ import java.util.List; */ public class Sentence extends LetterComposite { + /** + * Constructor + */ public Sentence(List words) { for (Word w : words) { this.add(w); diff --git a/composite/src/main/java/com/iluwatar/composite/Word.java b/composite/src/main/java/com/iluwatar/composite/Word.java index 3060b0a1b..98c5f0b0d 100644 --- a/composite/src/main/java/com/iluwatar/composite/Word.java +++ b/composite/src/main/java/com/iluwatar/composite/Word.java @@ -9,6 +9,9 @@ import java.util.List; */ public class Word extends LetterComposite { + /** + * Constructor + */ public Word(List letters) { for (Letter l : letters) { this.add(l); diff --git a/dao/src/main/java/com/iluwatar/dao/App.java b/dao/src/main/java/com/iluwatar/dao/App.java index 2e115d8ce..a9351689d 100644 --- a/dao/src/main/java/com/iluwatar/dao/App.java +++ b/dao/src/main/java/com/iluwatar/dao/App.java @@ -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()); } /** diff --git a/dao/src/main/java/com/iluwatar/dao/Customer.java b/dao/src/main/java/com/iluwatar/dao/Customer.java index e6d7f7763..3d782016b 100644 --- a/dao/src/main/java/com/iluwatar/dao/Customer.java +++ b/dao/src/main/java/com/iluwatar/dao/Customer.java @@ -11,6 +11,9 @@ public class Customer { private String firstName; private String lastName; + /** + * Constructor + */ public Customer(final int id, final String firstName, final String lastName) { this.id = id; this.firstName = firstName; @@ -54,8 +57,9 @@ public class Customer { isEqual = true; } else if (o != null && (getClass() == o.getClass())) { final Customer customer = (Customer) o; - if (getId() == customer.getId()) + if (getId() == customer.getId()) { isEqual = true; + } } return isEqual; } diff --git a/dao/src/main/resources/log4j.xml b/dao/src/main/resources/log4j.xml index 136817f50..906e37170 100644 --- a/dao/src/main/resources/log4j.xml +++ b/dao/src/main/resources/log4j.xml @@ -1,17 +1,17 @@ + xmlns:log4j='http://jakarta.apache.org/log4j/'> - - - - - + + + + + - - - - + + + + \ No newline at end of file diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java index 0cc62c995..79bf6aefd 100644 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java +++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java @@ -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())) {}; }); } diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java index 0a17ac13d..1011b78b4 100644 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java +++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java @@ -17,12 +17,18 @@ public class Inventory { private final List 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(); diff --git a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java index 1bc43263f..0b7b6dabc 100644 --- a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java +++ b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java @@ -77,8 +77,8 @@ public class InventoryTest { final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT); for (int i = 0; i < THREAD_COUNT; i++) { executorService.execute(() -> { - while (inventory.addItem(new Item())) ; - }); + while (inventory.addItem(new Item())) {}; + }); } // Wait until all threads have finished diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java index 6514feb7f..98e19b770 100644 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java +++ b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java @@ -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. *

- * 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. *

- * 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). *

- * 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(""); diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java index db26265cc..e1e3eab7b 100644 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java +++ b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java @@ -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; diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java index 5a3366e4e..6792a5d37 100644 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java @@ -107,9 +107,9 @@ public abstract class CollisionTest { 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 { 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()); } diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java index 09acf7442..bd13bd248 100644 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java @@ -63,6 +63,37 @@ public abstract class EventEmitterTest { 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 { 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); - } - } diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java index 992ee4cf5..edec65b65 100644 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java @@ -24,7 +24,7 @@ public class KingsHandTest extends EventEmitterTest { } /** - * 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. */ diff --git a/execute-around/src/main/java/com/iluwatar/execute/around/App.java b/execute-around/src/main/java/com/iluwatar/execute/around/App.java index 4a0648dbe..4695b8df5 100644 --- a/execute-around/src/main/java/com/iluwatar/execute/around/App.java +++ b/execute-around/src/main/java/com/iluwatar/execute/around/App.java @@ -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 { diff --git a/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java b/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java index be89ff9ce..e1a9073ef 100644 --- a/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java +++ b/execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java @@ -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 { diff --git a/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java b/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java index 168026b65..0c959a716 100644 --- a/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java +++ b/execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java @@ -65,11 +65,11 @@ public class SimpleFileWriterTest { * Verify if an {@link IOException} during the write ripples through */ @Test(expected = IOException.class) - public void testIOException() throws Exception { + public void testIoException() throws Exception { final File temporaryFile = this.testFolder.newFile(); new SimpleFileWriter(temporaryFile.getPath(), writer -> { - throw new IOException(""); - }); + throw new IOException(""); + }); } } diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenGoldmineFacade.java b/facade/src/main/java/com/iluwatar/facade/DwarvenGoldmineFacade.java index d6b653eaa..fd37e40c5 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenGoldmineFacade.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenGoldmineFacade.java @@ -16,6 +16,9 @@ public class DwarvenGoldmineFacade { private final List workers; + /** + * Constructor + */ public DwarvenGoldmineFacade() { workers = new ArrayList<>(); workers.add(new DwarvenGoldDigger()); diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java b/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java index d329fe84b..3190c9365 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java @@ -46,6 +46,9 @@ public abstract class DwarvenMineWorker { } } + /** + * Perform actions + */ public void action(Action... actions) { for (Action action : actions) { action(action); diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java index bdff83e17..cb5254f91 100644 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java @@ -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 integerList = new ArrayList<>(); diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java index e80356d8e..dae300c4e 100644 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java @@ -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 */ public abstract class DecoratingIterator implements Iterator { @@ -16,8 +14,6 @@ public abstract class DecoratingIterator implements Iterator { /** * Creates an iterator that decorates the given iterator. - * - * @param fromIterator */ public DecoratingIterator(Iterator fromIterator) { this.fromIterator = fromIterator; diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java index 19283152e..ef1859529 100644 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java @@ -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. diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java index 7d4cb0530..9159e90b0 100644 --- a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java +++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java @@ -26,7 +26,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; public abstract class FluentIterableTest { /** - * Create a new {@link FluentIterable} from the given integers + * Create a new {@link FluentIterable} from the given integers * * @param integers The integers * @return The new iterable, use for testing diff --git a/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java b/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java index 26c836b0e..1ff624e11 100644 --- a/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java +++ b/flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java @@ -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) { diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java index a48abbcb0..8418e01e6 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java @@ -14,6 +14,9 @@ public class AlchemistShop { private List topShelf; private List 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"); diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/App.java b/front-controller/src/main/java/com/iluwatar/front/controller/App.java index 18a92d37d..1beac119c 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/App.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/App.java @@ -2,32 +2,34 @@ package com.iluwatar.front.controller; /** * - * The Front Controller is a presentation tier pattern. Essentially it defines a - * controller that handles all requests for a web site. + * The Front Controller is a presentation tier pattern. Essentially it defines a controller that + * handles all requests for a web site. *

- * 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. *

- * 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}). *

* In this example we have implemented two views: {@link ArcherView} and {@link CatapultView}. These - * are displayed by sending correct request to the {@link FrontController} object. For example, - * the {@link ArcherView} gets displayed when {@link FrontController} receives request "Archer". When + * are displayed by sending correct request to the {@link FrontController} object. For example, the + * {@link ArcherView} gets displayed when {@link FrontController} receives request "Archer". When * the request is unknown, we display the error view ({@link ErrorView}). * */ public class App { - - /** - * Program entry point - * @param args command line args - */ - public static void main(String[] args) { - FrontController controller = new FrontController(); - controller.handleRequest("Archer"); - controller.handleRequest("Catapult"); - controller.handleRequest("foobar"); - } + + /** + * Program entry point + * + * @param args + * command line args + */ + public static void main(String[] args) { + FrontController controller = new FrontController(); + controller.handleRequest("Archer"); + controller.handleRequest("Catapult"); + controller.handleRequest("foobar"); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java b/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java index b3963d8e9..bb44d34f0 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java @@ -7,9 +7,9 @@ package com.iluwatar.front.controller; */ public class ApplicationException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public ApplicationException(Throwable cause) { - super(cause); - } + public ApplicationException(Throwable cause) { + super(cause); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java index 117aa0c8c..8396d5cfc 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class ArcherCommand implements Command { - @Override - public void process() { - new ArcherView().display(); - } + @Override + public void process() { + new ArcherView().display(); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java index d8cae33c1..d16fe8b71 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class ArcherView implements View { - @Override - public void display() { - System.out.println("Displaying archers"); - } + @Override + public void display() { + System.out.println("Displaying archers"); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java index fae5d1753..b5ad9e37c 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class CatapultCommand implements Command { - @Override - public void process() { - new CatapultView().display(); - } + @Override + public void process() { + new CatapultView().display(); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java index 9ad94d522..161b4ed4e 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class CatapultView implements View { - @Override - public void display() { - System.out.println("Displaying catapults"); - } + @Override + public void display() { + System.out.println("Displaying catapults"); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/Command.java b/front-controller/src/main/java/com/iluwatar/front/controller/Command.java index 95bd00129..2ad41a629 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/Command.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/Command.java @@ -6,6 +6,6 @@ package com.iluwatar.front.controller; * */ public interface Command { - - void process(); + + void process(); } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java b/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java index 04c31dd34..c1045c821 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class ErrorView implements View { - @Override - public void display() { - System.out.println("Error 500"); - } + @Override + public void display() { + System.out.println("Error 500"); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java index 0c6c132f2..6b84d7f78 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java @@ -2,33 +2,33 @@ package com.iluwatar.front.controller; /** * - * FrontController is the handler class that takes in all the requests and - * renders the correct response. + * FrontController is the handler class that takes in all the requests and renders the correct + * response. * */ public class FrontController { - - public void handleRequest(String request) { - Command command = getCommand(request); - command.process(); - } - - private Command getCommand(String request) { - Class commandClass = getCommandClass(request); - try { - return (Command) commandClass.newInstance(); - } catch (Exception e) { - throw new ApplicationException(e); - } - } - - private Class getCommandClass(String request) { - Class result; - try { - result = Class.forName("com.iluwatar.front.controller." + request + "Command"); - } catch (ClassNotFoundException e) { - result = UnknownCommand.class; - } - return result; - } + + public void handleRequest(String request) { + Command command = getCommand(request); + command.process(); + } + + private Command getCommand(String request) { + Class commandClass = getCommandClass(request); + try { + return (Command) commandClass.newInstance(); + } catch (Exception e) { + throw new ApplicationException(e); + } + } + + private Class getCommandClass(String request) { + Class result; + try { + result = Class.forName("com.iluwatar.front.controller." + request + "Command"); + } catch (ClassNotFoundException e) { + result = UnknownCommand.class; + } + return result; + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java b/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java index f8f93e7e0..d800d4db0 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java @@ -7,8 +7,8 @@ package com.iluwatar.front.controller; */ public class UnknownCommand implements Command { - @Override - public void process() { - new ErrorView().display(); - } + @Override + public void process() { + new ErrorView().display(); + } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/View.java b/front-controller/src/main/java/com/iluwatar/front/controller/View.java index 29c5f0fcb..55bb187ce 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/View.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/View.java @@ -7,5 +7,5 @@ package com.iluwatar.front.controller; */ public interface View { - void display(); + void display(); } diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java index 2c28aa8ce..f858a797d 100644 --- a/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java +++ b/front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java @@ -10,10 +10,10 @@ import com.iluwatar.front.controller.App; * */ public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } + + @Test + public void test() { + String[] args = {}; + App.main(args); + } } diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java index 18bdf0d13..4b038cfda 100644 --- a/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java +++ b/front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java @@ -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 diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java index 80f2eefb2..b67b602ca 100644 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java +++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java @@ -21,17 +21,15 @@ import java.util.concurrent.LinkedBlockingQueue; * *

* APPLICABILITY
- *

    - *
  • UNIX network subsystems - In operating systems network operations are carried out - * asynchronously with help of hardware level interrupts.
  • - *
  • 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.
    + * 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.
  • - *
  • Android AsyncTask framework - Framework provides a way to execute long running blocking + * request and sends response back to the client.
    + * 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. - *
+ * respond to user inputs.
* *

* IMPLEMENTATION
@@ -121,6 +119,7 @@ public class App { try { Thread.sleep(i); } catch (InterruptedException e) { + System.out.println(e); } return (i) * (i + 1) / 2; } diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java index c1aa0780b..38a762483 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java @@ -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; + } } } diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java index 02499ed0a..5934da75c 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java @@ -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); diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java index 9496bde36..a1ea5b4ee 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java @@ -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(); } diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java index 987678cc7..b180579d2 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java @@ -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); diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java index 5b30fee35..53d1a3dd9 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java @@ -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; diff --git a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java index cb96cd6e0..ffb13c160 100644 --- a/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java +++ b/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java @@ -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); diff --git a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java index f15760f08..71d9bf250 100644 --- a/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java +++ b/intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java @@ -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; diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/App.java b/interpreter/src/main/java/com/iluwatar/interpreter/App.java index 2f88951f1..e4e238c15 100644 --- a/interpreter/src/main/java/com/iluwatar/interpreter/App.java +++ b/interpreter/src/main/java/com/iluwatar/interpreter/App.java @@ -55,6 +55,9 @@ public class App { return s.equals("+") || s.equals("-") || s.equals("*"); } + /** + * Get expression for string + */ public static Expression getOperatorInstance(String s, Expression left, Expression right) { switch (s) { case "+": @@ -63,7 +66,8 @@ public class App { return new MinusExpression(left, right); case "*": return new MultiplyExpression(left, right); + default: + return new MultiplyExpression(left, right); } - return null; } } diff --git a/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java b/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java index 2cdee9966..150596cd8 100644 --- a/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java +++ b/interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java @@ -27,9 +27,9 @@ public abstract class ExpressionTest { for (int i = -10; i < 10; i++) { for (int j = -10; j < 10; j++) { testData.add(new Object[]{ - new NumberExpression(i), - new NumberExpression(j), - resultCalc.apply(i, j) + new NumberExpression(i), + new NumberExpression(j), + resultCalc.apply(i, j) }); } } diff --git a/iterator/src/main/java/com/iluwatar/iterator/App.java b/iterator/src/main/java/com/iluwatar/iterator/App.java index c9c5fa521..467040ca6 100644 --- a/iterator/src/main/java/com/iluwatar/iterator/App.java +++ b/iterator/src/main/java/com/iluwatar/iterator/App.java @@ -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()); } diff --git a/iterator/src/main/java/com/iluwatar/iterator/TreasureChest.java b/iterator/src/main/java/com/iluwatar/iterator/TreasureChest.java index 02496e33c..6b5c54a5a 100644 --- a/iterator/src/main/java/com/iluwatar/iterator/TreasureChest.java +++ b/iterator/src/main/java/com/iluwatar/iterator/TreasureChest.java @@ -12,6 +12,9 @@ public class TreasureChest { private List 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 getItems() { ArrayList list = new ArrayList<>(); list.addAll(items); diff --git a/iterator/src/main/java/com/iluwatar/iterator/TreasureChestItemIterator.java b/iterator/src/main/java/com/iluwatar/iterator/TreasureChestItemIterator.java index 39c12ab44..a8303f308 100644 --- a/iterator/src/main/java/com/iluwatar/iterator/TreasureChestItemIterator.java +++ b/iterator/src/main/java/com/iluwatar/iterator/TreasureChestItemIterator.java @@ -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; diff --git a/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java b/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java index a32066ea8..a2102a2e2 100644 --- a/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java +++ b/iterator/src/test/java/com/iluwatar/iterator/TreasureChestTest.java @@ -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()) { diff --git a/layers/src/main/java/com/iluwatar/layers/App.java b/layers/src/main/java/com/iluwatar/layers/App.java index d175553f7..ecb532510 100644 --- a/layers/src/main/java/com/iluwatar/layers/App.java +++ b/layers/src/main/java/com/iluwatar/layers/App.java @@ -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. *

- * 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. *

- * The data access layer is formed of Spring Data repositories CakeDao, - * CakeToppingDao and CakeLayerDao. 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 CakeDao, CakeToppingDao and + * CakeLayerDao. The repositories can be used for CRUD operations on cakes, cake toppings and cake layers + * respectively. *

- * The business layer is built on top of the data access layer. CakeBakingService - * 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. CakeBakingService 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 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. *

- * 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 ( - * CakeInfo, CakeToppingInfo, CakeLayerInfo) to translate - * data between layers. In other words, CakeBakingService cannot return entities ( - * Cake, CakeTopping, CakeLayer) directly since these reside - * on data access layer but instead translates these into business layer DTOs (CakeInfo, CakeToppingInfo, CakeLayerInfo) 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 ( CakeInfo, + * CakeToppingInfo, CakeLayerInfo) to translate data between layers. In other words, + * CakeBakingService cannot return entities ( Cake, CakeTopping, + * CakeLayer) directly since these reside on data access layer but instead translates these into business + * layer DTOs (CakeInfo, CakeToppingInfo, CakeLayerInfo) 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)); diff --git a/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java b/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java index 80bd3438b..adfa585d6 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java @@ -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 getAllCakes(); /** * Store new cake topping - * - * @param toppingInfo */ void saveNewTopping(CakeToppingInfo toppingInfo); /** * Get available cake toppings - * - * @return */ List getAvailableToppings(); /** * Add new cake layer - * - * @param layerInfo */ void saveNewLayer(CakeLayerInfo layerInfo); /** * Get available cake layers - * - * @return */ List getAvailableLayers(); } diff --git a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeInfo.java index f60ee9a14..6ae5008f0 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeInfo.java @@ -14,18 +14,27 @@ public class CakeInfo { public final CakeToppingInfo cakeToppingInfo; public final List cakeLayerInfos; + /** + * Constructor + */ public CakeInfo(Long id, CakeToppingInfo cakeToppingInfo, List cakeLayerInfos) { this.id = Optional.of(id); this.cakeToppingInfo = cakeToppingInfo; this.cakeLayerInfos = cakeLayerInfos; } + /** + * Constructor + */ public CakeInfo(CakeToppingInfo cakeToppingInfo, List 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(); diff --git a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java index 3dff379da..339a61b4e 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java @@ -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; diff --git a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java b/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java index 4e432ec44..726d597d2 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java @@ -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; diff --git a/layers/src/main/resources/META-INF/persistence.xml b/layers/src/main/resources/META-INF/persistence.xml index d94d8582b..96856e1b9 100644 --- a/layers/src/main/resources/META-INF/persistence.xml +++ b/layers/src/main/resources/META-INF/persistence.xml @@ -1,8 +1,8 @@ + xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> - + \ No newline at end of file diff --git a/layers/src/main/resources/applicationContext.xml b/layers/src/main/resources/applicationContext.xml index 0c908ad2e..6b3bc466d 100644 --- a/layers/src/main/resources/applicationContext.xml +++ b/layers/src/main/resources/applicationContext.xml @@ -1,42 +1,39 @@ - + - + - + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java index 25e46d8b9..dabd8c313 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java @@ -7,6 +7,9 @@ package com.iluwatar.lazy.loading; */ public class Heavy { + /** + * Constructor + */ public Heavy() { System.out.println("Creating Heavy ..."); try { diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java index 132ebaa5f..f78005c73 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java @@ -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(); diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java index d2b15a3af..56074846e 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java @@ -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(); diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java index da021e014..aa86e3b34 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java @@ -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} as {@link Heavy} factory. + * Java 8 functional interface {@link Supplier} as {@link Heavy} factory. * */ public class Java8Holder { diff --git a/memento/src/main/java/com/iluwatar/memento/App.java b/memento/src/main/java/com/iluwatar/memento/App.java index c99894680..e08e9a106 100644 --- a/memento/src/main/java/com/iluwatar/memento/App.java +++ b/memento/src/main/java/com/iluwatar/memento/App.java @@ -23,6 +23,9 @@ import java.util.Stack; */ public class App { + /** + * Program entry point + */ public static void main(String[] args) { Stack states = new Stack<>(); diff --git a/memento/src/main/java/com/iluwatar/memento/Star.java b/memento/src/main/java/com/iluwatar/memento/Star.java index b4ec1c669..f67edfd15 100644 --- a/memento/src/main/java/com/iluwatar/memento/Star.java +++ b/memento/src/main/java/com/iluwatar/memento/Star.java @@ -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; diff --git a/message-channel/src/main/java/com/iluwatar/message/channel/App.java b/message-channel/src/main/java/com/iluwatar/message/channel/App.java index a41dd74dc..b0aeb690f 100644 --- a/message-channel/src/main/java/com/iluwatar/message/channel/App.java +++ b/message-channel/src/main/java/com/iluwatar/message/channel/App.java @@ -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(); diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java index d04f284ac..0cf4f8c34 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java @@ -39,9 +39,7 @@ public class FileLoader { br.close(); return sb.toString(); - } - - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); } diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java index 02cb2703a..6f220cffb 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java @@ -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(); } } diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java index 133d8555d..f38dc2655 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java @@ -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."); } } diff --git a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java b/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java index dfdcba31b..ba371525a 100644 --- a/model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java +++ b/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()); } /** diff --git a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java index b81e44251..429eda73e 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java +++ b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java @@ -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; diff --git a/monostate/src/main/java/com/iluwatar/monostate/Server.java b/monostate/src/main/java/com/iluwatar/monostate/Server.java index f48f4ad0f..21794de42 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/Server.java +++ b/monostate/src/main/java/com/iluwatar/monostate/Server.java @@ -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; diff --git a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java index 6769f95dd..fa1e74048 100644 --- a/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java +++ b/naked-objects/dom/src/main/java/domainapp/dom/app/homepage/HomePageService.java @@ -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) diff --git a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java b/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java index 5e4642455..849f01c5d 100644 --- a/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java +++ b/naked-objects/dom/src/main/java/domainapp/dom/modules/simple/SimpleObjects.java @@ -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); diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java b/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java index 2918fe7f6..266529c74 100644 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java +++ b/naked-objects/fixture/src/main/java/domainapp/fixture/modules/simple/SimpleObjectCreate.java @@ -45,8 +45,6 @@ public class SimpleObjectCreate extends FixtureScript { /** * The created simple object (output). - * - * @return */ public SimpleObject getSimpleObject() { return simpleObject; diff --git a/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java b/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java index c978e0b82..c82ef8498 100644 --- a/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java +++ b/naked-objects/fixture/src/main/java/domainapp/fixture/scenarios/RecreateSimpleObjects.java @@ -29,7 +29,7 @@ import domainapp.fixture.modules.simple.SimpleObjectsTearDown; public class RecreateSimpleObjects extends FixtureScript { - public final List NAMES = Collections.unmodifiableList(Arrays.asList("Foo", "Bar", "Baz", + public final List 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()); } diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java b/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java index c617915f1..0384b0eb4 100644 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java +++ b/naked-objects/integtests/src/test/java/domainapp/integtests/bootstrap/SimpleAppSystemInitializer.java @@ -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) { diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java b/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java index ef6012919..2ea375b4a 100644 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java +++ b/naked-objects/integtests/src/test/java/domainapp/integtests/specglue/modules/simple/SimpleObjectGlue.java @@ -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 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()); } diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java index 3ceef4e63..7a7ad91b2 100644 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java +++ b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/SimpleAppIntegTest.java @@ -27,13 +27,13 @@ import domainapp.integtests.bootstrap.SimpleAppSystemInitializer; public abstract class SimpleAppIntegTest extends IntegrationTestAbstract { - @BeforeClass - public static void initClass() { - org.apache.log4j.PropertyConfigurator.configure("logging.properties"); - SimpleAppSystemInitializer.initIsft(); + @BeforeClass + public static void initClass() { + org.apache.log4j.PropertyConfigurator.configure("logging.properties"); + SimpleAppSystemInitializer.initIsft(); - // instantiating will install onto ThreadLocal - new ScenarioExecutionForIntegration(); - } + // instantiating will install onto ThreadLocal + new ScenarioExecutionForIntegration(); + } } diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java index 610136bb8..872aff7a3 100644 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java +++ b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectIntegTest.java @@ -35,87 +35,86 @@ import static org.assertj.core.api.Assertions.assertThat; public class SimpleObjectIntegTest extends SimpleAppIntegTest { + @Inject + FixtureScripts fixtureScripts; + + RecreateSimpleObjects fs; + SimpleObject simpleObjectPojo; + SimpleObject simpleObjectWrapped; + + @Before + public void setUp() throws Exception { + // given + fs = new RecreateSimpleObjects().setNumber(1); + fixtureScripts.runFixtureScript(fs, null); + + simpleObjectPojo = fs.getSimpleObjects().get(0); + + assertThat(simpleObjectPojo).isNotNull(); + simpleObjectWrapped = wrap(simpleObjectPojo); + } + + public static class Name extends SimpleObjectIntegTest { + + @Test + public void accessible() throws Exception { + // when + final String name = simpleObjectWrapped.getName(); + // then + assertThat(name).isEqualTo(fs.names.get(0)); + } + + @Test + public void cannotBeUpdatedDirectly() throws Exception { + + // expect + expectedExceptions.expect(DisabledException.class); + + // when + simpleObjectWrapped.setName("new name"); + } + } + + public static class UpdateName extends SimpleObjectIntegTest { + + @Test + public void happyCase() throws Exception { + + // when + simpleObjectWrapped.updateName("new name"); + + // then + assertThat(simpleObjectWrapped.getName()).isEqualTo("new name"); + } + + @Test + public void failsValidation() throws Exception { + + // expect + expectedExceptions.expect(InvalidException.class); + expectedExceptions.expectMessage("Exclamation mark is not allowed"); + + // when + simpleObjectWrapped.updateName("new name!"); + } + } + + public static class Title extends SimpleObjectIntegTest { + @Inject - FixtureScripts fixtureScripts; + DomainObjectContainer container; - RecreateSimpleObjects fs; - SimpleObject simpleObjectPojo; - SimpleObject simpleObjectWrapped; + @Test + public void interpolatesName() throws Exception { - @Before - public void setUp() throws Exception { - // given - fs = new RecreateSimpleObjects().setNumber(1); - fixtureScripts.runFixtureScript(fs, null); + // given + final String name = simpleObjectWrapped.getName(); - simpleObjectPojo = fs.getSimpleObjects().get(0); + // when + final String title = container.titleOf(simpleObjectWrapped); - assertThat(simpleObjectPojo).isNotNull(); - simpleObjectWrapped = wrap(simpleObjectPojo); - } - - public static class Name extends SimpleObjectIntegTest { - - @Test - public void accessible() throws Exception { - // when - final String name = simpleObjectWrapped.getName(); - // then - assertThat(name).isEqualTo(fs.NAMES.get(0)); - } - - @Test - public void cannotBeUpdatedDirectly() throws Exception { - - // expect - expectedExceptions.expect(DisabledException.class); - - // when - simpleObjectWrapped.setName("new name"); - } - } - - public static class UpdateName extends SimpleObjectIntegTest { - - @Test - public void happyCase() throws Exception { - - // when - simpleObjectWrapped.updateName("new name"); - - // then - assertThat(simpleObjectWrapped.getName()).isEqualTo("new name"); - } - - @Test - public void failsValidation() throws Exception { - - // expect - expectedExceptions.expect(InvalidException.class); - expectedExceptions.expectMessage("Exclamation mark is not allowed"); - - // when - simpleObjectWrapped.updateName("new name!"); - } - } - - - public static class Title extends SimpleObjectIntegTest { - - @Inject - DomainObjectContainer container; - - @Test - public void interpolatesName() throws Exception { - - // given - final String name = simpleObjectWrapped.getName(); - - // when - final String title = container.titleOf(simpleObjectWrapped); - - // then - assertThat(title).isEqualTo("Object: " + name); - } + // then + assertThat(title).isEqualTo("Object: " + name); } + } } \ No newline at end of file diff --git a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java index fd3b0ff46..332213542 100644 --- a/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java +++ b/naked-objects/integtests/src/test/java/domainapp/integtests/tests/modules/simple/SimpleObjectsIntegTest.java @@ -42,102 +42,102 @@ import static org.assertj.core.api.Assertions.assertThat; public class SimpleObjectsIntegTest extends SimpleAppIntegTest { - @Inject - FixtureScripts fixtureScripts; - @Inject - SimpleObjects simpleObjects; + @Inject + FixtureScripts fixtureScripts; + @Inject + SimpleObjects simpleObjects; - public static class ListAll extends SimpleObjectsIntegTest { + public static class ListAll extends SimpleObjectsIntegTest { - @Test - public void happyCase() throws Exception { + @Test + public void happyCase() throws Exception { - // given - RecreateSimpleObjects fs = new RecreateSimpleObjects(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); + // given + RecreateSimpleObjects fs = new RecreateSimpleObjects(); + fixtureScripts.runFixtureScript(fs, null); + nextTransaction(); - // when - final List all = wrap(simpleObjects).listAll(); + // when + final List all = wrap(simpleObjects).listAll(); - // then - assertThat(all).hasSize(fs.getSimpleObjects().size()); + // then + assertThat(all).hasSize(fs.getSimpleObjects().size()); - SimpleObject simpleObject = wrap(all.get(0)); - assertThat(simpleObject.getName()).isEqualTo(fs.getSimpleObjects().get(0).getName()); - } - - @Test - public void whenNone() throws Exception { - - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - - // when - final List all = wrap(simpleObjects).listAll(); - - // then - assertThat(all).hasSize(0); - } + SimpleObject simpleObject = wrap(all.get(0)); + assertThat(simpleObject.getName()).isEqualTo(fs.getSimpleObjects().get(0).getName()); } - public static class Create extends SimpleObjectsIntegTest { + @Test + public void whenNone() throws Exception { - @Test - public void happyCase() throws Exception { + // given + FixtureScript fs = new SimpleObjectsTearDown(); + fixtureScripts.runFixtureScript(fs, null); + nextTransaction(); - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); + // when + final List all = wrap(simpleObjects).listAll(); - // when - wrap(simpleObjects).create("Faz"); - - // then - final List all = wrap(simpleObjects).listAll(); - assertThat(all).hasSize(1); - } - - @Test - public void whenAlreadyExists() throws Exception { - - // given - FixtureScript fs = new SimpleObjectsTearDown(); - fixtureScripts.runFixtureScript(fs, null); - nextTransaction(); - wrap(simpleObjects).create("Faz"); - nextTransaction(); - - // then - expectedExceptions.expectCause(causalChainContains(SQLIntegrityConstraintViolationException.class)); - - // when - wrap(simpleObjects).create("Faz"); - nextTransaction(); - } - - private static Matcher causalChainContains(final Class cls) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(Throwable item) { - final List causalChain = Throwables.getCausalChain(item); - for (Throwable throwable : causalChain) { - if(cls.isAssignableFrom(throwable.getClass())){ - return true; - } - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("exception with causal chain containing " + cls.getSimpleName()); - } - }; - } + // then + assertThat(all).hasSize(0); } + } + + public static class Create extends SimpleObjectsIntegTest { + + @Test + public void happyCase() throws Exception { + + // given + FixtureScript fs = new SimpleObjectsTearDown(); + fixtureScripts.runFixtureScript(fs, null); + nextTransaction(); + + // when + wrap(simpleObjects).create("Faz"); + + // then + final List all = wrap(simpleObjects).listAll(); + assertThat(all).hasSize(1); + } + + @Test + public void whenAlreadyExists() throws Exception { + + // given + FixtureScript fs = new SimpleObjectsTearDown(); + fixtureScripts.runFixtureScript(fs, null); + nextTransaction(); + wrap(simpleObjects).create("Faz"); + nextTransaction(); + + // then + expectedExceptions.expectCause(causalChainContains(SQLIntegrityConstraintViolationException.class)); + + // when + wrap(simpleObjects).create("Faz"); + nextTransaction(); + } + + private static Matcher causalChainContains(final Class cls) { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(Throwable item) { + final List causalChain = Throwables.getCausalChain(item); + for (Throwable throwable : causalChain) { + if (cls.isAssignableFrom(throwable.getClass())) { + return true; + } + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("exception with causal chain containing " + cls.getSimpleName()); + } + }; + } + } } \ No newline at end of file diff --git a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java b/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java index c7bbd8c80..a292a7779 100644 --- a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java +++ b/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java @@ -74,7 +74,7 @@ public class SimpleApplication extends IsisWicketApplication { *

* 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; diff --git a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java b/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java index 5de258890..4478b9bfa 100644 --- a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java +++ b/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java @@ -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; diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java b/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java index 79d7d6345..d85955f0a 100644 --- a/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java +++ b/object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java @@ -5,8 +5,6 @@ import java.util.HashSet; /** * * Generic object pool - * - * @param */ public abstract class ObjectPool { @@ -15,6 +13,9 @@ public abstract class ObjectPool { protected abstract T create(); + /** + * Checkout object from pool + */ public synchronized T checkOut() { if (available.size() <= 0) { available.add(create()); diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java b/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java index aeefd6b3a..f3923fff5 100644 --- a/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java +++ b/object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java @@ -11,6 +11,9 @@ public class Oliphaunt { private final int id; + /** + * Constructor + */ public Oliphaunt() { id = counter++; try { diff --git a/observer/src/main/java/com/iluwatar/observer/Weather.java b/observer/src/main/java/com/iluwatar/observer/Weather.java index 634953945..4e04143a2 100644 --- a/observer/src/main/java/com/iluwatar/observer/Weather.java +++ b/observer/src/main/java/com/iluwatar/observer/Weather.java @@ -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]; diff --git a/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java b/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java index 9d1c6ed07..d503c8421 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java @@ -15,6 +15,9 @@ public class GWeather extends Observable { currentWeather = WeatherType.SUNNY; } + /** + * Makes time pass for weather + */ public void timePasses() { WeatherType[] enumValues = WeatherType.values(); currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; diff --git a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java index f1ad2dca6..f3b3c7dbb 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java @@ -22,6 +22,9 @@ public abstract class Observable, O extends Observ this.observers.add(observer); } + /** + * Notify observers + */ @SuppressWarnings("unchecked") public void notifyObservers(A argument) { for (O observer : observers) { diff --git a/observer/src/main/java/com/iluwatar/observer/generic/Observer.java b/observer/src/main/java/com/iluwatar/observer/generic/Observer.java index b01955419..34b9ac359 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/Observer.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/Observer.java @@ -3,10 +3,6 @@ package com.iluwatar.observer.generic; /** * * Observer - * - * @param - * @param - * @param */ public interface Observer, O extends Observer, A> { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java index ff06d7d5b..a305c010c 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java @@ -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; diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java index 99231ab51..aa0d3699d 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java @@ -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 { } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MQPublishPoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java similarity index 81% rename from poison-pill/src/main/java/com/iluwatar/poison/pill/MQPublishPoint.java rename to poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java index a266d9f4d..74ed43e33 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MQPublishPoint.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java @@ -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; } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MQSubscribePoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java similarity index 80% rename from poison-pill/src/main/java/com/iluwatar/poison/pill/MQSubscribePoint.java rename to poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java index c093b1412..ed7624116 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MQSubscribePoint.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java @@ -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; } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java index ecde39e35..5405de869 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java @@ -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 { diff --git a/pom.xml b/pom.xml index 724b058f1..1285c8108 100644 --- a/pom.xml +++ b/pom.xml @@ -244,7 +244,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 2.15 + 2.17 validate diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java index 599a80407..849c2413c 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java @@ -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", diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java index 9deb32e16..2efd0b4ee 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java @@ -12,6 +12,9 @@ public class Stew { private int numMeat; private int numPeppers; + /** + * Constructor + */ public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { this.numPotatoes = numPotatoes; this.numCarrots = numCarrots; @@ -19,12 +22,18 @@ public class Stew { this.numPeppers = numPeppers; } + /** + * Mix the stew + */ public void mix() { System.out.println(String.format( "Mixing the stew we find: %d potatoes, %d carrots, %d meat and %d peppers", numPotatoes, numCarrots, numMeat, numPeppers)); } + /** + * Taste the stew + */ public void taste() { System.out.println("Tasting the stew"); if (numPotatoes > 0) { diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java index 23d54ccf4..0bd62ada3 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java @@ -12,6 +12,9 @@ public class StewData { private int numMeat; private int numPeppers; + /** + * Constructor + */ public StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { this.numPotatoes = numPotatoes; this.numCarrots = numCarrots; diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java index 50d94d92f..63cae9413 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java @@ -5,14 +5,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** - * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces - * coupling between Producer and Consumer by separating Identification of work with Execution of - * Work. + * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces coupling between + * Producer and Consumer by separating Identification of work with Execution of Work. *

- * In producer consumer design pattern a shared queue is used to control the flow and this - * separation allows you to code producer and consumer separately. It also addresses the issue of - * different timing require to produce item or consuming item. by using producer consumer pattern - * both Producer and Consumer Thread can work with different speed. + * In producer consumer design pattern a shared queue is used to control the flow and this separation allows you to code + * producer and consumer separately. It also addresses the issue of different timing require to produce item or + * consuming item. by using producer consumer pattern both Producer and Consumer Thread can work with different speed. * */ public class App { @@ -20,7 +18,8 @@ public class App { /** * Program entry point * - * @param args command line args + * @param args + * command line args */ public static void main(String[] args) { @@ -35,7 +34,7 @@ public class App { producer.produce(); } }); - }; + } for (int i = 0; i < 3; i++) { final Consumer consumer = new Consumer("Consumer_" + i, queue); diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java index 8bb3b75b6..ff63ab41b 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java @@ -14,6 +14,9 @@ public class Consumer { this.queue = queue; } + /** + * Consume item from the queue + */ public void consume() throws InterruptedException { Item item = queue.take(); diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java index 40e71c607..8b122a5fc 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java @@ -19,6 +19,9 @@ public class Producer { this.queue = queue; } + /** + * Put item in the queue + */ public void produce() throws InterruptedException { Item item = new Item(name, itemId++); diff --git a/property/src/main/java/com/iluwatar/property/Character.java b/property/src/main/java/com/iluwatar/property/Character.java index 10b8f495d..50e564623 100644 --- a/property/src/main/java/com/iluwatar/property/Character.java +++ b/property/src/main/java/com/iluwatar/property/Character.java @@ -18,6 +18,9 @@ public class Character implements Prototype { private String name; private Type type; + /** + * Constructor + */ public Character() { this.prototype = new Prototype() { // Null-value object @Override @@ -43,6 +46,9 @@ public class Character implements Prototype { this.prototype = prototype; } + /** + * Constructor + */ public Character(String name, Character prototype) { this.name = name; this.type = prototype.type; diff --git a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java b/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java index 4c5a60bcd..85792104d 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java +++ b/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java @@ -11,12 +11,18 @@ public class HeroFactoryImpl implements HeroFactory { private Warlord warlord; private Beast beast; + /** + * Constructor + */ public HeroFactoryImpl(Mage mage, Warlord warlord, Beast beast) { this.mage = mage; this.warlord = warlord; this.beast = beast; } + /** + * Create mage + */ public Mage createMage() { try { return mage.clone(); @@ -25,6 +31,9 @@ public class HeroFactoryImpl implements HeroFactory { } } + /** + * Create warlord + */ public Warlord createWarlord() { try { return warlord.clone(); @@ -33,6 +42,9 @@ public class HeroFactoryImpl implements HeroFactory { } } + /** + * Create beast + */ public Beast createBeast() { try { return beast.clone(); diff --git a/proxy/src/main/java/com/iluwatar/proxy/App.java b/proxy/src/main/java/com/iluwatar/proxy/App.java index 25a903e41..837424f28 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/App.java +++ b/proxy/src/main/java/com/iluwatar/proxy/App.java @@ -18,6 +18,9 @@ package com.iluwatar.proxy; */ public class App { + /** + * Program entry point + */ public static void main(String[] args) { WizardTowerProxy tower = new WizardTowerProxy(); diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java index 30f982ed1..f80dd1ad1 100644 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java @@ -28,10 +28,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(); diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/App.java b/reactor/src/main/java/com/iluwatar/reactor/app/App.java index 2c49d9001..d074c9b19 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/App.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/App.java @@ -80,8 +80,6 @@ public class App { /** * App entry. - * - * @throws IOException */ public static void main(String[] args) throws IOException { new App(new ThreadPoolDispatcher(2)).start(); diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java index ee25b0be0..13cdd70e1 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java @@ -37,10 +37,10 @@ public class AppClient { * @throws IOException if any I/O error occurs. */ public void start() throws IOException { - service.execute(new TCPLoggingClient("Client 1", 6666)); - service.execute(new TCPLoggingClient("Client 2", 6667)); - service.execute(new UDPLoggingClient("Client 3", 6668)); - service.execute(new UDPLoggingClient("Client 4", 6668)); + service.execute(new TcpLoggingClient("Client 1", 6666)); + service.execute(new TcpLoggingClient("Client 2", 6667)); + service.execute(new UdpLoggingClient("Client 3", 6668)); + service.execute(new UdpLoggingClient("Client 4", 6668)); } /** @@ -69,7 +69,7 @@ public class AppClient { /** * A logging client that sends requests to Reactor on TCP socket. */ - static class TCPLoggingClient implements Runnable { + static class TcpLoggingClient implements Runnable { private final int serverPort; private final String clientName; @@ -80,7 +80,7 @@ public class AppClient { * @param clientName the name of the client to be sent in logging requests. * @param port the port on which client will send logging requests. */ - public TCPLoggingClient(String clientName, int serverPort) { + public TcpLoggingClient(String clientName, int serverPort) { this.clientName = clientName; this.serverPort = serverPort; } @@ -118,7 +118,7 @@ public class AppClient { /** * A logging client that sends requests to Reactor on UDP socket. */ - static class UDPLoggingClient implements Runnable { + static class UdpLoggingClient implements Runnable { private final String clientName; private final InetSocketAddress remoteAddress; @@ -129,7 +129,7 @@ public class AppClient { * @param port the port on which client will send logging requests. * @throws UnknownHostException if localhost is unknown */ - public UDPLoggingClient(String clientName, int port) throws UnknownHostException { + public UdpLoggingClient(String clientName, int port) throws UnknownHostException { this.clientName = clientName; this.remoteAddress = new InetSocketAddress(InetAddress.getLocalHost(), port); } diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java index df08426d0..cd1318c89 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java @@ -131,6 +131,7 @@ public abstract class AbstractNioChannel { * channel.write(buffer, key); * } * + * * * @param data the data to be written on underlying channel. * @param key the key which is writable. diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java index 16c13e5f9..271a6975d 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java @@ -14,40 +14,41 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** - * This class acts as Synchronous Event De-multiplexer and Initiation Dispatcher of Reactor pattern. - * Multiple handles i.e. {@link AbstractNioChannel}s can be registered to the reactor and it blocks - * for events from all these handles. Whenever an event occurs on any of the registered handles, it - * synchronously de-multiplexes the event which can be any of read, write or accept, and dispatches - * the event to the appropriate {@link ChannelHandler} using the {@link Dispatcher}. + * This class acts as Synchronous Event De-multiplexer and Initiation Dispatcher of Reactor pattern. Multiple handles + * i.e. {@link AbstractNioChannel}s can be registered to the reactor and it blocks for events from all these handles. + * Whenever an event occurs on any of the registered handles, it synchronously de-multiplexes the event which can be any + * of read, write or accept, and dispatches the event to the appropriate {@link ChannelHandler} using the + * {@link Dispatcher}. * *

- * Implementation: A NIO reactor runs in its own thread when it is started using {@link #start()} - * method. {@link NioReactor} uses {@link Selector} for realizing Synchronous Event De-multiplexing. + * Implementation: A NIO reactor runs in its own thread when it is started using {@link #start()} method. + * {@link NioReactor} uses {@link Selector} for realizing Synchronous Event De-multiplexing. * *

- * NOTE: This is one of the ways to implement NIO reactor and it does not take care of all possible - * edge cases which are required in a real application. This implementation is meant to demonstrate - * the fundamental concepts that lie behind Reactor pattern. + * NOTE: This is one of the ways to implement NIO reactor and it does not take care of all possible edge cases which are + * required in a real application. This implementation is meant to demonstrate the fundamental concepts that lie behind + * Reactor pattern. */ public class NioReactor { private final Selector selector; private final Dispatcher dispatcher; /** - * All the work of altering the SelectionKey operations and Selector operations are performed in - * the context of main event loop of reactor. So when any channel needs to change its readability - * or writability, a new command is added in the command queue and then the event loop picks up - * the command and executes it in next iteration. + * All the work of altering the SelectionKey operations and Selector operations are performed in the context of main + * event loop of reactor. So when any channel needs to change its readability or writability, a new command is added + * in the command queue and then the event loop picks up the command and executes it in next iteration. */ private final Queue pendingCommands = new ConcurrentLinkedQueue<>(); private final ExecutorService reactorMain = Executors.newSingleThreadExecutor(); /** - * Creates a reactor which will use provided {@code dispatcher} to dispatch events. The - * application can provide various implementations of dispatcher which suits its needs. + * Creates a reactor which will use provided {@code dispatcher} to dispatch events. The application can provide + * various implementations of dispatcher which suits its needs. * - * @param dispatcher a non-null dispatcher used to dispatch events on registered channels. - * @throws IOException if any I/O error occurs. + * @param dispatcher + * a non-null dispatcher used to dispatch events on registered channels. + * @throws IOException + * if any I/O error occurs. */ public NioReactor(Dispatcher dispatcher) throws IOException { this.dispatcher = dispatcher; @@ -57,7 +58,8 @@ public class NioReactor { /** * Starts the reactor event loop in a new thread. * - * @throws IOException if any I/O error occurs. + * @throws IOException + * if any I/O error occurs. */ public void start() throws IOException { reactorMain.execute(() -> { @@ -73,8 +75,10 @@ public class NioReactor { /** * Stops the reactor and related resources such as dispatcher. * - * @throws InterruptedException if interrupted while stopping the reactor. - * @throws IOException if any I/O error occurs. + * @throws InterruptedException + * if interrupted while stopping the reactor. + * @throws IOException + * if any I/O error occurs. */ public void stop() throws InterruptedException, IOException { reactorMain.shutdownNow(); @@ -84,15 +88,15 @@ public class NioReactor { } /** - * Registers a new channel (handle) with this reactor. Reactor will start waiting for events on - * this channel and notify of any events. While registering the channel the reactor uses - * {@link AbstractNioChannel#getInterestedOps()} to know about the interested operation of this - * channel. + * Registers a new channel (handle) with this reactor. Reactor will start waiting for events on this channel and + * notify of any events. While registering the channel the reactor uses {@link AbstractNioChannel#getInterestedOps()} + * to know about the interested operation of this channel. * - * @param channel a new channel on which reactor will wait for events. The channel must be bound - * prior to being registered. + * @param channel + * a new channel on which reactor will wait for events. The channel must be bound prior to being registered. * @return this - * @throws IOException if any I/O error occurs. + * @throws IOException + * if any I/O error occurs. */ public NioReactor registerChannel(AbstractNioChannel channel) throws IOException { SelectionKey key = channel.getJavaChannel().register(selector, channel.getInterestedOps()); @@ -113,8 +117,8 @@ public class NioReactor { processPendingCommands(); /* - * Synchronous event de-multiplexing happens here, this is blocking call which returns when it - * is possible to initiate non-blocking operation on any of the registered channels. + * Synchronous event de-multiplexing happens here, this is blocking call which returns when it is possible to + * initiate non-blocking operation on any of the registered channels. */ selector.select(); @@ -147,8 +151,8 @@ public class NioReactor { } /* - * Initiation dispatcher logic, it checks the type of event and notifier application specific - * event handler to handle the event. + * Initiation dispatcher logic, it checks the type of event and notifier application specific event handler to handle + * the event. */ private void processKey(SelectionKey key) throws IOException { if (key.isAcceptable()) { @@ -196,14 +200,15 @@ public class NioReactor { } /** - * Queues the change of operations request of a channel, which will change the interested - * operations of the channel sometime in future. + * Queues the change of operations request of a channel, which will change the interested operations of the channel + * sometime in future. *

- * This is a non-blocking method and does not guarantee that the operations have changed when this - * method returns. + * This is a non-blocking method and does not guarantee that the operations have changed when this method returns. * - * @param key the key for which operations have to be changed. - * @param interestedOps the new interest operations. + * @param key + * the key for which operations have to be changed. + * @param interestedOps + * the new interest operations. */ public void changeOps(SelectionKey key, int interestedOps) { pendingCommands.add(new ChangeKeyOpsCommand(key, interestedOps)); diff --git a/repository/src/main/java/com/iluwatar/repository/AppConfig.java b/repository/src/main/java/com/iluwatar/repository/AppConfig.java index cca09d8aa..62b9a4c04 100644 --- a/repository/src/main/java/com/iluwatar/repository/AppConfig.java +++ b/repository/src/main/java/com/iluwatar/repository/AppConfig.java @@ -39,8 +39,6 @@ public class AppConfig { /** * Factory to create a especific instance of Entity Manager - * - * @return */ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { @@ -55,8 +53,6 @@ public class AppConfig { /** * Properties for Jpa - * - * @return */ private Properties jpaProperties() { Properties properties = new Properties(); @@ -65,6 +61,9 @@ public class AppConfig { return properties; } + /** + * Get transaction manager + */ @Bean public JpaTransactionManager transactionManager() throws SQLException { JpaTransactionManager transactionManager = new JpaTransactionManager(); diff --git a/repository/src/main/java/com/iluwatar/repository/Person.java b/repository/src/main/java/com/iluwatar/repository/Person.java index ca4013b54..04d65a6d0 100644 --- a/repository/src/main/java/com/iluwatar/repository/Person.java +++ b/repository/src/main/java/com/iluwatar/repository/Person.java @@ -23,6 +23,9 @@ public class Person { public Person() { } + /** + * Constructor + */ public Person(String name, String surname, int age) { this.name = name; this.surname = surname; @@ -80,30 +83,40 @@ public class Person { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Person other = (Person) obj; - if (age != other.age) + if (age != other.age) { return false; + } if (id == null) { - if (other.id != null) + if (other.id != null) { return false; - } else if (!id.equals(other.id)) + } + } else if (!id.equals(other.id)) { return false; + } if (name == null) { - if (other.name != null) + if (other.name != null) { return false; - } else if (!name.equals(other.name)) + } + } else if (!name.equals(other.name)) { return false; + } if (surname == null) { - if (other.surname != null) + if (other.surname != null) { return false; - } else if (!surname.equals(other.surname)) + } + } else if (!surname.equals(other.surname)) { return false; + } return true; } diff --git a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java index ce9842dff..fa96f3ca6 100644 --- a/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java +++ b/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java @@ -32,6 +32,10 @@ public class PersonSpecifications { } + /** + * Name specification + * + */ public static class NameEqualSpec implements Specification { public String name; @@ -40,6 +44,9 @@ public class PersonSpecifications { this.name = name; } + /** + * Get predicate + */ public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return cb.equal(root.get("name"), this.name); diff --git a/repository/src/main/resources/META-INF/persistence.xml b/repository/src/main/resources/META-INF/persistence.xml index 0aded0dbd..00767fbc2 100644 --- a/repository/src/main/resources/META-INF/persistence.xml +++ b/repository/src/main/resources/META-INF/persistence.xml @@ -1,8 +1,8 @@ + xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> - + diff --git a/repository/src/main/resources/applicationContext.xml b/repository/src/main/resources/applicationContext.xml index 9322c9f64..ed03aba0a 100644 --- a/repository/src/main/resources/applicationContext.xml +++ b/repository/src/main/resources/applicationContext.xml @@ -1,39 +1,37 @@ - + - - - - - + - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java index 6f8746aa6..682d2021f 100644 --- a/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java +++ b/repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java @@ -90,8 +90,8 @@ public class AnnotationBasedRepositoryTest { assertEquals(3, persons.size()); assertTrue(persons.stream().allMatch((item) -> { - return item.getAge() > 20 && item.getAge() < 40; - })); + return item.getAge() > 20 && item.getAge() < 40; + })); } @Test diff --git a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java index 49e684bf1..17393f2ff 100644 --- a/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java +++ b/repository/src/test/java/com/iluwatar/repository/AppConfigTest.java @@ -1,6 +1,7 @@ package com.iluwatar.repository; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.sql.ResultSet; import java.sql.SQLException; @@ -36,8 +37,6 @@ public class AppConfigTest { /** * Test for correct query execution - * - * @throws SQLException */ @Test @Transactional diff --git a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java index 3d6708815..9eb6b4723 100644 --- a/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java +++ b/repository/src/test/java/com/iluwatar/repository/RepositoryTest.java @@ -88,8 +88,8 @@ public class RepositoryTest { assertEquals(3, persons.size()); assertTrue(persons.stream().allMatch((item) -> { - return item.getAge() > 20 && item.getAge() < 40; - })); + return item.getAge() > 20 && item.getAge() < 40; + })); } @Test diff --git a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java index 32cd3792e..f734432af 100644 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java +++ b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java @@ -24,9 +24,6 @@ public class App { /** * Program entry point - * - * @param args command line args - * @throws Exception */ public static void main(String[] args) throws Exception { diff --git a/servant/src/main/java/com/iluwatar/servant/App.java b/servant/src/main/java/com/iluwatar/servant/App.java index 42babbc1d..cb5a63fa5 100644 --- a/servant/src/main/java/com/iluwatar/servant/App.java +++ b/servant/src/main/java/com/iluwatar/servant/App.java @@ -18,15 +18,13 @@ public class App { /** * Program entry point - * - * @param args */ public static void main(String[] args) { scenario(jenkins, 1); scenario(travis, 0); } - /* + /** * Can add a List with enum Actions for variable scenarios */ public static void scenario(Servant servant, int compliment) { @@ -44,16 +42,18 @@ public class App { servant.giveWine(k); servant.giveWine(q); // compliment - servant.GiveCompliments(guests.get(compliment)); + servant.giveCompliments(guests.get(compliment)); // outcome of the night - for (Royalty r : guests) + for (Royalty r : guests) { r.changeMood(); + } // check your luck - if (servant.checkIfYouWillBeHanged(guests)) + if (servant.checkIfYouWillBeHanged(guests)) { System.out.println(servant.name + " will live another day"); - else + } else { System.out.println("Poor " + servant.name + ". His days are numbered"); + } } } diff --git a/servant/src/main/java/com/iluwatar/servant/King.java b/servant/src/main/java/com/iluwatar/servant/King.java index 5e931c149..ab99252ad 100644 --- a/servant/src/main/java/com/iluwatar/servant/King.java +++ b/servant/src/main/java/com/iluwatar/servant/King.java @@ -28,10 +28,12 @@ public class King implements Royalty { @Override public void changeMood() { - if (!isHungry && isDrunk) + if (!isHungry && isDrunk) { isHappy = true; - if (complimentReceived) + } + if (complimentReceived) { isHappy = false; + } } @Override diff --git a/servant/src/main/java/com/iluwatar/servant/Queen.java b/servant/src/main/java/com/iluwatar/servant/Queen.java index db5446d34..cc33ab470 100644 --- a/servant/src/main/java/com/iluwatar/servant/Queen.java +++ b/servant/src/main/java/com/iluwatar/servant/Queen.java @@ -29,8 +29,9 @@ public class Queen implements Royalty { @Override public void changeMood() { - if (complimentReceived && isFlirty && isDrunk) + if (complimentReceived && isFlirty && isDrunk) { isHappy = true; + } } @Override diff --git a/servant/src/main/java/com/iluwatar/servant/Servant.java b/servant/src/main/java/com/iluwatar/servant/Servant.java index 987bf8791..dbb623331 100644 --- a/servant/src/main/java/com/iluwatar/servant/Servant.java +++ b/servant/src/main/java/com/iluwatar/servant/Servant.java @@ -11,6 +11,9 @@ public class Servant { public String name; + /** + * Constructor + */ public Servant(String name) { this.name = name; } @@ -23,15 +26,20 @@ public class Servant { r.getDrink(); } - public void GiveCompliments(Royalty r) { + public void giveCompliments(Royalty r) { r.receiveCompliments(); } + /** + * Check if we will be hanged + */ public boolean checkIfYouWillBeHanged(ArrayList tableGuests) { boolean anotherDay = true; - for (Royalty r : tableGuests) - if (!r.getMood()) + for (Royalty r : tableGuests) { + if (!r.getMood()) { anotherDay = false; + } + } return anotherDay; } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java b/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java index a7053165d..ab0d3f9a0 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java @@ -47,6 +47,9 @@ public class App { queryData(); } + /** + * Initialize data + */ public static void initData() { // spells Spell spell1 = new Spell("Ice dart"); @@ -149,6 +152,9 @@ public class App { wizardDao.merge(wizard4); } + /** + * Query the data + */ public static void queryData() { MagicService service = new MagicServiceImpl(new WizardDaoImpl(), new SpellbookDaoImpl(), new SpellDaoImpl()); diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java index eae9286fa..2665ff858 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java @@ -39,8 +39,9 @@ public abstract class DaoBaseImpl implements Dao { result = (E) criteria.uniqueResult(); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); @@ -57,8 +58,9 @@ public abstract class DaoBaseImpl implements Dao { session.persist(entity); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); @@ -75,8 +77,9 @@ public abstract class DaoBaseImpl implements Dao { result = (E) session.merge(entity); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); @@ -93,8 +96,9 @@ public abstract class DaoBaseImpl implements Dao { session.delete(entity); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); @@ -111,8 +115,9 @@ public abstract class DaoBaseImpl implements Dao { Criteria criteria = session.createCriteria(persistentClass); result = criteria.list(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java index 9d1aec488..fce6fb873 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java @@ -14,11 +14,11 @@ import com.iluwatar.servicelayer.wizard.Wizard; */ public class HibernateUtil { - private static final SessionFactory sessionFactory; + private static final SessionFactory SESSION_FACTORY; static { try { - sessionFactory = + SESSION_FACTORY = new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class) .addAnnotatedClass(Spell.class) .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect") @@ -33,6 +33,6 @@ public class HibernateUtil { } public static SessionFactory getSessionFactory() { - return sessionFactory; + return SESSION_FACTORY; } } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java index f46f55184..cda3fe58d 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java @@ -21,6 +21,9 @@ public class MagicServiceImpl implements MagicService { private SpellbookDao spellbookDao; private SpellDao spellDao; + /** + * Constructor + */ public MagicServiceImpl(WizardDao wizardDao, SpellbookDao spellbookDao, SpellDao spellDao) { this.wizardDao = wizardDao; this.spellbookDao = spellbookDao; diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java index f5f017625..66d06448b 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java @@ -27,8 +27,9 @@ public class SpellDaoImpl extends DaoBaseImpl implements SpellDao { result.getSpellbook().getWizards().size(); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java index 1de82d4a9..842764056 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java @@ -28,8 +28,9 @@ public class SpellbookDaoImpl extends DaoBaseImpl implements Spellboo result.getWizards().size(); tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java index ad89dd28a..9ff36edef 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java @@ -30,8 +30,9 @@ public class WizardDaoImpl extends DaoBaseImpl implements WizardDao { } tx.commit(); } catch (Exception e) { - if (tx != null) + if (tx != null) { tx.rollback(); + } throw e; } finally { session.close(); diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java index f2d338cdc..f2dd31221 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java @@ -12,6 +12,9 @@ public class ServiceImpl implements Service { private final String serviceName; private final int id; + /** + * Constructor + */ public ServiceImpl(String serviceName) { // set the service name this.serviceName = serviceName; diff --git a/singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java b/singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java index 585b11e61..f8b7e170f 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java +++ b/singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java @@ -8,7 +8,7 @@ public final class IvoryTower { /** * Static to class instance of the class. */ - private static final IvoryTower instance = new IvoryTower(); + private static final IvoryTower INSTANCE = new IvoryTower(); /** * Private constructor so nobody can instantiate the class. @@ -21,6 +21,6 @@ public final class IvoryTower { * @return instance of the singleton. */ public static IvoryTower getInstance() { - return instance; + return INSTANCE; } } diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java index 1aca15b30..ab39a652d 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java +++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java @@ -11,14 +11,14 @@ package com.iluwatar.singleton; */ public class ThreadSafeDoubleCheckLocking { - private static volatile ThreadSafeDoubleCheckLocking INSTANCE; + private static volatile ThreadSafeDoubleCheckLocking instance; /** * private constructor to prevent client from instantiating. */ private ThreadSafeDoubleCheckLocking() { // to prevent instantiating by Reflection call - if (INSTANCE != null) { + if (instance != null) { throw new IllegalStateException("Already initialized."); } } @@ -31,12 +31,12 @@ public class ThreadSafeDoubleCheckLocking { public static ThreadSafeDoubleCheckLocking getInstance() { // local variable increases performance by 25 percent // Joshua Bloch "Effective Java, Second Edition", p. 283-284 - ThreadSafeDoubleCheckLocking result = INSTANCE; + ThreadSafeDoubleCheckLocking result = instance; if (result == null) { synchronized (ThreadSafeDoubleCheckLocking.class) { - result = INSTANCE; + result = instance; if (result == null) { - INSTANCE = result = new ThreadSafeDoubleCheckLocking(); + instance = result = new ThreadSafeDoubleCheckLocking(); } } } diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java index 98281b4c8..e67922016 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java +++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java @@ -16,7 +16,7 @@ public class ThreadSafeLazyLoadedIvoryTower { /** * The instance gets created only when it is called for first time. Lazy-loading */ - public synchronized static ThreadSafeLazyLoadedIvoryTower getInstance() { + public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() { if (instance == null) { instance = new ThreadSafeLazyLoadedIvoryTower(); diff --git a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java index 3afc1bf14..24cd7cf4b 100644 --- a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java +++ b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java @@ -1,13 +1,17 @@ package com.iluwatar.singleton; -import org.junit.Test; +import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * This class provides several test case that test singleton construction. @@ -29,7 +33,7 @@ public class LazyLoadedSingletonThreadSafetyTest { } @Test - public void test_MultipleCallsReturnTheSameObjectInSameThread() { + public void testMultipleCallsReturnTheSameObjectInSameThread() { // Create several instances in the same calling thread ThreadSafeLazyLoadedIvoryTower instance1 = ThreadSafeLazyLoadedIvoryTower.getInstance(); ThreadSafeLazyLoadedIvoryTower instance2 = ThreadSafeLazyLoadedIvoryTower.getInstance(); @@ -42,9 +46,10 @@ public class LazyLoadedSingletonThreadSafetyTest { } @Test - public void test_MultipleCallsReturnTheSameObjectInDifferentThreads() + public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws InterruptedException, ExecutionException { - {// create several threads and inside each callable instantiate the singleton class + { + // create several threads and inside each callable instantiate the singleton class ExecutorService executorService = Executors.newSingleThreadExecutor(); List> threadList = new ArrayList<>(); @@ -63,7 +68,8 @@ public class LazyLoadedSingletonThreadSafetyTest { // tidy up the executor executorService.shutdown(); } - {// now check the contents that were added to threadObjects by each thread + { + // now check the contents that were added to threadObjects by each thread assertEquals(NUM_THREADS, threadObjects.size()); assertEquals(threadObjects.get(0), threadObjects.get(1)); assertEquals(threadObjects.get(1), threadObjects.get(2)); diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java index d755d6c2e..373a24f92 100644 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ b/specification/src/main/java/com/iluwatar/specification/app/App.java @@ -31,6 +31,9 @@ import com.iluwatar.specification.selector.MovementSelector; */ public class App { + /** + * Program entry point + */ public static void main(String[] args) { // initialize creatures list List creatures = diff --git a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java index 2ec3ccf55..f02befb73 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java @@ -16,6 +16,9 @@ public abstract class AbstractCreature implements Creature { private Movement movement; private Color color; + /** + * Constructor + */ public AbstractCreature(String name, Size size, Movement movement, Color color) { this.name = name; this.size = size; diff --git a/state/src/main/java/com/iluwatar/state/App.java b/state/src/main/java/com/iluwatar/state/App.java index 2013466e0..63b59ad59 100644 --- a/state/src/main/java/com/iluwatar/state/App.java +++ b/state/src/main/java/com/iluwatar/state/App.java @@ -13,6 +13,9 @@ package com.iluwatar.state; */ public class App { + /** + * Program entry point + */ public static void main(String[] args) { Mammoth mammoth = new Mammoth(); diff --git a/state/src/main/java/com/iluwatar/state/Mammoth.java b/state/src/main/java/com/iluwatar/state/Mammoth.java index 8269ecb3d..92f4d7188 100644 --- a/state/src/main/java/com/iluwatar/state/Mammoth.java +++ b/state/src/main/java/com/iluwatar/state/Mammoth.java @@ -13,6 +13,9 @@ public class Mammoth { state = new PeacefulState(this); } + /** + * Makes time pass for the mammoth + */ public void timePasses() { if (state.getClass().equals(PeacefulState.class)) { changeStateTo(new AngryState(this)); diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java index 3bf7b9a68..a839cd49e 100644 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java +++ b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java @@ -11,7 +11,7 @@ package com.iluwatar.stepbuilder; * methods available, NO build method until is the right time to build the object. * *

- * Implementation
+ * Implementation *