diff --git a/.travis.yml b/.travis.yml index af275508b..a59370c30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,18 @@ language: java jdk: - oraclejdk8 +env: + global: + - GH_REF: github.com/iluwatar/java-design-patterns.git + - secure: "LxTDuNS/rBWIvKkaEqr79ImZAe48mCdoYCF41coxNXgNoippo4GIBArknqtv+XvdkiuRZ1yGyj6pn8GU33c/yn+krddTUkVCwTbVatbalW5jhQjDbHYym/JcxaK9ZS/3JTeGcWrBgiPqHEEDhCf26vPZsXoMSeVCEORVKTp1BSg=" + before_install: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" after_success: - mvn clean test jacoco:report coveralls:report + - bash update-ghpages.sh # Migration to container-based infrastructure sudo: false diff --git a/README.md b/README.md index 4715c3b9b..77282f569 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,12 @@ # Design pattern samples in Java +[![Build status](https://travis-ci.org/iluwatar/java-design-patterns.svg?branch=master)](https://travis-ci.org/iluwatar/java-design-patterns) +[![Coverage Status](https://coveralls.io/repos/iluwatar/java-design-patterns/badge.svg?branch=master)](https://coveralls.io/r/iluwatar/java-design-patterns?branch=master) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/5634/badge.svg)](https://scan.coverity.com/projects/5634) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build status](https://travis-ci.org/iluwatar/java-design-patterns.svg?branch=master)](https://travis-ci.org/iluwatar/java-design-patterns) [![Coverage Status](https://coveralls.io/repos/iluwatar/java-design-patterns/badge.svg?branch=master)](https://coveralls.io/r/iluwatar/java-design-patterns?branch=master) - Coverity Scan Build Status - - - - - -# Table of Contents - - Introduction - - How to contribute - - Frequently Asked Questions - - Credits - - License - - -# Introduction [↑](#top) +# Introduction Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system. @@ -34,72 +21,22 @@ Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns. +# Getting started -# How to contribute [↑](#top) +Before you dive into the material, you should be familiar with various +[Programming/Software Design Principles](http://webpro.github.io/programming-principles/). + +Once you are familiar with these concepts you can start drilling down into patterns by any of the following approaches + + - Using difficulty tags, `Difficulty-Beginner`, `Difficulty-Intermediate` & `Difficulty-Expert`. + - Using pattern categories, `Creational`, `Behavioral` and others. + - Search for a specific pattern. Can't find one? Please report a new pattern [here](https://github.com/iluwatar/java-design-patterns/issues). + +# How to contribute If you are willing to contribute to the project you will find the relevant information in our [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). - -# Frequently asked questions [↑](#top) - -**Q: What is the difference between State and Strategy patterns?** - -While the implementation is similar they solve different problems. The State -pattern deals with what state an object is in - it encapsulates state-dependent -behavior. -The Strategy pattern deals with how an object performs a certain task - it -encapsulates an algorithm. - -**Q: What is the difference between Strategy and Template Method patterns?** - -In Template Method the algorithm is chosen at compile time via inheritance. -With Strategy pattern the algorithm is chosen at runtime via composition. - -**Q: What is the difference between Proxy and Decorator patterns?** - -The difference is the intent of the patterns. While Proxy controls access to -the object Decorator is used to add responsibilities to the object. - -**Q: What is the difference between Chain of Responsibility and Intercepting Filter patterns?** - -While the implementations look similar there are differences. The Chain of -Responsibility forms a chain of request processors and the processors are then -executed one by one until the correct processor is found. In Intercepting -Filter the chain is constructed from filters and the whole chain is always -executed. - -**Q: What is the difference between Visitor and Double Dispatch patterns?** - -The Visitor pattern is a means of adding a new operation to existing classes. -Double dispatch is a means of dispatching function calls with respect to two -polymorphic types, rather than a single polymorphic type, which is what -languages like C++ and Java _do not_ support directly. - -**Q: What are the differences between Flyweight and Object Pool patterns?** - -They differ in the way they are used. - -Pooled objects can simultaneously be used by a single "client" only. For that, -a pooled object must be checked out from the pool, then it can be used by a -client, and then the client must return the object back to the pool. Multiple -instances of identical objects may exist, up to the maximal capacity of the -pool. - -In contrast, a Flyweight object is singleton, and it can be used simultaneously -by multiple clients. - -As for concurrent access, pooled objects can be mutable and they usually don't -need to be thread safe, as typically, only one thread is going to use a -specific instance at the same time. Flyweight must either be immutable (the -best option), or implement thread safety. - -As for performance and scalability, pools can become bottlenecks, if all the -pooled objects are in use and more clients need them, threads will become -blocked waiting for available object from the pool. This is not the case with -Flyweight. - - -# Credits [↑](#top) +# Credits * [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) * [Effective Java (2nd Edition)](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683) @@ -113,7 +50,6 @@ Flyweight. * [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2) * [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697) - -# License [↑](#top) +# License This project is licensed under the terms of the MIT license. diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 000000000..0ff943d95 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/factory-method/index.md b/factory-method/index.md index fa30a4349..8011e42c8 100644 --- a/factory-method/index.md +++ b/factory-method/index.md @@ -4,7 +4,9 @@ title: Factory Method folder: factory-method permalink: /patterns/factory-method/ categories: Creational -tags: Java +tags: + - Java + - Difficulty-Beginner --- **Intent:** Define an interface for creating an object, but let subclasses diff --git a/faq.md b/faq.md new file mode 100644 index 000000000..b98bc7589 --- /dev/null +++ b/faq.md @@ -0,0 +1,67 @@ +--- +layout: page +title: FAQ +permalink: /faq/ +icon: fa-question +page-index: 2 +--- + +### Q1: What is the difference between State and Strategy patterns? {#Q1} + +While the implementation is similar they solve different problems. The State +pattern deals with what state an object is in - it encapsulates state-dependent +behavior. +The Strategy pattern deals with how an object performs a certain task - it +encapsulates an algorithm. + +### Q2: What is the difference between Strategy and Template Method patterns? {#Q2} + +In Template Method the algorithm is chosen at compile time via inheritance. +With Strategy pattern the algorithm is chosen at runtime via composition. + +### Q3: What is the difference between Proxy and Decorator patterns? {#Q3} + +The difference is the intent of the patterns. While Proxy controls access to +the object Decorator is used to add responsibilities to the object. + +### Q4: What is the difference between Chain of Responsibility and Intercepting Filter patterns? {#Q4} + +While the implementations look similar there are differences. The Chain of +Responsibility forms a chain of request processors and the processors are then +executed one by one until the correct processor is found. In Intercepting +Filter the chain is constructed from filters and the whole chain is always +executed. + +### Q5: What is the difference between Visitor and Double Dispatch patterns? {#Q5} + +The Visitor pattern is a means of adding a new operation to existing classes. +Double dispatch is a means of dispatching function calls with respect to two +polymorphic types, rather than a single polymorphic type, which is what +languages like C++ and Java _do not_ support directly. + +### Q6: What are the differences between Flyweight and Object Pool patterns? {#Q6} + +They differ in the way they are used. + +Pooled objects can simultaneously be used by a single "client" only. For that, +a pooled object must be checked out from the pool, then it can be used by a +client, and then the client must return the object back to the pool. Multiple +instances of identical objects may exist, up to the maximal capacity of the +pool. + +In contrast, a Flyweight object is singleton, and it can be used simultaneously +by multiple clients. + +As for concurrent access, pooled objects can be mutable and they usually don't +need to be thread safe, as typically, only one thread is going to use a +specific instance at the same time. Flyweight must either be immutable (the +best option), or implement thread safety. + +As for performance and scalability, pools can become bottlenecks, if all the +pooled objects are in use and more clients need them, threads will become +blocked waiting for available object from the pool. This is not the case with +Flyweight. + +### Q7: What are the differences between FluentInterface and Builder patterns? {#Q7} + +Fluent interfaces are sometimes confused with the Builder pattern, because they share method chaining and a fluent usage. However, fluent interfaces are not primarily used to create shared (mutable) objects, but to configure complex objects without having to respecify the target object on every property change. \ No newline at end of file diff --git a/fluentinterface/etc/fluentinterface.png b/fluentinterface/etc/fluentinterface.png new file mode 100644 index 000000000..611fec7c6 Binary files /dev/null and b/fluentinterface/etc/fluentinterface.png differ diff --git a/fluentinterface/etc/fluentinterface.ucls b/fluentinterface/etc/fluentinterface.ucls new file mode 100644 index 000000000..aab2c9ad7 --- /dev/null +++ b/fluentinterface/etc/fluentinterface.ucls @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fluentinterface/index.md b/fluentinterface/index.md new file mode 100644 index 000000000..27a4d1a26 --- /dev/null +++ b/fluentinterface/index.md @@ -0,0 +1,42 @@ +--- +layout: pattern +title: Fluent Interface +folder: fluentinterface +permalink: /patterns/fluentinterface/ +categories: Other +tags: + - Java + - Difficulty-Intermediate +--- + +**Intent:** A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific language. Using this pattern results in code that can be read nearly as human language. + +**Implementation:** + +A fluent interface can be implemented using any of + + * Method Chaining - calling a method returns some object on which further methods can be called. + * Static Factory Methods and Imports + * Named parameters - can be simulated in Java using static factory methods. + +![Fluent Interface](./etc/fluentinterface.png "Fluent Interface") + + +**Applicability:** Use the Fluent Interface pattern when + +* you provide an API that would benefit from a DSL-like usage +* you have objects that are difficult to configure or use + +**Real world examples:** + +* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html) +* [Google Guava FluentInterable](https://github.com/google/guava/wiki/FunctionalExplained) +* [JOOQ](http://www.jooq.org/doc/3.0/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/) +* [Mockito](http://mockito.org/) +* [Java Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial) + +**Credits** + +* [Fluent Interface - Martin Fowler](http://www.martinfowler.com/bliki/FluentInterface.html) +* [Evolutionary architecture and emergent design: Fluent interfaces - Neal Ford](http://www.ibm.com/developerworks/library/j-eaed14/) +* [Internal DSL](http://www.infoq.com/articles/internal-dsls-java) diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml new file mode 100644 index 000000000..be8ab8039 --- /dev/null +++ b/fluentinterface/pom.xml @@ -0,0 +1,20 @@ + + + + java-design-patterns + com.iluwatar + 1.6.0 + + 4.0.0 + + fluentinterface + + + junit + junit + test + + + \ No newline at end of file diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java new file mode 100644 index 000000000..f7352fe39 --- /dev/null +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/App.java @@ -0,0 +1,103 @@ +package com.iluwatar.fluentinterface; + +import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; +import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable; +import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; + +import static java.lang.String.valueOf; + +/** + * Fluent interface pattern is useful when you want to provide an easy readable, flowing API. Those + * interfaces tend to mimic domain specific languages, so they can nearly be read as human + * languages. + *

