diff --git a/.travis.yml b/.travis.yml index 60693c5cc..deb436cd2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ after_success: - mvn clean test jacoco:report coveralls:report - bash update-ghpages.sh -sudo: false +sudo: false # route the build to the container-based infrastructure for a faster build diff --git a/abstract-factory/index.md b/abstract-factory/README.md similarity index 100% rename from abstract-factory/index.md rename to abstract-factory/README.md diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 32171a5f2..734020720 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT abstract-factory diff --git a/adapter/index.md b/adapter/README.md similarity index 100% rename from adapter/index.md rename to adapter/README.md diff --git a/adapter/pom.xml b/adapter/pom.xml index 3c231d60a..476eb4dce 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT adapter diff --git a/async-method-invocation/index.md b/async-method-invocation/README.md similarity index 100% rename from async-method-invocation/index.md rename to async-method-invocation/README.md diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index d640b890e..292eb136b 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT async-method-invocation diff --git a/bridge/index.md b/bridge/README.md similarity index 100% rename from bridge/index.md rename to bridge/README.md diff --git a/bridge/pom.xml b/bridge/pom.xml index ba474af55..6ac261286 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT bridge diff --git a/builder/index.md b/builder/README.md similarity index 100% rename from builder/index.md rename to builder/README.md diff --git a/builder/pom.xml b/builder/pom.xml index 66f679cc6..7d83f6c28 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT builder diff --git a/business-delegate/index.md b/business-delegate/README.md similarity index 100% rename from business-delegate/index.md rename to business-delegate/README.md diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 920672062..3834b4c8f 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT business-delegate diff --git a/caching/index.md b/caching/README.md similarity index 100% rename from caching/index.md rename to caching/README.md diff --git a/caching/pom.xml b/caching/pom.xml index 1dad83d0e..7b1b22354 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT caching diff --git a/callback/index.md b/callback/README.md similarity index 100% rename from callback/index.md rename to callback/README.md diff --git a/callback/pom.xml b/callback/pom.xml index 55b1abbc5..8615c4653 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT callback diff --git a/chain/index.md b/chain/README.md similarity index 100% rename from chain/index.md rename to chain/README.md diff --git a/chain/pom.xml b/chain/pom.xml index 4a0c5a96a..a1cbffcb2 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT chain diff --git a/command/index.md b/command/README.md similarity index 100% rename from command/index.md rename to command/README.md diff --git a/command/pom.xml b/command/pom.xml index 69c499371..bb5cd78ff 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT command diff --git a/composite/index.md b/composite/README.md similarity index 100% rename from composite/index.md rename to composite/README.md diff --git a/composite/pom.xml b/composite/pom.xml index 551dc1f2d..6513a104e 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT composite diff --git a/dao/index.md b/dao/README.md similarity index 100% rename from dao/index.md rename to dao/README.md diff --git a/dao/etc/dao.png b/dao/etc/dao.png index 9fe34b976..452e72ba1 100644 Binary files a/dao/etc/dao.png and b/dao/etc/dao.png differ diff --git a/dao/etc/dao.ucls b/dao/etc/dao.ucls index bf11f18b3..0706837fc 100644 --- a/dao/etc/dao.ucls +++ b/dao/etc/dao.ucls @@ -1,45 +1,71 @@ - - + + - - + + - - - - - - - - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + diff --git a/dao/pom.xml b/dao/pom.xml index 3b6fc7d1e..26c35abb0 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT dao @@ -44,6 +44,18 @@ log4j log4j + + com.h2database + h2 + + + de.bechte.junit + junit-hierarchicalcontextrunner + + + org.mockito + mockito-core + diff --git a/dao/src/main/java/com/iluwatar/dao/App.java b/dao/src/main/java/com/iluwatar/dao/App.java index 3fa4b34d5..a63289ae9 100644 --- a/dao/src/main/java/com/iluwatar/dao/App.java +++ b/dao/src/main/java/com/iluwatar/dao/App.java @@ -20,49 +20,101 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.dao; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; + +import javax.sql.DataSource; import org.apache.log4j.Logger; +import org.h2.jdbcx.JdbcDataSource; /** - * * Data Access Object (DAO) is an object that provides an abstract interface to some type of * database or other persistence mechanism. By mapping application calls to the persistence layer, * DAO provide some specific data operations without exposing details of the database. This * isolation supports the Single responsibility principle. It separates what data accesses the * application needs, in terms of domain-specific objects and data types (the public interface of * the DAO), from how these needs can be satisfied with a specific DBMS. - *

- * With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without - * directly interacting with the data. The below example demonstrates basic CRUD operations: select, - * add, update, and delete. + * + *

