summaryrefslogtreecommitdiff
path: root/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
diff options
context:
space:
mode:
authorDico200 <dico.karssiens@gmail.com>2018-07-25 01:53:02 +0100
committerDico200 <dico.karssiens@gmail.com>2018-07-25 01:53:02 +0100
commit5e168847c2624b767deb9da310ecfdf169e0f43c (patch)
tree56b76556a6837fff20b800d5a22218286a975581 /dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
parent60503351a30a91985b95ee8aa64e163ef084b34b (diff)
Add dicore3-core, without really irrelevant packages
Diffstat (limited to 'dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java')
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java173
1 files changed, 173 insertions, 0 deletions
diff --git a/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java b/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
new file mode 100644
index 0000000..b59979a
--- /dev/null
+++ b/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
@@ -0,0 +1,173 @@
+package io.dico.dicore;
+
+/**
+ * A chainable object
+ * <p>
+ * It is not possible to declare another upper bound for type parameter Subtype.
+ * However, it is required that it also extends the type parameter Element.
+ *
+ * @param <Subtype> the interface that is chainable
+ * @param <Element> the element of the chain, this is a supertype of the subtype
+ */
+@SuppressWarnings("unchecked")
+public interface InterfaceChain<Element, Subtype extends InterfaceChain<Element, Subtype>> {
+
+ /**
+ * returns the empty InterfaceChain instance.
+ *
+ * @return the empty InterfaceChain instance
+ */
+ Subtype getEmptyInstance();
+
+ /**
+ * returns a InterfaceChain with the last added element detached.
+ * <p>
+ * if this InterfaceChain is the empty instance, the empty instance is returned.
+ *
+ * @return a InterfaceChain with the last added element detached
+ * @implNote for the purpose of lambdas, the default implementation also returns the empty instance.
+ */
+ default Subtype withoutLastNode() {
+ return getEmptyInstance();
+ }
+
+ /**
+ * returns the element that was inserted as the last element
+ * <p>
+ * For instance, calling this method on the result of calling {@link InterfaceChain#withElement(Object)}
+ * would return the given element.
+ *
+ * @return the element that was inserted as the last element
+ * @implNote for the purpose of lambdas, the default implementation returns this object,
+ * which is required to implement the Element type parameter.
+ */
+ default Element getDelegateOfLastNode() {
+ //noinspection unchecked
+ return (Element) this;
+ }
+
+ /**
+ * @return The number of elements chained from this InterfaceChain.
+ * @implNote for the purpose of lambdas, the default implementation returns 1.
+ */
+ default int getElementCount() {
+ return 1;
+ }
+
+ /**
+ * Get a new InterfaceChain that includes the given Element.
+ * <p>
+ * The default implementation of the Subtype should look like this:
+ * <pre> {@code
+ * if (element == null) {
+ * return this;
+ * }
+ *
+ * int count = getElementCount() + 1;
+ * return new Subtype() {
+ * \@Override
+ * public void exampleElementMethod() {
+ * try {
+ * Subtype.this.exampleElementMethod();
+ * } finally {
+ * element.exampleElementMethod();
+ * }
+ * }
+ *
+ * \@Override
+ * public Subtype withoutLastNode() {
+ * return Subtype.this;
+ * }
+ *
+ * \@Override
+ * public Element getDelegateOfLastNode() {
+ * return element;
+ * }
+ *
+ * \@Override
+ * public int getElementCount() {
+ * return count;
+ * }
+ * };
+ * }
+ * </pre>
+ *
+ * @param element A new element to insert at the end of this InterfaceChain.
+ * @return a new InterfaceChain that includes the given Element.
+ */
+ Subtype withElement(Element element);
+
+ /**
+ * Append each of the elements to this InterfaceChain
+ *
+ * @param elements the elements to append
+ * @return a new InterfaceChain with the elements appended
+ */
+ default Subtype withElements(Element... elements) {
+ Subtype result = (Subtype) this;
+ for (Element element : elements) {
+ result = result.withElement(element);
+ }
+ return result;
+ }
+
+ /*
+ Example Subtypes implementation
+
+ public class Subtypes {
+
+ private Subtypes() {
+
+ }
+
+ private static final Subtype empty = new Subtype() {
+ @Override
+ public void exampleElementMethod() {
+
+ }
+
+ @Override
+ public Subtype withElement(Element other) {
+ return Subtypes.singleton(other);
+ }
+
+ @Override
+ public int getElementCount() {
+ return 0;
+ }
+
+ @Override
+ public Element getDelegateOfLastNode() {
+ return null;
+ }
+ };
+
+ public static Subtype empty() {
+ return empty;
+ }
+
+ public static Subtype singleton(Element element) {
+ if (element instanceof Subtype) {
+ return (Subtype) element;
+ }
+ if (element == null) {
+ return empty();
+ }
+ return new Subtype() {
+ @Override
+ public void exampleElementMethod() {
+ element.exampleElementMethod();
+ }
+
+ @Override
+ public Element getDelegateOfLastNode() {
+ return element;
+ }
+ };
+ }
+
+ }
+
+ */
+
+}