+ * In this example two implementations of a {@link FluentIterable} interface are given. The + * SimpleFluentIterable evaluates eagerly and would be too costly for real world applications. The + * LazyFluentIterable is evaluated on termination. Their usage is demonstrated with a simple number + * list that is filtered, transformed and collected. The result is printed afterwards. + *

+ */ +public class App { + + public static void main(String[] args) { + + List integerList = new ArrayList<>(); + integerList.addAll(Arrays.asList( + 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, + 45, 23, 2, -68, 45 + )); + + prettyPrint("The initial list contains: ", integerList); + + List firstFiveNegatives = + SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).first(3).asList(); + prettyPrint("The first three negative values are: ", firstFiveNegatives); + + + List lastTwoPositives = + SimpleFluentIterable.fromCopyOf(integerList).filter(positives()).last(2).asList(); + prettyPrint("The last two positive values are: ", lastTwoPositives); + + SimpleFluentIterable + .fromCopyOf(integerList) + .filter(number -> number % 2 == 0) + .first() + .ifPresent( + evenNumber -> System.out.println(String.format("The first even number is: %d", + evenNumber))); + + + List transformedList = + SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).map(transformToString()) + .asList(); + prettyPrint("A string-mapped list of negative numbers contains: ", transformedList); + + + List lastTwoOfFirstFourStringMapped = + LazyFluentIterable.from(integerList).filter(positives()).first(4).last(2) + .map(number -> "String[" + String.valueOf(number) + "]").asList(); + prettyPrint( + "The lazy list contains the last two of the first four positive numbers mapped to Strings: ", + lastTwoOfFirstFourStringMapped); + + LazyFluentIterable + .from(integerList) + .filter(negatives()) + .first(2) + .last() + .ifPresent( + lastOfFirstTwo -> System.out.println(String.format( + "The last of the first two negatives is: %d", lastOfFirstTwo))); + } + + private static Function transformToString() { + return integer -> "String[" + valueOf(integer) + "]"; + } + + private static Predicate negatives() { + return integer -> (integer < 0); + } + + private static Predicate positives() { + return integer -> (integer > 0); + } + + private static void prettyPrint(String prefix, Iterable iterable) { + prettyPrint(", ", prefix, ".", iterable); + } + + private static void prettyPrint(String delimiter, String prefix, String suffix, + Iterable iterable) { + StringJoiner joiner = new StringJoiner(delimiter, prefix, "."); + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + joiner.add(iterator.next().toString()); + } + + System.out.println(joiner); + } +} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java new file mode 100644 index 000000000..5c4df0391 --- /dev/null +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java @@ -0,0 +1,89 @@ +package com.iluwatar.fluentinterface.fluentiterable; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * The FluentIterable is a more convenient implementation of the common iterable interface based on + * the fluent interface design pattern. This interface defines common operations, but doesn't aim to + * be complete. It was inspired by Guava's com.google.common.collect.FluentIterable. + * + * @param is the class of objects the iterable contains + */ +public interface FluentIterable extends Iterable { + + /** + * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy + * the predicate. + * + * @param predicate the condition to test with for the filtering. If the test is negative, the + * tested object is removed by the iterator. + * @return a filtered FluentIterable + */ + FluentIterable filter(Predicate predicate); + + /** + * Returns an Optional containing the first element of this iterable if present, else returns + * Optional.empty(). + * + * @return the first element after the iteration is evaluated + */ + Optional first(); + + /** + * Evaluates the iteration and leaves only the count first elements. + * + * @return the first count elements as an Iterable + */ + FluentIterable first(int count); + + /** + * Evaluates the iteration and returns the last element. This is a terminating operation. + * + * @return the last element after the iteration is evaluated + */ + Optional last(); + + /** + * Evaluates the iteration and leaves only the count last elements. + * + * @return the last counts elements as an Iterable + */ + FluentIterable last(int count); + + /** + * Transforms this FluentIterable into a new one containing objects of the type NEW_TYPE. + * + * @param function a function that transforms an instance of TYPE into an instance of NEW_TYPE + * @param the target type of the transformation + * @return a new FluentIterable of the new type + */ + FluentIterable map(Function function); + + /** + * Returns the contents of this Iterable as a List. + * + * @return a List representation of this Iterable + */ + List asList(); + + /** + * Utility method that iterates over iterable and adds the contents to a list. + * + * @param iterable the iterable to collect + * @param the type of the objects to iterate + * @return a list with all objects of the given iterator + */ + static List copyToList(Iterable iterable) { + ArrayList copy = new ArrayList<>(); + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + copy.add(iterator.next()); + } + return copy; + } +} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java new file mode 100644 index 000000000..e80356d8e --- /dev/null +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java @@ -0,0 +1,60 @@ +package com.iluwatar.fluentinterface.fluentiterable.lazy; + +import java.util.Iterator; + +/** + * This class is used to realize LazyFluentIterables. It decorates a given iterator. Does not + * support consecutive hasNext() calls. + * + * @param + */ +public abstract class DecoratingIterator implements Iterator { + + protected final Iterator fromIterator; + + private TYPE next = null; + + /** + * Creates an iterator that decorates the given iterator. + * + * @param fromIterator + */ + public DecoratingIterator(Iterator fromIterator) { + this.fromIterator = fromIterator; + } + + /** + * Precomputes and saves the next element of the Iterable. null is considered as end of data. + * + * @return true if a next element is available + */ + @Override + public final boolean hasNext() { + next = computeNext(); + return next != null; + } + + /** + * Returns the next element of the Iterable. + * + * @return the next element of the Iterable, or null if not present. + */ + @Override + public final TYPE next() { + if (next == null) { + return fromIterator.next(); + } else { + final TYPE result = next; + next = null; + return result; + } + } + + /** + * Computes the next object of the Iterable. Can be implemented to realize custom behaviour for an + * iteration process. null is considered as end of data. + * + * @return the next element of the Iterable. + */ + public abstract TYPE computeNext(); +} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java new file mode 100644 index 000000000..560b10189 --- /dev/null +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java @@ -0,0 +1,230 @@ +package com.iluwatar.fluentinterface.fluentiterable.lazy; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; + +import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; + +/** + * This is a lazy implementation of the FluentIterable interface. It evaluates all chained + * operations when a terminating operation is applied. + * + * @param the type of the objects the iteration is about + */ +public class LazyFluentIterable implements FluentIterable { + + private final Iterable iterable; + + /** + * This constructor creates a new LazyFluentIterable. It wraps the given iterable. + * + * @param iterable the iterable this FluentIterable works on. + */ + protected LazyFluentIterable(Iterable iterable) { + this.iterable = iterable; + } + + /** + * This constructor can be used to implement anonymous subclasses of the LazyFluentIterable. + */ + protected LazyFluentIterable() { + iterable = this; + } + + /** + * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy + * the predicate. + * + * @param predicate the condition to test with for the filtering. If the test is negative, the + * tested object is removed by the iterator. + * @return a new FluentIterable object that decorates the source iterable + */ + @Override + public FluentIterable filter(Predicate predicate) { + return new LazyFluentIterable() { + @Override + public Iterator iterator() { + return new DecoratingIterator(iterable.iterator()) { + @Override + public TYPE computeNext() { + while (fromIterator.hasNext()) { + TYPE candidate = fromIterator.next(); + if (!predicate.test(candidate)) { + continue; + } + return candidate; + } + + return null; + } + }; + } + }; + } + + /** + * Can be used to collect objects from the iteration. Is a terminating operation. + * + * @return an Optional containing the first object of this Iterable + */ + @Override + public Optional first() { + Iterator resultIterator = first(1).iterator(); + return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); + } + + /** + * Can be used to collect objects from the iteration. + * + * @param count defines the number of objects to return + * @return the same FluentIterable with a collection decimated to a maximum of 'count' first + * objects. + */ + @Override + public FluentIterable first(int count) { + return new LazyFluentIterable() { + @Override + public Iterator iterator() { + return new DecoratingIterator(iterable.iterator()) { + int currentIndex = 0; + + @Override + public TYPE computeNext() { + if (currentIndex < count) { + if (fromIterator.hasNext()) { + TYPE candidate = fromIterator.next(); + currentIndex++; + return candidate; + } + } + return null; + } + }; + } + }; + } + + /** + * Can be used to collect objects from the iteration. Is a terminating operation. + * + * @return an Optional containing the last object of this Iterable + */ + @Override + public Optional last() { + Iterator resultIterator = last(1).iterator(); + return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); + } + + /** + * Can be used to collect objects from the Iterable. Is a terminating operation. This operation is + * memory intensive, because the contents of this Iterable are collected into a List, when the + * next object is requested. + * + * @param count defines the number of objects to return + * @return the same FluentIterable with a collection decimated to a maximum of 'count' last + * objects + */ + @Override + public FluentIterable last(int count) { + return new LazyFluentIterable() { + @Override + public Iterator iterator() { + return new DecoratingIterator(iterable.iterator()) { + private int stopIndex; + private int totalElementsCount; + private List list; + private int currentIndex = 0; + + @Override + public TYPE computeNext() { + initialize(); + + TYPE candidate = null; + while (currentIndex < stopIndex && fromIterator.hasNext()) { + currentIndex++; + fromIterator.next(); + } + if (currentIndex >= stopIndex && fromIterator.hasNext()) { + candidate = fromIterator.next(); + } + return candidate; + } + + private void initialize() { + if (list == null) { + list = new ArrayList<>(); + Iterator newIterator = iterable.iterator(); + while (newIterator.hasNext()) { + list.add(newIterator.next()); + } + + totalElementsCount = list.size(); + stopIndex = totalElementsCount - count; + } + } + }; + } + }; + } + + /** + * Transforms this FluentIterable into a new one containing objects of the type NEW_TYPE. + * + * @param function a function that transforms an instance of TYPE into an instance of NEW_TYPE + * @param the target type of the transformation + * @return a new FluentIterable of the new type + */ + @Override + public FluentIterable map(Function function) { + return new LazyFluentIterable() { + @Override + public Iterator iterator() { + return new DecoratingIterator(null) { + Iterator oldTypeIterator = iterable.iterator(); + + @Override + public NEW_TYPE computeNext() { + while (oldTypeIterator.hasNext()) { + TYPE candidate = oldTypeIterator.next(); + return function.apply(candidate); + } + return null; + } + }; + } + }; + } + + /** + * Collects all remaining objects of this iteration into a list. + * + * @return a list with all remaining objects of this iteration + */ + @Override + public List asList() { + List copy = FluentIterable.copyToList(iterable); + return copy; + } + + @Override + public Iterator iterator() { + return new DecoratingIterator(iterable.iterator()) { + @Override + public TYPE computeNext() { + return fromIterator.next(); + } + }; + } + + /** + * @return a FluentIterable from a given iterable. Calls the LazyFluentIterable constructor. + */ + public static final FluentIterable from(Iterable iterable) { + return new LazyFluentIterable<>(iterable); + } + +} diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java new file mode 100644 index 000000000..19283152e --- /dev/null +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java @@ -0,0 +1,198 @@ +package com.iluwatar.fluentinterface.fluentiterable.simple; + +import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * This is a simple implementation of the FluentIterable interface. It evaluates all chained + * operations eagerly. This implementation would be costly to be utilized in real applications. + * + * @param the type of the objects the iteration is about + */ +public class SimpleFluentIterable implements FluentIterable { + + private final Iterable iterable; + + /** + * This constructor creates a copy of a given iterable's contents. + * + * @param iterable the iterable this interface copies to work on. + */ + protected SimpleFluentIterable(Iterable iterable) { + this.iterable = iterable; + } + + /** + * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy + * the predicate. + * + * @param predicate the condition to test with for the filtering. If the test is negative, the + * tested object is removed by the iterator. + * @return the same FluentIterable with a filtered collection + */ + @Override + public final FluentIterable filter(Predicate predicate) { + Iterator iterator = iterator(); + while (iterator.hasNext()) { + TYPE nextElement = iterator.next(); + if (!predicate.test(nextElement)) { + iterator.remove(); + } + } + return this; + } + + /** + * Can be used to collect objects from the Iterable. Is a terminating operation. + * + * @return an option of the first object of the Iterable + */ + @Override + public final Optional first() { + Iterator resultIterator = first(1).iterator(); + return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty(); + } + + /** + * Can be used to collect objects from the Iterable. Is a terminating operation. + * + * @param count defines the number of objects to return + * @return the same FluentIterable with a collection decimated to a maximum of 'count' first + * objects. + */ + @Override + public final FluentIterable first(int count) { + Iterator iterator = iterator(); + int currentCount = 0; + while (iterator.hasNext()) { + iterator.next(); + if (currentCount >= count) { + iterator.remove(); + } + currentCount++; + } + return this; + } + + /** + * Can be used to collect objects from the Iterable. Is a terminating operation. + * + * @return an option of the last object of the Iterable + */ + @Override + public final Optional last() { + List list = last(1).asList(); + if (list.isEmpty()) { + return Optional.empty(); + } + return Optional.of(list.get(0)); + } + + /** + * Can be used to collect objects from the Iterable. Is a terminating operation. + * + * @param count defines the number of objects to return + * @return the same FluentIterable with a collection decimated to a maximum of 'count' last + * objects + */ + @Override + public final FluentIterable last(int count) { + int remainingElementsCount = getRemainingElementsCount(); + Iterator iterator = iterator(); + int currentIndex = 0; + while (iterator.hasNext()) { + iterator.next(); + if (currentIndex < remainingElementsCount - count) { + iterator.remove(); + } + currentIndex++; + } + + return this; + } + + /** + * Transforms this FluentIterable into a new one containing objects of the type NEW_TYPE. + * + * @param function a function that transforms an instance of TYPE into an instance of NEW_TYPE + * @param the target type of the transformation + * @return a new FluentIterable of the new type + */ + @Override + public final FluentIterable map(Function function) { + List temporaryList = new ArrayList<>(); + Iterator iterator = iterator(); + while (iterator.hasNext()) { + temporaryList.add(function.apply(iterator.next())); + } + return from(temporaryList); + } + + /** + * Collects all remaining objects of this Iterable into a list. + * + * @return a list with all remaining objects of this Iterable + */ + @Override + public List asList() { + return toList(iterable.iterator()); + } + + /** + * @return a FluentIterable from a given iterable. Calls the SimpleFluentIterable constructor. + */ + public static final FluentIterable from(Iterable iterable) { + return new SimpleFluentIterable<>(iterable); + } + + public static final FluentIterable fromCopyOf(Iterable iterable) { + List copy = FluentIterable.copyToList(iterable); + return new SimpleFluentIterable<>(copy); + } + + @Override + public Iterator iterator() { + return iterable.iterator(); + } + + @Override + public void forEach(Consumer action) { + iterable.forEach(action); + } + + + @Override + public Spliterator spliterator() { + return iterable.spliterator(); + } + + /** + * @return the count of remaining objects of the current Iterable + */ + public final int getRemainingElementsCount() { + int counter = 0; + Iterator iterator = iterator(); + while (iterator.hasNext()) { + iterator.next(); + counter++; + } + return counter; + } + + /** + * Collects the remaining objects of the given iterator into a List. + * + * @return a new List with the remaining objects. + */ + public static List toList(Iterator iterator) { + List copy = new ArrayList<>(); + while (iterator.hasNext()) { + copy.add(iterator.next()); + } + return copy; + } +} diff --git a/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java new file mode 100644 index 000000000..d0abb7bf1 --- /dev/null +++ b/fluentinterface/src/test/java/com/iluwatar/fluentinterface/AppTest.java @@ -0,0 +1,12 @@ +package com.iluwatar.fluentinterface; + +import org.junit.Test; + +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index 8cac48a09..c9387b58d 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -27,7 +27,7 @@ - 1.9.0-SNAPSHOT + 1.9.0 UTF-8 UTF-8 diff --git a/pom.xml b/pom.xml index 68cfab646..2205c9220 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.iluwatar @@ -9,8 +10,8 @@ UTF-8 - 5.0.0.Final - 1.8.2.RELEASE + 5.0.1.Final + 1.9.0.RELEASE 1.4.188 4.12 3.0 @@ -77,8 +78,9 @@ step-builder layers message-channel + fluentinterface reactor - + @@ -206,6 +208,30 @@ + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.15 + + + validate + + check + + validate + + checkstyle.xml + UTF-8 + false + false + + + + diff --git a/update-ghpages.sh b/update-ghpages.sh new file mode 100644 index 000000000..82486d5a4 --- /dev/null +++ b/update-ghpages.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Clone gh-pages +git clone -b gh-pages "https://${GH_REF}" ghpagesclone +cd ghpagesclone + +# Init and update submodule to latest +git submodule update --init --recursive +git submodule update --remote + +# Setup Git +git config user.name "Travis-CI" +git config user.email "travis@no.reply" + +# If there is a new version of the master branch +if git status | grep patterns > /dev/null 2>&1 +then + # it should be committed + git add . + git commit -m ":sparkles: :up: Automagic Update via Travis-CI" + git push --quiet "https://${GH_TOKEN}:x-oauth-basic@${GH_REF}" gh-pages > /dev/null 2>&1 +fi