With the DAO pattern, we can use various method calls to retrieve/add/delete/update data + * without directly interacting with the data source. The below example demonstrates basic CRUD + * operations: select, add, update, and delete. + * * */ public class App { - + private static final String DB_URL = "jdbc:h2:~/dao:customerdb"; private static Logger log = Logger.getLogger(App.class); - + /** * Program entry point. * * @param args command line args. + * @throws Exception if any error occurs. */ - public static void main(final String[] args) { - final CustomerDao customerDao = new CustomerDaoImpl(generateSampleCustomers()); - log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); - log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2)); + public static void main(final String[] args) throws Exception { + final CustomerDao inMemoryDao = new InMemoryCustomerDao(); + performOperationsUsing(inMemoryDao); + + final DataSource dataSource = createDataSource(); + createSchema(dataSource); + final CustomerDao dbDao = new DbCustomerDao(dataSource); + performOperationsUsing(dbDao); + deleteSchema(dataSource); + } + + private static void deleteSchema(DataSource dataSource) throws SQLException { + try (Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement()) { + statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL); + } + } + + private static void createSchema(DataSource dataSource) throws SQLException { + try (Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement()) { + statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL); + } + } + + private static DataSource createDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + return dataSource; + } + + private static void performOperationsUsing(final CustomerDao customerDao) throws Exception { + addCustomers(customerDao); + log.info("customerDao.getAllCustomers(): "); + try (Stream customerStream = customerDao.getAll()) { + customerStream.forEach((customer) -> log.info(customer)); + } + log.info("customerDao.getCustomerById(2): " + customerDao.getById(2)); final Customer customer = new Customer(4, "Dan", "Danson"); - customerDao.addCustomer(customer); - log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + customerDao.add(customer); + log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); customer.setFirstName("Daniel"); customer.setLastName("Danielson"); - customerDao.updateCustomer(customer); - log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); - customerDao.deleteCustomer(customer); - log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + customerDao.update(customer); + log.info("customerDao.getAllCustomers(): "); + try (Stream customerStream = customerDao.getAll()) { + customerStream.forEach((cust) -> log.info(cust)); + } + customerDao.delete(customer); + log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); + } + + private static void addCustomers(CustomerDao customerDao) throws Exception { + for (Customer customer : generateSampleCustomers()) { + customerDao.add(customer); + } } /** diff --git a/dao/src/main/java/com/iluwatar/dao/Customer.java b/dao/src/main/java/com/iluwatar/dao/Customer.java index 6d10fb146..d6b512dd6 100644 --- a/dao/src/main/java/com/iluwatar/dao/Customer.java +++ b/dao/src/main/java/com/iluwatar/dao/Customer.java @@ -20,11 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.dao; /** - * - * Customer + * A customer POJO that represents the data that will be read from the data source. * */ public class Customer { @@ -34,7 +34,7 @@ public class Customer { private String lastName; /** - * Constructor + * Creates an instance of customer. */ public Customer(final int id, final String firstName, final String lastName) { this.id = id; @@ -73,12 +73,12 @@ public class Customer { } @Override - public boolean equals(final Object o) { + public boolean equals(final Object that) { boolean isEqual = false; - if (this == o) { + if (this == that) { isEqual = true; - } else if (o != null && getClass() == o.getClass()) { - final Customer customer = (Customer) o; + } else if (that != null && getClass() == that.getClass()) { + final Customer customer = (Customer) that; if (getId() == customer.getId()) { isEqual = true; } diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java b/dao/src/main/java/com/iluwatar/dao/CustomerDao.java index 26b4df47b..059a9e9f7 100644 --- a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java +++ b/dao/src/main/java/com/iluwatar/dao/CustomerDao.java @@ -20,24 +20,62 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.dao; -import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; /** + * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object + * that provides an interface to some type of persistence mechanism. By mapping application calls + * to the persistence layer, DAO provides some specific data operations without exposing details + * of the database. This isolation supports the Single responsibility principle. It separates what + * data accesses the application needs, in terms of domain-specific objects and data types + * (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS, + * database schema, etc. * - * CustomerDao - * + *

Any change in the way data is stored and retrieved will not change the client code as the + * client will be using interface and need not worry about exact source. + * + * @see InMemoryCustomerDao + * @see DbCustomerDao */ public interface CustomerDao { - List getAllCustomers(); + /** + * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based + * on the implementation. The stream must be closed after use. + * @throws Exception if any error occurs. + */ + Stream getAll() throws Exception; + + /** + * @param id unique identifier of the customer. + * @return an optional with customer if a customer with unique identifier id + * exists, empty optional otherwise. + * @throws Exception if any error occurs. + */ + Optional getById(int id) throws Exception; - Customer getCustomerById(int id); + /** + * @param customer the customer to be added. + * @return true if customer is successfully added, false if customer already exists. + * @throws Exception if any error occurs. + */ + boolean add(Customer customer) throws Exception; - void addCustomer(Customer customer); + /** + * @param customer the customer to be updated. + * @return true if customer exists and is successfully updated, false otherwise. + * @throws Exception if any error occurs. + */ + boolean update(Customer customer) throws Exception; - void updateCustomer(Customer customer); - - void deleteCustomer(Customer customer); + /** + * @param customer the customer to be deleted. + * @return true if customer exists and is successfully deleted, false otherwise. + * @throws Exception if any error occurs. + */ + boolean delete(Customer customer) throws Exception; } diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java b/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java deleted file mode 100644 index 25d4149fa..000000000 --- a/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dao; - -import java.util.List; - -/** - * - * The data access object (DAO) is an object that provides an abstract interface to some type of - * database or other persistence mechanism. By mapping application calls to the persistence layer, - * DAO provide some specific data operations without exposing details of the database. This - * isolation supports the Single responsibility principle. It separates what data accesses the - * application needs, in terms of domain-specific objects and data types (the public interface of - * the DAO), from how these needs can be satisfied with a specific DBMS, database schema, etc. - * - */ -public class CustomerDaoImpl implements CustomerDao { - - // Represents the DB structure for our example so we don't have to managed it ourselves - // Note: Normally this would be in the form of an actual database and not part of the Dao Impl. - private List customers; - - public CustomerDaoImpl(final List customers) { - this.customers = customers; - } - - @Override - public List getAllCustomers() { - return customers; - } - - @Override - public Customer getCustomerById(final int id) { - Customer customer = null; - for (final Customer cus : getAllCustomers()) { - if (cus.getId() == id) { - customer = cus; - break; - } - } - return customer; - } - - @Override - public void addCustomer(final Customer customer) { - if (getCustomerById(customer.getId()) == null) { - customers.add(customer); - } - } - - - @Override - public void updateCustomer(final Customer customer) { - if (getAllCustomers().contains(customer)) { - final int index = getAllCustomers().indexOf(customer); - getAllCustomers().set(index, customer); - } - } - - @Override - public void deleteCustomer(final Customer customer) { - getAllCustomers().remove(customer); - } -} diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java b/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java new file mode 100644 index 000000000..05707fa0e --- /dev/null +++ b/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java @@ -0,0 +1,9 @@ +package com.iluwatar.dao; + +public interface CustomerSchemaSql { + + String CREATE_SCHEMA_SQL = "CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), " + + "LNAME VARCHAR(100))"; + + String DELETE_SCHEMA_SQL = "DROP TABLE CUSTOMERS"; +} diff --git a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java new file mode 100644 index 000000000..622b5b1f0 --- /dev/null +++ b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java @@ -0,0 +1,183 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import javax.sql.DataSource; + +/** + * An implementation of {@link CustomerDao} that persists customers in RDBMS. + * + */ +public class DbCustomerDao implements CustomerDao { + + private final DataSource dataSource; + + /** + * Creates an instance of {@link DbCustomerDao} which uses provided dataSource + * to store and retrieve customer information. + * + * @param dataSource a non-null dataSource. + */ + public DbCustomerDao(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * @return a lazily populated stream of customers. Note the stream returned must be closed to + * free all the acquired resources. The stream keeps an open connection to the database till + * it is complete or is closed manually. + */ + @Override + public Stream getAll() throws Exception { + + Connection connection; + try { + connection = getConnection(); + PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); + ResultSet resultSet = statement.executeQuery(); + return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED) { + + @Override + public boolean tryAdvance(Consumer action) { + try { + if (!resultSet.next()) { + return false; + } + action.accept(createCustomer(resultSet)); + return true; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }, false).onClose(() -> mutedClose(connection)); + } catch (SQLException e) { + throw new Exception(e.getMessage(), e); + } + } + + private Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + private void mutedClose(Connection connection) { + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private Customer createCustomer(ResultSet resultSet) throws SQLException { + return new Customer(resultSet.getInt("ID"), + resultSet.getString("FNAME"), + resultSet.getString("LNAME")); + } + + /** + * {@inheritDoc} + */ + @Override + public Optional getById(int id) throws Exception { + try (Connection connection = getConnection(); + PreparedStatement statement = + connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) { + + statement.setInt(1, id); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + return Optional.of(createCustomer(resultSet)); + } else { + return Optional.empty(); + } + } catch (SQLException ex) { + throw new Exception(ex.getMessage(), ex); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean add(Customer customer) throws Exception { + if (getById(customer.getId()).isPresent()) { + return false; + } + + try (Connection connection = getConnection(); + PreparedStatement statement = + connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) { + statement.setInt(1, customer.getId()); + statement.setString(2, customer.getFirstName()); + statement.setString(3, customer.getLastName()); + statement.execute(); + return true; + } catch (SQLException ex) { + throw new Exception(ex.getMessage(), ex); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean update(Customer customer) throws Exception { + try (Connection connection = getConnection(); + PreparedStatement statement = + connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) { + statement.setString(1, customer.getFirstName()); + statement.setString(2, customer.getLastName()); + statement.setInt(3, customer.getId()); + return statement.executeUpdate() > 0; + } catch (SQLException ex) { + throw new Exception(ex.getMessage(), ex); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean delete(Customer customer) throws Exception { + try (Connection connection = getConnection(); + PreparedStatement statement = + connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) { + statement.setInt(1, customer.getId()); + return statement.executeUpdate() > 0; + } catch (SQLException ex) { + throw new Exception(ex.getMessage(), ex); + } + } +} diff --git a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java new file mode 100644 index 000000000..15c63d1de --- /dev/null +++ b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java @@ -0,0 +1,73 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.dao; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory + * and data is lost when the application exits. + *
+ * This implementation is useful as temporary database or for testing. + */ +public class InMemoryCustomerDao implements CustomerDao { + + private Map idToCustomer = new HashMap<>(); + + /** + * An eagerly evaluated stream of customers stored in memory. + */ + @Override + public Stream getAll() { + return idToCustomer.values().stream(); + } + + @Override + public Optional getById(final int id) { + return Optional.ofNullable(idToCustomer.get(id)); + } + + @Override + public boolean add(final Customer customer) { + if (getById(customer.getId()).isPresent()) { + return false; + } + + idToCustomer.put(customer.getId(), customer); + return true; + } + + @Override + public boolean update(final Customer customer) { + return idToCustomer.replace(customer.getId(), customer) != null; + } + + @Override + public boolean delete(final Customer customer) { + return idToCustomer.remove(customer.getId()) != null; + } +} diff --git a/dao/src/test/java/com/iluwatar/dao/AppTest.java b/dao/src/test/java/com/iluwatar/dao/AppTest.java index b4caa54b4..169fc046e 100644 --- a/dao/src/test/java/com/iluwatar/dao/AppTest.java +++ b/dao/src/test/java/com/iluwatar/dao/AppTest.java @@ -20,18 +20,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.dao; import org.junit.Test; -import java.io.IOException; - /** * Tests that DAO example runs without errors. */ public class AppTest { @Test - public void test() throws IOException { + public void test() throws Exception { String[] args = {}; App.main(args); } diff --git a/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java b/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java deleted file mode 100644 index f30740629..000000000 --- a/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * The MIT License - * Copyright (c) 2014 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -public class CustomerDaoImplTest { - - private CustomerDaoImpl impl; - private List customers; - private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger"); - - @Before - public void setUp() { - customers = new ArrayList<>(); - customers.add(CUSTOMER); - impl = new CustomerDaoImpl(customers); - } - - @Test - public void deleteExistingCustomer() { - assertEquals(1, impl.getAllCustomers().size()); - impl.deleteCustomer(CUSTOMER); - assertTrue(impl.getAllCustomers().isEmpty()); - } - - @Test - public void deleteNonExistingCustomer() { - final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); - impl.deleteCustomer(nonExistingCustomer); - assertEquals(1, impl.getAllCustomers().size()); - } - - @Test - public void updateExistingCustomer() { - final String newFirstname = "Bernard"; - final String newLastname = "Montgomery"; - final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname); - impl.updateCustomer(customer); - final Customer cust = impl.getCustomerById(CUSTOMER.getId()); - assertEquals(newFirstname, cust.getFirstName()); - assertEquals(newLastname, cust.getLastName()); - } - - @Test - public void updateNonExistingCustomer() { - final int nonExistingId = getNonExistingCustomerId(); - final String newFirstname = "Douglas"; - final String newLastname = "MacArthur"; - final Customer customer = new Customer(nonExistingId, newFirstname, newLastname); - impl.updateCustomer(customer); - assertNull(impl.getCustomerById(nonExistingId)); - final Customer existingCustomer = impl.getCustomerById(CUSTOMER.getId()); - assertEquals(CUSTOMER.getFirstName(), existingCustomer.getFirstName()); - assertEquals(CUSTOMER.getLastName(), existingCustomer.getLastName()); - } - - @Test - public void addCustomer() { - final Customer newCustomer = new Customer(3, "George", "Patton"); - impl.addCustomer(newCustomer); - assertEquals(2, impl.getAllCustomers().size()); - } - - @Test - public void addAlreadyAddedCustomer() { - final Customer newCustomer = new Customer(3, "George", "Patton"); - impl.addCustomer(newCustomer); - assertEquals(2, impl.getAllCustomers().size()); - impl.addCustomer(newCustomer); - assertEquals(2, impl.getAllCustomers().size()); - } - - @Test - public void getExistinCustomerById() { - assertEquals(CUSTOMER, impl.getCustomerById(CUSTOMER.getId())); - } - - @Test - public void getNonExistinCustomerById() { - final int nonExistingId = getNonExistingCustomerId(); - assertNull(impl.getCustomerById(nonExistingId)); - } - - /** - * An arbitrary number which does not correspond to an active Customer id. - * - * @return an int of a customer id which doesn't exist - */ - private int getNonExistingCustomerId() { - return 999; - } -} diff --git a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java b/dao/src/test/java/com/iluwatar/dao/CustomerTest.java index 600b5ba3f..6a02fd6be 100644 --- a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java +++ b/dao/src/test/java/com/iluwatar/dao/CustomerTest.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.dao; import static org.junit.Assert.assertEquals; diff --git a/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java new file mode 100644 index 000000000..08e61ebe6 --- /dev/null +++ b/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java @@ -0,0 +1,247 @@ +package com.iluwatar.dao; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.stream.Stream; + +import javax.sql.DataSource; + +import org.h2.jdbcx.JdbcDataSource; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mockito; + +import de.bechte.junit.runners.context.HierarchicalContextRunner; + +/** + * Tests {@link DbCustomerDao}. + */ +@RunWith(HierarchicalContextRunner.class) +public class DbCustomerDaoTest { + + private static final String DB_URL = "jdbc:h2:~/dao:customerdb"; + private DbCustomerDao dao; + private Customer existingCustomer = new Customer(1, "Freddy", "Krueger"); + + /** + * Creates customers schema. + * @throws SQLException if there is any error while creating schema. + */ + @Before + public void createSchema() throws SQLException { + try (Connection connection = DriverManager.getConnection(DB_URL); + Statement statement = connection.createStatement()) { + statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL); + } + } + + /** + * Represents the scenario where DB connectivity is present. + */ + public class ConnectionSuccess { + + /** + * Setup for connection success scenario. + * @throws Exception if any error occurs. + */ + @Before + public void setUp() throws Exception { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + dao = new DbCustomerDao(dataSource); + boolean result = dao.add(existingCustomer); + assertTrue(result); + } + + /** + * Represents the scenario when DAO operations are being performed on a non existing customer. + */ + public class NonExistingCustomer { + + @Test + public void addingShouldResultInSuccess() throws Exception { + try (Stream allCustomers = dao.getAll()) { + assumeTrue(allCustomers.count() == 1); + } + + final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); + boolean result = dao.add(nonExistingCustomer); + assertTrue(result); + + assertCustomerCountIs(2); + assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get()); + } + + @Test + public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception { + final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); + boolean result = dao.delete(nonExistingCustomer); + + assertFalse(result); + assertCustomerCountIs(1); + } + + @Test + public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception { + final int nonExistingId = getNonExistingCustomerId(); + final String newFirstname = "Douglas"; + final String newLastname = "MacArthur"; + final Customer customer = new Customer(nonExistingId, newFirstname, newLastname); + boolean result = dao.update(customer); + + assertFalse(result); + assertFalse(dao.getById(nonExistingId).isPresent()); + } + + @Test + public void retrieveShouldReturnNoCustomer() throws Exception { + assertFalse(dao.getById(getNonExistingCustomerId()).isPresent()); + } + } + + /** + * Represents a scenario where DAO operations are being performed on an already existing + * customer. + * + */ + public class ExistingCustomer { + + @Test + public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception { + Customer existingCustomer = new Customer(1, "Freddy", "Krueger"); + + boolean result = dao.add(existingCustomer); + + assertFalse(result); + assertCustomerCountIs(1); + assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get()); + } + + @Test + public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception { + boolean result = dao.delete(existingCustomer); + + assertTrue(result); + assertCustomerCountIs(0); + assertFalse(dao.getById(existingCustomer.getId()).isPresent()); + } + + @Test + public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception { + final String newFirstname = "Bernard"; + final String newLastname = "Montgomery"; + final Customer customer = new Customer(existingCustomer.getId(), newFirstname, newLastname); + boolean result = dao.update(customer); + + assertTrue(result); + + final Customer cust = dao.getById(existingCustomer.getId()).get(); + assertEquals(newFirstname, cust.getFirstName()); + assertEquals(newLastname, cust.getLastName()); + } + } + } + + /** + * Represents a scenario where DB connectivity is not present due to network issue, or + * DB service unavailable. + * + */ + public class ConnectivityIssue { + + private static final String EXCEPTION_CAUSE = "Connection not available"; + @Rule public ExpectedException exception = ExpectedException.none(); + + /** + * setup a connection failure scenario. + * @throws SQLException if any error occurs. + */ + @Before + public void setUp() throws SQLException { + dao = new DbCustomerDao(mockedDatasource()); + exception.expect(Exception.class); + exception.expectMessage(EXCEPTION_CAUSE); + } + + private DataSource mockedDatasource() throws SQLException { + DataSource mockedDataSource = mock(DataSource.class); + Connection mockedConnection = mock(Connection.class); + SQLException exception = new SQLException(EXCEPTION_CAUSE); + doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString()); + doReturn(mockedConnection).when(mockedDataSource).getConnection(); + return mockedDataSource; + } + + @Test + public void addingACustomerFailsWithExceptionAsFeedbackToClient() throws Exception { + dao.add(new Customer(2, "Bernard", "Montgomery")); + } + + @Test + public void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() throws Exception { + dao.delete(existingCustomer); + } + + @Test + public void updatingACustomerFailsWithFeedbackToTheClient() throws Exception { + final String newFirstname = "Bernard"; + final String newLastname = "Montgomery"; + + dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname)); + } + + @Test + public void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() throws Exception { + dao.getById(existingCustomer.getId()); + } + + @Test + public void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() throws Exception { + dao.getAll(); + } + + } + + /** + * Delete customer schema for fresh setup per test. + * @throws SQLException if any error occurs. + */ + @After + public void deleteSchema() throws SQLException { + try (Connection connection = DriverManager.getConnection(DB_URL); + Statement statement = connection.createStatement()) { + statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL); + } + } + + private void assertCustomerCountIs(int count) throws Exception { + try (Stream allCustomers = dao.getAll()) { + assertTrue(allCustomers.count() == count); + } + } + + + /** + * An arbitrary number which does not correspond to an active Customer id. + * + * @return an int of a customer id which doesn't exist + */ + private int getNonExistingCustomerId() { + return 999; + } +} diff --git a/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java new file mode 100644 index 000000000..65a087b9b --- /dev/null +++ b/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java @@ -0,0 +1,164 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.dao; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import de.bechte.junit.runners.context.HierarchicalContextRunner; + +/** + * Tests {@link InMemoryCustomerDao}. + */ +@RunWith(HierarchicalContextRunner.class) +public class InMemoryCustomerDaoTest { + + private InMemoryCustomerDao dao; + private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger"); + + @Before + public void setUp() { + dao = new InMemoryCustomerDao(); + assertTrue(dao.add(CUSTOMER)); + } + + /** + * Represents the scenario when the DAO operations are being performed on a non existent + * customer. + */ + public class NonExistingCustomer { + + @Test + public void addingShouldResultInSuccess() throws Exception { + try (Stream allCustomers = dao.getAll()) { + assumeTrue(allCustomers.count() == 1); + } + + final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); + boolean result = dao.add(nonExistingCustomer); + assertTrue(result); + + assertCustomerCountIs(2); + assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get()); + } + + @Test + public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception { + final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund"); + boolean result = dao.delete(nonExistingCustomer); + + assertFalse(result); + assertCustomerCountIs(1); + } + + @Test + public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception { + final int nonExistingId = getNonExistingCustomerId(); + final String newFirstname = "Douglas"; + final String newLastname = "MacArthur"; + final Customer customer = new Customer(nonExistingId, newFirstname, newLastname); + boolean result = dao.update(customer); + + assertFalse(result); + assertFalse(dao.getById(nonExistingId).isPresent()); + } + + @Test + public void retrieveShouldReturnNoCustomer() throws Exception { + assertFalse(dao.getById(getNonExistingCustomerId()).isPresent()); + } + } + + /** + * Represents the scenario when the DAO operations are being performed on an already existing + * customer. + */ + public class ExistingCustomer { + + @Test + public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception { + boolean result = dao.add(CUSTOMER); + + assertFalse(result); + assertCustomerCountIs(1); + assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get()); + } + + @Test + public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception { + boolean result = dao.delete(CUSTOMER); + + assertTrue(result); + assertCustomerCountIs(0); + assertFalse(dao.getById(CUSTOMER.getId()).isPresent()); + } + + @Test + public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception { + final String newFirstname = "Bernard"; + final String newLastname = "Montgomery"; + final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname); + boolean result = dao.update(customer); + + assertTrue(result); + + final Customer cust = dao.getById(CUSTOMER.getId()).get(); + assertEquals(newFirstname, cust.getFirstName()); + assertEquals(newLastname, cust.getLastName()); + } + + @Test + public void retriveShouldReturnTheCustomer() { + Optional optionalCustomer = dao.getById(CUSTOMER.getId()); + + assertTrue(optionalCustomer.isPresent()); + assertEquals(CUSTOMER, optionalCustomer.get()); + } + } + + /** + * An arbitrary number which does not correspond to an active Customer id. + * + * @return an int of a customer id which doesn't exist + */ + private int getNonExistingCustomerId() { + return 999; + } + + private void assertCustomerCountIs(int count) throws Exception { + try (Stream allCustomers = dao.getAll()) { + assertTrue(allCustomers.count() == count); + } + } +} diff --git a/decorator/index.md b/decorator/README.md similarity index 100% rename from decorator/index.md rename to decorator/README.md diff --git a/decorator/pom.xml b/decorator/pom.xml index d8f253bd2..58f2bb0ba 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT decorator diff --git a/decorator/src/main/java/com/iluwatar/decorator/Troll.java b/decorator/src/main/java/com/iluwatar/decorator/Troll.java index 7992d708d..628adda4b 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/Troll.java +++ b/decorator/src/main/java/com/iluwatar/decorator/Troll.java @@ -29,6 +29,7 @@ package com.iluwatar.decorator; */ public class Troll implements Hostile { + @Override public void attack() { System.out.println("The troll swings at you with a club!"); } @@ -38,6 +39,7 @@ public class Troll implements Hostile { return 10; } + @Override public void fleeBattle() { System.out.println("The troll shrieks in horror and runs away!"); } diff --git a/delegation/index.md b/delegation/README.md similarity index 100% rename from delegation/index.md rename to delegation/README.md diff --git a/delegation/pom.xml b/delegation/pom.xml index 1cfb3e4e3..33592dd82 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT 4.0.0 diff --git a/dependency-injection/index.md b/dependency-injection/README.md similarity index 100% rename from dependency-injection/index.md rename to dependency-injection/README.md diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index cb210ca5a..d8be9fcff 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT dependency-injection diff --git a/double-checked-locking/index.md b/double-checked-locking/README.md similarity index 100% rename from double-checked-locking/index.md rename to double-checked-locking/README.md diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index e3b4c5bff..f8ac5fa2e 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/index.md b/double-dispatch/README.md similarity index 100% rename from double-dispatch/index.md rename to double-dispatch/README.md diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 8414a6aa1..8896abd9f 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT double-dispatch diff --git a/event-aggregator/index.md b/event-aggregator/README.md similarity index 100% rename from event-aggregator/index.md rename to event-aggregator/README.md diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index 6627bdb1a..1b1f289b2 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT event-aggregator diff --git a/event-driven-architecture/index.md b/event-driven-architecture/README.md similarity index 100% rename from event-driven-architecture/index.md rename to event-driven-architecture/README.md diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index b0b588c6b..cccf39088 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT event-driven-architecture diff --git a/execute-around/index.md b/execute-around/README.md similarity index 100% rename from execute-around/index.md rename to execute-around/README.md diff --git a/execute-around/pom.xml b/execute-around/pom.xml index a8654ac77..23a0a4a15 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT execute-around diff --git a/facade/index.md b/facade/README.md similarity index 100% rename from facade/index.md rename to facade/README.md diff --git a/facade/pom.xml b/facade/pom.xml index daa3853cd..a526243a1 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT facade diff --git a/factory-kit/index.md b/factory-kit/README.md similarity index 100% rename from factory-kit/index.md rename to factory-kit/README.md diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml index c336c5f49..ea2aa5976 100644 --- a/factory-kit/pom.xml +++ b/factory-kit/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT factory-kit diff --git a/factory-method/index.md b/factory-method/README.md similarity index 100% rename from factory-method/index.md rename to factory-method/README.md diff --git a/factory-method/pom.xml b/factory-method/pom.xml index 25ca9f726..7e1cfd28f 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT factory-method diff --git a/feature-toggle/index.md b/feature-toggle/README.md similarity index 100% rename from feature-toggle/index.md rename to feature-toggle/README.md diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml index 5f732f5a3..cf479dd0a 100644 --- a/feature-toggle/pom.xml +++ b/feature-toggle/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT 4.0.0 diff --git a/fluentinterface/index.md b/fluentinterface/README.md similarity index 100% rename from fluentinterface/index.md rename to fluentinterface/README.md diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 5faf359d1..2e4129b2d 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT 4.0.0 diff --git a/flux/index.md b/flux/README.md similarity index 100% rename from flux/index.md rename to flux/README.md diff --git a/flux/pom.xml b/flux/pom.xml index 25182d784..bd454ca23 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT flux diff --git a/flyweight/index.md b/flyweight/README.md similarity index 100% rename from flyweight/index.md rename to flyweight/README.md diff --git a/flyweight/pom.xml b/flyweight/pom.xml index a066c8924..a4221d762 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT flyweight diff --git a/front-controller/index.md b/front-controller/README.md similarity index 100% rename from front-controller/index.md rename to front-controller/README.md diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 8cb7ddc6d..c8f136ca8 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT front-controller diff --git a/half-sync-half-async/index.md b/half-sync-half-async/README.md similarity index 100% rename from half-sync-half-async/index.md rename to half-sync-half-async/README.md diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 357cabf4b..5b6ce56b1 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT half-sync-half-async diff --git a/intercepting-filter/index.md b/intercepting-filter/README.md similarity index 100% rename from intercepting-filter/index.md rename to intercepting-filter/README.md diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 0ff3be16b..6ef1e25bc 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT intercepting-filter diff --git a/interpreter/index.md b/interpreter/README.md similarity index 100% rename from interpreter/index.md rename to interpreter/README.md diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 3a09ae310..a0003672a 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT interpreter diff --git a/iterator/index.md b/iterator/README.md similarity index 100% rename from iterator/index.md rename to iterator/README.md diff --git a/iterator/pom.xml b/iterator/pom.xml index 2aeea6100..dcd70f809 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT iterator diff --git a/layers/index.md b/layers/README.md similarity index 100% rename from layers/index.md rename to layers/README.md diff --git a/layers/pom.xml b/layers/pom.xml index c6e68150b..abd888afa 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/index.md b/lazy-loading/README.md similarity index 100% rename from lazy-loading/index.md rename to lazy-loading/README.md diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index 0ca7272a0..37b321aec 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT lazy-loading diff --git a/mediator/index.md b/mediator/README.md similarity index 100% rename from mediator/index.md rename to mediator/README.md diff --git a/mediator/pom.xml b/mediator/pom.xml index 8e24da4b9..7f3209479 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT mediator diff --git a/memento/index.md b/memento/README.md similarity index 100% rename from memento/index.md rename to memento/README.md diff --git a/memento/pom.xml b/memento/pom.xml index fc78cb65b..b7355784c 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT memento diff --git a/message-channel/index.md b/message-channel/README.md similarity index 100% rename from message-channel/index.md rename to message-channel/README.md diff --git a/message-channel/pom.xml b/message-channel/pom.xml index a6f626a11..3afc5b32e 100644 --- a/message-channel/pom.xml +++ b/message-channel/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT message-channel diff --git a/model-view-controller/index.md b/model-view-controller/README.md similarity index 100% rename from model-view-controller/index.md rename to model-view-controller/README.md diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 4e8697171..0ae6a6fc6 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/index.md b/model-view-presenter/README.md similarity index 100% rename from model-view-presenter/index.md rename to model-view-presenter/README.md diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index c4f1c82dd..e0a3c57fb 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT model-view-presenter model-view-presenter diff --git a/monad/index.md b/monad/README.md similarity index 97% rename from monad/index.md rename to monad/README.md index 82deba922..ffc67a354 100644 --- a/monad/index.md +++ b/monad/README.md @@ -1,35 +1,35 @@ ---- -layout: pattern -title: Monad -folder: monad -permalink: /patterns/monad/ -categories: Other -tags: - - Java - - Difficulty-Advanced - - Functional ---- - -## Intent - -Monad pattern based on monad from linear algebra represents the way of chaining operations -together step by step. Binding functions can be described as passing one's output to another's input -basing on the 'same type' contract. Formally, monad consists of a type constructor M and two -operations: -bind - that takes monadic object and a function from plain object to monadic value and returns monadic value -return - that takes plain type object and returns this object wrapped in a monadic value. - -![alt text](./etc/monad.png "Monad") - -## Applicability - -Use the Monad in any of the following situations - -* when you want to chain operations easily -* when you want to apply each function regardless of the result of any of them - -## Credits - -* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU) -* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads) +--- +layout: pattern +title: Monad +folder: monad +permalink: /patterns/monad/ +categories: Other +tags: + - Java + - Difficulty-Advanced + - Functional +--- + +## Intent + +Monad pattern based on monad from linear algebra represents the way of chaining operations +together step by step. Binding functions can be described as passing one's output to another's input +basing on the 'same type' contract. Formally, monad consists of a type constructor M and two +operations: +bind - that takes monadic object and a function from plain object to monadic value and returns monadic value +return - that takes plain type object and returns this object wrapped in a monadic value. + +![alt text](./etc/monad.png "Monad") + +## Applicability + +Use the Monad in any of the following situations + +* when you want to chain operations easily +* when you want to apply each function regardless of the result of any of them + +## Credits + +* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU) +* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads) * [Monad on Wikipedia](https://en.wikipedia.org/wiki/Monad_(functional_programming)) \ No newline at end of file diff --git a/monad/pom.xml b/monad/pom.xml index ec5a14a8c..b737e2174 100644 --- a/monad/pom.xml +++ b/monad/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT monad diff --git a/monostate/index.md b/monostate/README.md similarity index 100% rename from monostate/index.md rename to monostate/README.md diff --git a/monostate/pom.xml b/monostate/pom.xml index bb6119253..bb246d38c 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT monostate diff --git a/multiton/index.md b/multiton/README.md similarity index 94% rename from multiton/index.md rename to multiton/README.md index 68fb6bbc6..0462ff0ec 100644 --- a/multiton/index.md +++ b/multiton/README.md @@ -9,6 +9,9 @@ tags: - Difficulty-Beginner --- +## Also known as +Registry + ## Intent Ensure a class only has limited number of instances, and provide a global point of access to them. diff --git a/multiton/pom.xml b/multiton/pom.xml index 6b07c638d..2482c056b 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT multiton diff --git a/mute-idiom/README.md b/mute-idiom/README.md new file mode 100644 index 000000000..efc09f306 --- /dev/null +++ b/mute-idiom/README.md @@ -0,0 +1,28 @@ +--- +layout: pattern +title: Mute Idiom +folder: mute-idiom +permalink: /patterns/mute-idiom/ +categories: Other +tags: + - Java + - Difficulty-Beginner + - Idiom +--- + +## Intent +Provide a template to supress any exceptions that either are declared but cannot occur or should only be logged; +while executing some business logic. The template removes the need to write repeated `try-catch` blocks. + + +![alt text](./etc/mute-idiom.png "Mute Idiom") + +## Applicability +Use this idiom when + +* an API declares some exception but can never throw that exception. Eg. ByteArrayOutputStream bulk write method. +* you need to suppress some exception just by logging it, such as closing a resource. + +## Credits + +* [JOOQ: Mute Design Pattern](http://blog.jooq.org/2016/02/18/the-mute-design-pattern/) diff --git a/mute-idiom/etc/mute-idiom.png b/mute-idiom/etc/mute-idiom.png new file mode 100644 index 000000000..203bdafc4 Binary files /dev/null and b/mute-idiom/etc/mute-idiom.png differ diff --git a/mute-idiom/etc/mute-idiom.ucls b/mute-idiom/etc/mute-idiom.ucls new file mode 100644 index 000000000..7b4d2f916 --- /dev/null +++ b/mute-idiom/etc/mute-idiom.ucls @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml new file mode 100644 index 000000000..3bfc3bf8a --- /dev/null +++ b/mute-idiom/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.12.0-SNAPSHOT + + mute-idiom + + + junit + junit + test + + + diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java new file mode 100644 index 000000000..8a2aca41e --- /dev/null +++ b/mute-idiom/src/main/java/com/iluwatar/mute/App.java @@ -0,0 +1,103 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.mute; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.sql.SQLException; + +/** + * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in + * situation when all we can do to handle the exception is to log it. + * This pattern should not be used everywhere. It is very important to logically handle the + * exceptions in a system, but some situations like the ones described above require this pattern, + * so that we don't need to repeat + *

+ * 
+ *   try {
+ *     // code that may throwing exception we need to ignore or may never be thrown
+ *   } catch (Exception ex) {
+ *     // ignore by logging or throw error if unexpected exception occurs
+ *   }
+ * 
+ * 
every time we need to ignore an exception. + * + */ +public class App { + + /** + * Program entry point. + * + * @param args command line args. + * @throws Exception if any exception occurs + */ + public static void main(String[] args) throws Exception { + + useOfLoggedMute(); + + useOfMute(); + } + + /* + * Typically used when the API declares some exception but cannot do so. Usually a + * signature mistake.In this example out is not supposed to throw exception as it is a + * ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected + * exception occurs. + */ + private static void useOfMute() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Mute.mute(() -> out.write("Hello".getBytes())); + } + + private static void useOfLoggedMute() throws SQLException { + Resource resource = null; + try { + resource = acquireResource(); + utilizeResource(resource); + } finally { + closeResource(resource); + } + } + + /* + * All we can do while failed close of a resource is to log it. + */ + private static void closeResource(Resource resource) { + Mute.loggedMute(() -> resource.close()); + } + + private static void utilizeResource(Resource resource) throws SQLException { + System.out.println("Utilizing acquired resource: " + resource); + } + + private static Resource acquireResource() throws SQLException { + return new Resource() { + + @Override + public void close() throws IOException { + throw new IOException("Error in closing resource: " + this); + } + }; + } +} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java new file mode 100644 index 000000000..d1440636f --- /dev/null +++ b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.mute; + +/** + * A runnable which may throw exception on execution. + * + */ +@FunctionalInterface +public interface CheckedRunnable { + /** + * Same as {@link Runnable#run()} with a possibility of exception in execution. + * @throws Exception if any exception occurs. + */ + void run() throws Exception; +} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java new file mode 100644 index 000000000..64169a8f5 --- /dev/null +++ b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java @@ -0,0 +1,68 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.mute; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * A utility class that allows you to utilize mute idiom. + */ +public final class Mute { + + // The constructor is never meant to be called. + private Mute() {} + + /** + * Executes the runnable and throws the exception occurred within a {@link AssertionError}. + * This method should be utilized to mute the operations that are guaranteed not to throw an exception. + * For instance {@link ByteArrayOutputStream#write(byte[])} declares in it's signature that it can throw + * an {@link IOException}, but in reality it cannot. This is because the bulk write method is not overridden + * in {@link ByteArrayOutputStream}. + * + * @param runnable a runnable that should never throw an exception on execution. + */ + public static void mute(CheckedRunnable runnable) { + try { + runnable.run(); + } catch (Exception e) { + throw new AssertionError(e); + } + } + + /** + * Executes the runnable and logs the exception occurred on {@link System#err}. + * This method should be utilized to mute the operations about which most you can do is log. + * For instance while closing a connection to database, or cleaning up a resource, + * all you can do is log the exception occurred. + * + * @param runnable a runnable that may throw an exception on execution. + */ + public static void loggedMute(CheckedRunnable runnable) { + try { + runnable.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java new file mode 100644 index 000000000..6970d06bc --- /dev/null +++ b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java @@ -0,0 +1,35 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.mute; + +import java.io.Closeable; + +/** + * Represents any resource that the application might acquire and that must be closed + * after it is utilized. Example of such resources can be a database connection, open + * files, sockets. + */ +public interface Resource extends Closeable { + +} diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java new file mode 100644 index 000000000..8075d9c85 --- /dev/null +++ b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java @@ -0,0 +1,38 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.mute; + +import org.junit.Test; + +/** + * Tests that Mute idiom example runs without errors. + * + */ +public class AppTest { + + @Test + public void test() throws Exception { + App.main(null); + } +} diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java new file mode 100644 index 000000000..58cbfe893 --- /dev/null +++ b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java @@ -0,0 +1,78 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.mute; + +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class MuteTest { + + private static final String MESSAGE = "should not occur"; + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Test + public void muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { + Mute.mute(() -> methodNotThrowingAnyException()); + } + + @Test + public void muteShouldRethrowUnexpectedExceptionAsAssertionError() throws Exception { + exception.expect(AssertionError.class); + exception.expectMessage(MESSAGE); + + Mute.mute(() -> methodThrowingException()); + } + + @Test + public void loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { + Mute.loggedMute(() -> methodNotThrowingAnyException()); + } + + @Test + public void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + System.setErr(new PrintStream(stream)); + + Mute.loggedMute(() -> methodThrowingException()); + + assertTrue(new String(stream.toByteArray()).contains(MESSAGE)); + } + + + private void methodNotThrowingAnyException() { + System.out.println("Executed successfully"); + } + + private void methodThrowingException() throws Exception { + throw new Exception(MESSAGE); + } +} diff --git a/naked-objects/index.md b/naked-objects/README.md similarity index 100% rename from naked-objects/index.md rename to naked-objects/README.md diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 102c7178e..be96b2456 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 6f476bc9b..6bbaaaeb1 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index 6dbfc9946..68cac3790 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index 451944aa5..d34dba9a3 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT naked-objects @@ -350,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT
diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index c8b483513..aa7d60438 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT naked-objects-webapp diff --git a/null-object/index.md b/null-object/README.md similarity index 100% rename from null-object/index.md rename to null-object/README.md diff --git a/null-object/pom.xml b/null-object/pom.xml index e8b1d2465..b765c6537 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT null-object diff --git a/object-pool/index.md b/object-pool/README.md similarity index 100% rename from object-pool/index.md rename to object-pool/README.md diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 5a2e4b8b6..6022ef8a7 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT object-pool diff --git a/observer/index.md b/observer/README.md similarity index 100% rename from observer/index.md rename to observer/README.md diff --git a/observer/pom.xml b/observer/pom.xml index c8cca3edc..fcc3e88aa 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT observer diff --git a/poison-pill/index.md b/poison-pill/README.md similarity index 100% rename from poison-pill/index.md rename to poison-pill/README.md diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 0cc3bd6e8..b76578122 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index 6339fb72b..ef443a2d5 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT pom 2014 @@ -48,6 +48,7 @@ 19.0 1.15.1 1.10.19 + 4.12.1 abstract-factory @@ -121,7 +122,7 @@ feature-toggle value-object monad - hexagonal + mute-idiom @@ -194,6 +195,12 @@ ${systemrules.version} test + + de.bechte.junit + junit-hierarchicalcontextrunner + ${hierarchical-junit-runner-version} + test + diff --git a/private-class-data/index.md b/private-class-data/README.md similarity index 100% rename from private-class-data/index.md rename to private-class-data/README.md diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index 97d623b46..877197664 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT private-class-data diff --git a/producer-consumer/index.md b/producer-consumer/README.md similarity index 100% rename from producer-consumer/index.md rename to producer-consumer/README.md diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 5c00b85f9..c4ea8f1df 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT producer-consumer diff --git a/property/index.md b/property/README.md similarity index 100% rename from property/index.md rename to property/README.md diff --git a/property/pom.xml b/property/pom.xml index a5cd459df..c753261d1 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT property diff --git a/prototype/index.md b/prototype/README.md similarity index 100% rename from prototype/index.md rename to prototype/README.md diff --git a/prototype/pom.xml b/prototype/pom.xml index da1aa0fd2..7fb43402f 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT prototype diff --git a/proxy/index.md b/proxy/README.md similarity index 100% rename from proxy/index.md rename to proxy/README.md diff --git a/proxy/pom.xml b/proxy/pom.xml index 4640a1bba..9936be34b 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT proxy diff --git a/publish-subscribe/index.md b/publish-subscribe/README.md similarity index 100% rename from publish-subscribe/index.md rename to publish-subscribe/README.md diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index bfa4838e7..1ff97ca47 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT publish-subscribe diff --git a/reactor/index.md b/reactor/README.md similarity index 100% rename from reactor/index.md rename to reactor/README.md diff --git a/reactor/pom.xml b/reactor/pom.xml index 9e228ce6e..80a15f9d3 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT reactor diff --git a/reader-writer-lock/index.md b/reader-writer-lock/README.md similarity index 100% rename from reader-writer-lock/index.md rename to reader-writer-lock/README.md diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index dbfafff66..0391ea291 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT reader-writer-lock diff --git a/repository/index.md b/repository/README.md similarity index 100% rename from repository/index.md rename to repository/README.md diff --git a/repository/pom.xml b/repository/pom.xml index 82e4b4d67..b8b81ee05 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT repository diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java index df24e1424..2807ae7ca 100644 --- a/repository/src/main/java/com/iluwatar/repository/App.java +++ b/repository/src/main/java/com/iluwatar/repository/App.java @@ -100,6 +100,8 @@ public class App { System.out.println(person); } + repository.deleteAll(); + context.close(); } diff --git a/repository/src/main/resources/applicationContext.xml b/repository/src/main/resources/applicationContext.xml index a3b5162da..8b4b81bb7 100644 --- a/repository/src/main/resources/applicationContext.xml +++ b/repository/src/main/resources/applicationContext.xml @@ -54,7 +54,8 @@ - + + diff --git a/resource-acquisition-is-initialization/index.md b/resource-acquisition-is-initialization/README.md similarity index 100% rename from resource-acquisition-is-initialization/index.md rename to resource-acquisition-is-initialization/README.md diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index e79ec99ee..63971d97c 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/servant/index.md b/servant/README.md similarity index 100% rename from servant/index.md rename to servant/README.md diff --git a/servant/pom.xml b/servant/pom.xml index 0161e71f6..a102ad348 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT servant diff --git a/service-layer/index.md b/service-layer/README.md similarity index 100% rename from service-layer/index.md rename to service-layer/README.md diff --git a/service-layer/pom.xml b/service-layer/pom.xml index ff88256a9..c5e4eb8d9 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT service-layer diff --git a/service-locator/index.md b/service-locator/README.md similarity index 100% rename from service-locator/index.md rename to service-locator/README.md diff --git a/service-locator/pom.xml b/service-locator/pom.xml index 4a64e8615..f07dc93f8 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT service-locator diff --git a/singleton/index.md b/singleton/README.md similarity index 100% rename from singleton/index.md rename to singleton/README.md diff --git a/singleton/pom.xml b/singleton/pom.xml index 66c02e664..8ab7e0686 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT singleton diff --git a/specification/index.md b/specification/README.md similarity index 100% rename from specification/index.md rename to specification/README.md diff --git a/specification/pom.xml b/specification/pom.xml index 125c34e0b..c54688919 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT specification diff --git a/state/index.md b/state/README.md similarity index 100% rename from state/index.md rename to state/README.md diff --git a/state/pom.xml b/state/pom.xml index 08b4846e6..2411eb2a7 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT state diff --git a/step-builder/index.md b/step-builder/README.md similarity index 100% rename from step-builder/index.md rename to step-builder/README.md diff --git a/step-builder/pom.xml b/step-builder/pom.xml index dde7443f9..8d926d118 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT step-builder diff --git a/strategy/index.md b/strategy/README.md similarity index 100% rename from strategy/index.md rename to strategy/README.md diff --git a/strategy/pom.xml b/strategy/pom.xml index 0b6b2dc4e..934ff8775 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT strategy diff --git a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java index d5b752c52..d17ff9041 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java +++ b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java @@ -31,6 +31,6 @@ public class MeleeStrategy implements DragonSlayingStrategy { @Override public void execute() { - System.out.println("With your Excalibur you severe the dragon's head!"); + System.out.println("With your Excalibur you sever the dragon's head!"); } } diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java index 341db8caf..35f4c1a82 100644 --- a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java +++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java @@ -52,7 +52,7 @@ public class DragonSlayingStrategyTest { return Arrays.asList( new Object[]{ new MeleeStrategy(), - "With your Excalibur you severe the dragon's head!" + "With your Excalibur you sever the dragon's head!" }, new Object[]{ new ProjectileStrategy(), diff --git a/template-method/index.md b/template-method/README.md similarity index 100% rename from template-method/index.md rename to template-method/README.md diff --git a/template-method/pom.xml b/template-method/pom.xml index 0feb89c02..af0b19cb4 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT template-method diff --git a/thread-pool/index.md b/thread-pool/README.md similarity index 100% rename from thread-pool/index.md rename to thread-pool/README.md diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index a2e683359..824dcd7af 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT thread-pool diff --git a/tolerant-reader/index.md b/tolerant-reader/README.md similarity index 100% rename from tolerant-reader/index.md rename to tolerant-reader/README.md diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index 6c8c96b3c..249788da0 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT tolerant-reader diff --git a/twin/index.md b/twin/README.md similarity index 100% rename from twin/index.md rename to twin/README.md diff --git a/twin/pom.xml b/twin/pom.xml index dc23b26ef..010bf37b2 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT twin diff --git a/value-object/index.md b/value-object/README.md similarity index 100% rename from value-object/index.md rename to value-object/README.md diff --git a/value-object/pom.xml b/value-object/pom.xml index 3cbb7bb86..66b2342eb 100644 --- a/value-object/pom.xml +++ b/value-object/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT value-object diff --git a/visitor/index.md b/visitor/README.md similarity index 100% rename from visitor/index.md rename to visitor/README.md diff --git a/visitor/pom.xml b/visitor/pom.xml index cdffb0151..1b594b179 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT visitor