From c1187ae0d787b39ca4019b2a9d5a16d031bef08f Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Tue, 31 May 2016 20:12:27 +0200
Subject: [PATCH 1/8] #355 init abstract-document module

---
 abstract-document/README.md | 26 +++++++++++++++++++++++
 abstract-document/pom.xml   | 42 +++++++++++++++++++++++++++++++++++++
 pom.xml                     |  3 ++-
 3 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 abstract-document/README.md
 create mode 100644 abstract-document/pom.xml

diff --git a/abstract-document/README.md b/abstract-document/README.md
new file mode 100644
index 000000000..d9538c0bd
--- /dev/null
+++ b/abstract-document/README.md
@@ -0,0 +1,26 @@
+---
+layout: pattern
+title: Abstract Document
+folder: abstract-document
+permalink: /patterns/abstract-document/
+categories: Structural
+tags: 
+ - Java
+ - Difficulty-Intermediate
+---
+
+## Intent
+Achieve flexibility of untyped languages and keep the type-safety 
+
+![alt text](./etc/abstract-document_1.png "Abstract Document")
+
+## Applicability
+Use the Abstract Document Pattern when
+
+* there is a need for dynamic properties
+* you want a better way to organize domain
+* you want loosely coupled system with flexibility of untyped languages
+
+## Real world examples
+
+* [Speedment](https://github.com/speedment/speedment)
\ No newline at end of file
diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml
new file mode 100644
index 000000000..e7fc58047
--- /dev/null
+++ b/abstract-document/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>java-design-patterns</artifactId>
+        <groupId>com.iluwatar</groupId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>abstract-document</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index af807b8ba..362519090 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,7 +125,8 @@
 		<module>mutex</module>
 		<module>semaphore</module>
                 <module>hexagonal</module>
-  </modules>
+		<module>abstract-document</module>
+	</modules>
 
 	<dependencyManagement>
 		<dependencies>

From 913411773f708a5d3d73cc7953a75c596f9bd7cd Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Wed, 1 Jun 2016 22:20:55 +0200
Subject: [PATCH 2/8] #355 document, abstract base, traits and example domain

---
 .../abstractdocument/AbstractDocument.java    | 38 +++++++++++++++++++
 .../iluwatar/abstractdocument/Document.java   | 34 +++++++++++++++++
 .../iluwatar/abstractdocument/domain/Car.java | 18 +++++++++
 .../abstractdocument/domain/HasModel.java     | 13 +++++++
 .../abstractdocument/domain/HasParts.java     | 13 +++++++
 .../abstractdocument/domain/HasPrice.java     | 13 +++++++
 .../abstractdocument/domain/Part.java         | 18 +++++++++
 7 files changed, 147 insertions(+)
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java

diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
new file mode 100644
index 000000000..d4aa8ed5b
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
@@ -0,0 +1,38 @@
+package com.iluwatar.abstractdocument;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+public abstract class AbstractDocument implements Document {
+
+	private final Map<String, Object> properties;
+
+	protected AbstractDocument(Map<String, Object> properties) {
+		Objects.requireNonNull(properties, "properties map is required");
+		this.properties = properties;
+	}
+
+	@Override
+	public Void put(String key, Object value) {
+		properties.put(key, value);
+		return null;
+	}
+
+	@Override
+	public Object get(String key) {
+		return properties.get(key);
+	}
+
+	@Override
+	public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
+		return Stream.of(get(key))
+				.filter(el -> el != null)
+				.map(el -> (List<Map<String, Object>>) el)
+				.findFirst().get().stream()
+				.map(constructor);
+	}
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
new file mode 100644
index 000000000..8d4db30b9
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
@@ -0,0 +1,34 @@
+package com.iluwatar.abstractdocument;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+public interface Document {
+
+	/**
+	 * Puts the value related to the key
+	 * 
+	 * @param key
+	 * @param value
+	 * @return Void
+	 */
+	Void put(String key, Object value);
+
+	/**
+	 * Gets the value for the key
+	 * 
+	 * @param key
+	 * @return value or null
+	 */
+	Object get(String key);
+
+	/**
+	 * Gets the stream of child documents
+	 * 
+	 * @param key
+	 * @param constructor
+	 * @return child documents
+	 */
+	<T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
new file mode 100644
index 000000000..70e31e70e
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
@@ -0,0 +1,18 @@
+package com.iluwatar.abstractdocument.domain;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.iluwatar.abstractdocument.AbstractDocument;
+
+public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {
+
+	protected Car() {
+		super(new HashMap<String, Object>());
+	}
+	
+	protected Car(Map<String,Object> properties) {
+		super(properties);
+	}
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
new file mode 100644
index 000000000..635f80abf
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
@@ -0,0 +1,13 @@
+package com.iluwatar.abstractdocument.domain;
+
+import java.util.Optional;
+
+import com.iluwatar.abstractdocument.Document;
+
+public interface HasModel extends Document {
+	
+	default Optional<String> getModel() {
+		return Optional.ofNullable((String) get("model"));
+	}
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
new file mode 100644
index 000000000..92c7dc7d9
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
@@ -0,0 +1,13 @@
+package com.iluwatar.abstractdocument.domain;
+
+import java.util.stream.Stream;
+
+import com.iluwatar.abstractdocument.Document;
+
+public interface HasParts extends Document {
+	
+	default Stream<Part> getParts() {
+		return children("parts", Part::new);
+	}
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
new file mode 100644
index 000000000..7c9e8e6a1
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
@@ -0,0 +1,13 @@
+package com.iluwatar.abstractdocument.domain;
+
+import java.util.Optional;
+
+import com.iluwatar.abstractdocument.Document;
+
+public interface HasPrice extends Document {
+	
+	default Optional<Number> getPartner() {
+		return Optional.ofNullable((Number) get("price"));
+	}
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
new file mode 100644
index 000000000..fa252a7bc
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
@@ -0,0 +1,18 @@
+package com.iluwatar.abstractdocument.domain;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.iluwatar.abstractdocument.AbstractDocument;
+
+public class Part extends AbstractDocument implements HasModel, HasPrice {
+
+	protected Part() {
+		super(new HashMap<String, Object>());
+	}
+	
+	protected Part(Map<String, Object> properties) {
+		super(properties);
+	}
+
+}

From 32b647323c845733fd7b8bfc93752a376b0543ae Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Wed, 1 Jun 2016 22:21:31 +0200
Subject: [PATCH 3/8] #355 class diagrams

---
 .../etc/abstract-document-base.png            | Bin 0 -> 14973 bytes
 .../etc/abstract-document-base.ucls           |  58 +++++++++++
 abstract-document/etc/abstract-document.png   | Bin 0 -> 16712 bytes
 abstract-document/etc/abstract-document.ucls  |  96 ++++++++++++++++++
 4 files changed, 154 insertions(+)
 create mode 100644 abstract-document/etc/abstract-document-base.png
 create mode 100644 abstract-document/etc/abstract-document-base.ucls
 create mode 100644 abstract-document/etc/abstract-document.png
 create mode 100644 abstract-document/etc/abstract-document.ucls

diff --git a/abstract-document/etc/abstract-document-base.png b/abstract-document/etc/abstract-document-base.png
new file mode 100644
index 0000000000000000000000000000000000000000..13345dbb862c12463c352af53dafb7f3ee42bf37
GIT binary patch
literal 14973
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
T^}xTC-jjMQFIFP*#_#_C2aR!W

literal 0
HcmV?d00001

diff --git a/abstract-document/etc/abstract-document-base.ucls b/abstract-document/etc/abstract-document-base.ucls
new file mode 100644
index 000000000..bfe927ed9
--- /dev/null
+++ b/abstract-document/etc/abstract-document-base.ucls
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<class-diagram version="1.1.9" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true" 
+  realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">  
+  <interface id="1" language="java" name="com.iluwatar.abstractdocument.Document" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/Document.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="249" y="405"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </interface>  
+  <class id="2" language="java" name="com.iluwatar.abstractdocument.AbstractDocument" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/AbstractDocument.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="250" y="237"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <class id="3" language="java" name="com.iluwatar.abstractdocument.domain.Car" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/Car.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="108" y="75"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <class id="4" language="java" name="com.iluwatar.abstractdocument.domain.Part" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/Part.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="400" y="76"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <generalization id="5">    
+    <end type="SOURCE" refId="4"/>    
+    <end type="TARGET" refId="2"/>  
+  </generalization>  
+  <realization id="6">    
+    <end type="SOURCE" refId="2"/>    
+    <end type="TARGET" refId="1"/>  
+  </realization>  
+  <generalization id="7">    
+    <end type="SOURCE" refId="3"/>    
+    <end type="TARGET" refId="2"/>  
+  </generalization>  
+  <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+    sort-features="false" accessors="true" visibility="true">    
+    <attributes public="true" package="true" protected="true" private="true" static="true"/>    
+    <operations public="true" package="true" protected="true" private="true" static="true"/>  
+  </classifier-display>  
+  <association-display labels="true" multiplicity="true"/>
+</class-diagram>
\ No newline at end of file
diff --git a/abstract-document/etc/abstract-document.png b/abstract-document/etc/abstract-document.png
new file mode 100644
index 0000000000000000000000000000000000000000..98d186f7e7aa8de23be6656c58332c826db77aa7
GIT binary patch
literal 16712
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

literal 0
HcmV?d00001

diff --git a/abstract-document/etc/abstract-document.ucls b/abstract-document/etc/abstract-document.ucls
new file mode 100644
index 000000000..ad97457fd
--- /dev/null
+++ b/abstract-document/etc/abstract-document.ucls
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<class-diagram version="1.1.9" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true" 
+  realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">  
+  <interface id="1" language="java" name="com.iluwatar.abstractdocument.Document" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/Document.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="-1" width="-1" x="341" y="376"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </interface>  
+  <interface id="2" language="java" name="com.iluwatar.abstractdocument.domain.HasModel" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/HasModel.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="81" width="173" x="41" y="194"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </interface>  
+  <interface id="3" language="java" name="com.iluwatar.abstractdocument.domain.HasPrice" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/HasPrice.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="81" width="175" x="254" y="194"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </interface>  
+  <interface id="4" language="java" name="com.iluwatar.abstractdocument.domain.HasParts" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/HasParts.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="81" width="173" x="469" y="194"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </interface>  
+  <class id="5" language="java" name="com.iluwatar.abstractdocument.domain.Car" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/Car.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="99" width="173" x="254" y="37"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <class id="6" language="java" name="com.iluwatar.abstractdocument.domain.Part" project="design-patterns" 
+    file="/design-patterns/src/com/iluwatar/abstractdocument/domain/Part.java" binary="false" corner="BOTTOM_RIGHT">    
+    <position height="99" width="173" x="41" y="37"/>    
+    <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+      sort-features="false" accessors="true" visibility="true">      
+      <attributes public="true" package="true" protected="true" private="true" static="true"/>      
+      <operations public="true" package="true" protected="true" private="true" static="true"/>    
+    </display>  
+  </class>  
+  <realization id="7">    
+    <end type="SOURCE" refId="5"/>    
+    <end type="TARGET" refId="2"/>  
+  </realization>  
+  <realization id="8">    
+    <end type="SOURCE" refId="6"/>    
+    <end type="TARGET" refId="2"/>  
+  </realization>  
+  <generalization id="9">    
+    <end type="SOURCE" refId="2"/>    
+    <end type="TARGET" refId="1"/>  
+  </generalization>  
+  <realization id="10">    
+    <end type="SOURCE" refId="5"/>    
+    <end type="TARGET" refId="3"/>  
+  </realization>  
+  <realization id="11">    
+    <end type="SOURCE" refId="5"/>    
+    <end type="TARGET" refId="4"/>  
+  </realization>  
+  <generalization id="12">    
+    <end type="SOURCE" refId="3"/>    
+    <end type="TARGET" refId="1"/>  
+  </generalization>  
+  <generalization id="13">    
+    <end type="SOURCE" refId="4"/>    
+    <end type="TARGET" refId="1"/>  
+  </generalization>  
+  <realization id="14">    
+    <end type="SOURCE" refId="6"/>    
+    <end type="TARGET" refId="3"/>  
+  </realization>  
+  <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" 
+    sort-features="false" accessors="true" visibility="true">    
+    <attributes public="true" package="true" protected="true" private="true" static="true"/>    
+    <operations public="true" package="true" protected="true" private="true" static="true"/>  
+  </classifier-display>  
+  <association-display labels="true" multiplicity="true"/>
+</class-diagram>
\ No newline at end of file

From a372f05e41910ed86b5d9d2d6cfd43ad1f964a24 Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Thu, 2 Jun 2016 07:27:35 +0200
Subject: [PATCH 4/8] #355 override toString to log properties

---
 .../abstractdocument/AbstractDocument.java    | 55 +++++++++++--------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
index d4aa8ed5b..c3f8e2a4b 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
@@ -8,31 +8,42 @@ import java.util.stream.Stream;
 
 public abstract class AbstractDocument implements Document {
 
-	private final Map<String, Object> properties;
+    private final Map<String, Object> properties;
 
-	protected AbstractDocument(Map<String, Object> properties) {
-		Objects.requireNonNull(properties, "properties map is required");
-		this.properties = properties;
-	}
+    protected AbstractDocument(Map<String, Object> properties) {
+        Objects.requireNonNull(properties, "properties map is required");
+        this.properties = properties;
+    }
 
-	@Override
-	public Void put(String key, Object value) {
-		properties.put(key, value);
-		return null;
-	}
+    @Override
+    public Void put(String key, Object value) {
+        properties.put(key, value);
+        return null;
+    }
 
-	@Override
-	public Object get(String key) {
-		return properties.get(key);
-	}
+    @Override
+    public Object get(String key) {
+        return properties.get(key);
+    }
 
-	@Override
-	public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
-		return Stream.of(get(key))
-				.filter(el -> el != null)
-				.map(el -> (List<Map<String, Object>>) el)
-				.findFirst().get().stream()
-				.map(constructor);
-	}
+    @Override
+    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
+        return Stream.of(get(key))
+                .filter(el -> el != null)
+                .map(el -> (List<Map<String, Object>>) el)
+                .findAny().get().stream()
+                .map(constructor);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(getClass().getName()).append("[");
+        properties.entrySet().forEach(e ->
+                builder.append("[").append(e.getKey()).append(" : ").append(e.getValue()).append("]")
+        );
+        builder.append("]");
+        return builder.toString();
+    }
 
 }

From 43f90ead48709c44d5253864d3d31c6bc24b0601 Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Thu, 2 Jun 2016 07:29:37 +0200
Subject: [PATCH 5/8] #355 abstract document test

---
 .../AbstractDocumentTest.java                 | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java

diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
new file mode 100644
index 000000000..43585d853
--- /dev/null
+++ b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
@@ -0,0 +1,48 @@
+package com.iluwatar.abstractdocument;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+
+public class AbstractDocumentTest {
+
+    private static final String KEY = "key";
+    private static final Object VALUE = "value";
+
+    private class DocumentImplementation extends AbstractDocument {
+
+        DocumentImplementation(Map<String, Object> properties) {
+            super(properties);
+        }
+    }
+
+    private DocumentImplementation document = new DocumentImplementation(new HashMap<>());
+
+    @Test
+    public void shouldPutAndGetValue() {
+        document.put(KEY, VALUE);
+        assertEquals(VALUE, document.get(KEY));
+        System.out.println(document);
+    }
+
+    @Test
+    public void shouldRetrieveChildren() {
+        Map<String,Object> child1 = new HashMap<>();
+        Map<String,Object> child2 = new HashMap<>();
+        List<Map<String, Object>> children = Arrays.asList(child1, child2);
+
+        document.put(KEY, children);
+
+        Stream<DocumentImplementation> childrenStream = document.children(KEY, DocumentImplementation::new);
+        assertNotNull(children);
+        assertEquals(2, childrenStream.count());
+    }
+
+}

From f3110de1306659b6cd70a318a1070a28fefc680e Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Thu, 2 Jun 2016 07:32:48 +0200
Subject: [PATCH 6/8] #355 handle case when there are no child elements for the
 given key

---
 .../com/iluwatar/abstractdocument/AbstractDocument.java   | 7 ++++---
 .../iluwatar/abstractdocument/AbstractDocumentTest.java   | 8 +++++++-
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
index c3f8e2a4b..f5ef69e3c 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
@@ -3,6 +3,7 @@ package com.iluwatar.abstractdocument;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
@@ -28,11 +29,11 @@ public abstract class AbstractDocument implements Document {
 
     @Override
     public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
-        return Stream.of(get(key))
+        Optional<List<Map<String, Object>>> any = Stream.of(get(key))
                 .filter(el -> el != null)
                 .map(el -> (List<Map<String, Object>>) el)
-                .findAny().get().stream()
-                .map(constructor);
+                .findAny();
+        return any.isPresent() ? any.get().stream().map(constructor) : Stream.empty();
     }
 
     @Override
diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
index 43585d853..baf872e4f 100644
--- a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
+++ b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
@@ -29,7 +29,6 @@ public class AbstractDocumentTest {
     public void shouldPutAndGetValue() {
         document.put(KEY, VALUE);
         assertEquals(VALUE, document.get(KEY));
-        System.out.println(document);
     }
 
     @Test
@@ -45,4 +44,11 @@ public class AbstractDocumentTest {
         assertEquals(2, childrenStream.count());
     }
 
+    @Test
+    public void shouldRetrieveEmptyStreamForNonExistinChildren() {
+        Stream<DocumentImplementation> children = document.children(KEY, DocumentImplementation::new);
+        assertNotNull(children);
+        assertEquals(0, children.count());
+    }
+
 }

From c229ec23b3f9d40a5f91f6865e299307a6117727 Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Thu, 2 Jun 2016 07:41:32 +0200
Subject: [PATCH 7/8] #355 clean up

---
 .../java/com/iluwatar/abstractdocument/AbstractDocument.java    | 2 +-
 .../src/main/java/com/iluwatar/abstractdocument/domain/Car.java | 2 +-
 .../main/java/com/iluwatar/abstractdocument/domain/Part.java    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
index f5ef69e3c..054b6ebfb 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
@@ -38,7 +38,7 @@ public abstract class AbstractDocument implements Document {
 
     @Override
     public String toString() {
-        final StringBuilder builder = new StringBuilder();
+        StringBuilder builder = new StringBuilder();
         builder.append(getClass().getName()).append("[");
         properties.entrySet().forEach(e ->
                 builder.append("[").append(e.getKey()).append(" : ").append(e.getValue()).append("]")
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
index 70e31e70e..b3dcaa77f 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
@@ -8,7 +8,7 @@ import com.iluwatar.abstractdocument.AbstractDocument;
 public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {
 
 	protected Car() {
-		super(new HashMap<String, Object>());
+		super(new HashMap<>());
 	}
 	
 	protected Car(Map<String,Object> properties) {
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
index fa252a7bc..c6e1a3908 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
@@ -8,7 +8,7 @@ import com.iluwatar.abstractdocument.AbstractDocument;
 public class Part extends AbstractDocument implements HasModel, HasPrice {
 
 	protected Part() {
-		super(new HashMap<String, Object>());
+		super(new HashMap<>());
 	}
 	
 	protected Part(Map<String, Object> properties) {

From afdeba4f9abbc18592585f98c0809517b7f80f33 Mon Sep 17 00:00:00 2001
From: qza <kokovic.zoran@gmail.com>
Date: Sat, 4 Jun 2016 20:06:32 +0200
Subject: [PATCH 8/8] #355 finalize example

---
 abstract-document/README.md                   | 17 ++--
 .../abstractdocument/AbstractDocument.java    | 86 +++++++++++-------
 .../com/iluwatar/abstractdocument/App.java    | 88 ++++++++++++++++++
 .../iluwatar/abstractdocument/Document.java   | 71 ++++++++++-----
 .../iluwatar/abstractdocument/domain/Car.java | 36 ++++++--
 .../abstractdocument/domain/HasModel.java     | 35 +++++++-
 .../abstractdocument/domain/HasParts.java     | 35 +++++++-
 .../abstractdocument/domain/HasPrice.java     | 35 +++++++-
 .../abstractdocument/domain/HasType.java      | 40 +++++++++
 .../abstractdocument/domain/Part.java         | 38 ++++++--
 .../AbstractDocumentTest.java                 | 90 +++++++++++++------
 .../iluwatar/abstractdocument/AppTest.java    | 37 ++++++++
 .../iluwatar/abstractdocument/DomainTest.java | 77 ++++++++++++++++
 pom.xml                                       |  2 +-
 14 files changed, 568 insertions(+), 119 deletions(-)
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java
 create mode 100644 abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java
 create mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java
 create mode 100644 abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java

diff --git a/abstract-document/README.md b/abstract-document/README.md
index d9538c0bd..bf28ff999 100644
--- a/abstract-document/README.md
+++ b/abstract-document/README.md
@@ -12,15 +12,20 @@ tags:
 ## Intent
 Achieve flexibility of untyped languages and keep the type-safety 
 
-![alt text](./etc/abstract-document_1.png "Abstract Document")
+![alt text](./etc/abstract-document-base.png "Abstract Document Base")
+
+![alt text](./etc/abstract-document.png "Abstract Document Traits and Domain")
+
 
 ## Applicability
 Use the Abstract Document Pattern when
 
-* there is a need for dynamic properties
-* you want a better way to organize domain
-* you want loosely coupled system with flexibility of untyped languages
+* there is a need to add new properties on the fly
+* you want a flexible way to organize domain in tree like structure
+* you want more loosely coupled system
 
-## Real world examples
 
-* [Speedment](https://github.com/speedment/speedment)
\ No newline at end of file
+## Credits
+
+* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)
+* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)
\ No newline at end of file
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
index 054b6ebfb..4bf8f0d14 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java
@@ -1,3 +1,25 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
 
 import java.util.List;
@@ -7,44 +29,44 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
+/**
+ * Abstract implementation of Document interface
+ */
 public abstract class AbstractDocument implements Document {
 
-    private final Map<String, Object> properties;
+  private final Map<String, Object> properties;
 
-    protected AbstractDocument(Map<String, Object> properties) {
-        Objects.requireNonNull(properties, "properties map is required");
-        this.properties = properties;
-    }
+  protected AbstractDocument(Map<String, Object> properties) {
+    Objects.requireNonNull(properties, "properties map is required");
+    this.properties = properties;
+  }
 
-    @Override
-    public Void put(String key, Object value) {
-        properties.put(key, value);
-        return null;
-    }
+  @Override
+  public Void put(String key, Object value) {
+    properties.put(key, value);
+    return null;
+  }
 
-    @Override
-    public Object get(String key) {
-        return properties.get(key);
-    }
+  @Override
+  public Object get(String key) {
+    return properties.get(key);
+  }
 
-    @Override
-    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
-        Optional<List<Map<String, Object>>> any = Stream.of(get(key))
-                .filter(el -> el != null)
-                .map(el -> (List<Map<String, Object>>) el)
-                .findAny();
-        return any.isPresent() ? any.get().stream().map(constructor) : Stream.empty();
-    }
+  @Override
+  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
+    Optional<List<Map<String, Object>>> any = Stream.of(get(key)).filter(el -> el != null)
+        .map(el -> (List<Map<String, Object>>) el).findAny();
+    return any.isPresent() ? any.get().stream().map(constructor) : Stream.empty();
+  }
 
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(getClass().getName()).append("[");
-        properties.entrySet().forEach(e ->
-                builder.append("[").append(e.getKey()).append(" : ").append(e.getValue()).append("]")
-        );
-        builder.append("]");
-        return builder.toString();
-    }
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append(getClass().getName()).append("[");
+    properties.entrySet()
+        .forEach(e -> builder.append("[").append(e.getKey()).append(" : ").append(e.getValue()).append("]"));
+    builder.append("]");
+    return builder.toString();
+  }
 
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java
new file mode 100644
index 000000000..d7758b6f7
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java
@@ -0,0 +1,88 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
+
+import com.iluwatar.abstractdocument.domain.Car;
+import com.iluwatar.abstractdocument.domain.HasModel;
+import com.iluwatar.abstractdocument.domain.HasParts;
+import com.iluwatar.abstractdocument.domain.HasPrice;
+import com.iluwatar.abstractdocument.domain.HasType;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The Abstract Document pattern enables handling additional, non-static
+ * properties. This pattern uses concept of traits to enable type safety and
+ * separate properties of different classes into set of interfaces.
+ * <p>
+ * <p>
+ * In Abstract Document pattern,({@link AbstractDocument}) fully implements
+ * {@link Document}) interface. Traits are then defined to enable access to
+ * properties in usual, static way.
+ */
+public class App {
+
+  /**
+   * Executes the App
+   */
+  public App() {
+    System.out.println("Constructing parts and car");
+
+    Map<String, Object> carProperties = new HashMap<>();
+    carProperties.put(HasModel.PROPERTY, "300SL");
+    carProperties.put(HasPrice.PROPERTY, 10000L);
+
+    Map<String, Object> wheelProperties = new HashMap<>();
+    wheelProperties.put(HasType.PROPERTY, "wheel");
+    wheelProperties.put(HasModel.PROPERTY, "15C");
+    wheelProperties.put(HasPrice.PROPERTY, 100L);
+
+    Map<String, Object> doorProperties = new HashMap<>();
+    doorProperties.put(HasType.PROPERTY, "door");
+    doorProperties.put(HasModel.PROPERTY, "Lambo");
+    doorProperties.put(HasPrice.PROPERTY, 300L);
+
+    carProperties.put(HasParts.PROPERTY, Arrays.asList(wheelProperties, doorProperties));
+
+    Car car = new Car(carProperties);
+
+    System.out.println("Here is our car:");
+    System.out.println("-> model: " + car.getModel().get());
+    System.out.println("-> price: " + car.getPrice().get());
+    System.out.println("-> parts: ");
+    car.getParts().forEach(p -> System.out
+        .println("\t" + p.getType().get() + "/" + p.getModel().get() + "/" + p.getPrice().get()));
+  }
+
+  /**
+   * Program entry point
+   *
+   * @param args command line args
+   */
+  public static void main(String[] args) {
+    new App();
+  }
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
index 8d4db30b9..7705f37eb 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java
@@ -1,34 +1,59 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
 
 import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
+/**
+ * Document interface
+ */
 public interface Document {
 
-	/**
-	 * Puts the value related to the key
-	 * 
-	 * @param key
-	 * @param value
-	 * @return Void
-	 */
-	Void put(String key, Object value);
+  /**
+   * Puts the value related to the key
+   *
+   * @param key   element key
+   * @param value element value
+   * @return Void
+   */
+  Void put(String key, Object value);
 
-	/**
-	 * Gets the value for the key
-	 * 
-	 * @param key
-	 * @return value or null
-	 */
-	Object get(String key);
+  /**
+   * Gets the value for the key
+   *
+   * @param key element key
+   * @return value or null
+   */
+  Object get(String key);
 
-	/**
-	 * Gets the stream of child documents
-	 * 
-	 * @param key
-	 * @param constructor
-	 * @return child documents
-	 */
-	<T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);
+  /**
+   * Gets the stream of child documents
+   *
+   * @param key         element key
+   * @param constructor constructor of child class
+   * @return child documents
+   */
+  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
index b3dcaa77f..e29ee63da 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java
@@ -1,18 +1,38 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
 
-import java.util.HashMap;
 import java.util.Map;
 
 import com.iluwatar.abstractdocument.AbstractDocument;
 
+/**
+ * Car entity
+ */
 public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {
 
-	protected Car() {
-		super(new HashMap<>());
-	}
-	
-	protected Car(Map<String,Object> properties) {
-		super(properties);
-	}
+  public Car(Map<String, Object> properties) {
+    super(properties);
+  }
 
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
index 635f80abf..fbd8c0d7f 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java
@@ -1,13 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
 
 import java.util.Optional;
 
 import com.iluwatar.abstractdocument.Document;
 
+/**
+ * HasModel trait for static access to 'model' property
+ */
 public interface HasModel extends Document {
-	
-	default Optional<String> getModel() {
-		return Optional.ofNullable((String) get("model"));
-	}
+
+  String PROPERTY = "model";
+
+  default Optional<String> getModel() {
+    return Optional.ofNullable((String) get(PROPERTY));
+  }
 
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
index 92c7dc7d9..581702cc9 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java
@@ -1,13 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
 
 import java.util.stream.Stream;
 
 import com.iluwatar.abstractdocument.Document;
 
+/**
+ * HasParts trait for static access to 'parts' property
+ */
 public interface HasParts extends Document {
-	
-	default Stream<Part> getParts() {
-		return children("parts", Part::new);
-	}
+
+  String PROPERTY = "parts";
+
+  default Stream<Part> getParts() {
+    return children(PROPERTY, Part::new);
+  }
 
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
index 7c9e8e6a1..3d1d0e3e7 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java
@@ -1,13 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
 
 import java.util.Optional;
 
 import com.iluwatar.abstractdocument.Document;
 
+/**
+ * HasPrice trait for static access to 'price' property
+ */
 public interface HasPrice extends Document {
-	
-	default Optional<Number> getPartner() {
-		return Optional.ofNullable((Number) get("price"));
-	}
+
+  String PROPERTY = "price";
+
+  default Optional<Number> getPrice() {
+    return Optional.ofNullable((Number) get(PROPERTY));
+  }
 
 }
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java
new file mode 100644
index 000000000..b0f292bb6
--- /dev/null
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java
@@ -0,0 +1,40 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
+
+import com.iluwatar.abstractdocument.Document;
+
+import java.util.Optional;
+
+/**
+ * HasType trait for static access to 'type' property
+ */
+public interface HasType extends Document {
+
+  String PROPERTY = "type";
+
+  default Optional<String> getType() {
+    return Optional.ofNullable((String) get(PROPERTY));
+  }
+
+}
diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
index c6e1a3908..e42f099d9 100644
--- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
+++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java
@@ -1,18 +1,38 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument.domain;
 
-import java.util.HashMap;
 import java.util.Map;
 
 import com.iluwatar.abstractdocument.AbstractDocument;
 
-public class Part extends AbstractDocument implements HasModel, HasPrice {
+/**
+ * Part entity
+ */
+public class Part extends AbstractDocument implements HasType, HasModel, HasPrice {
 
-	protected Part() {
-		super(new HashMap<>());
-	}
-	
-	protected Part(Map<String, Object> properties) {
-		super(properties);
-	}
+  public Part(Map<String, Object> properties) {
+    super(properties);
+  }
 
 }
diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
index baf872e4f..b6467e232 100644
--- a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
+++ b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java
@@ -1,3 +1,25 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
 
 import org.junit.Test;
@@ -11,44 +33,56 @@ import java.util.stream.Stream;
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertNotNull;
 
+/**
+ * AbstractDocument test class
+ */
 public class AbstractDocumentTest {
 
-    private static final String KEY = "key";
-    private static final Object VALUE = "value";
+  private static final String KEY = "key";
+  private static final String VALUE = "value";
 
-    private class DocumentImplementation extends AbstractDocument {
+  private class DocumentImplementation extends AbstractDocument {
 
-        DocumentImplementation(Map<String, Object> properties) {
-            super(properties);
-        }
+    DocumentImplementation(Map<String, Object> properties) {
+      super(properties);
     }
+  }
 
-    private DocumentImplementation document = new DocumentImplementation(new HashMap<>());
+  private DocumentImplementation document = new DocumentImplementation(new HashMap<>());
 
-    @Test
-    public void shouldPutAndGetValue() {
-        document.put(KEY, VALUE);
-        assertEquals(VALUE, document.get(KEY));
-    }
+  @Test
+  public void shouldPutAndGetValue() {
+    document.put(KEY, VALUE);
+    assertEquals(VALUE, document.get(KEY));
+  }
 
-    @Test
-    public void shouldRetrieveChildren() {
-        Map<String,Object> child1 = new HashMap<>();
-        Map<String,Object> child2 = new HashMap<>();
-        List<Map<String, Object>> children = Arrays.asList(child1, child2);
+  @Test
+  public void shouldRetrieveChildren() {
+    Map<String, Object> child1 = new HashMap<>();
+    Map<String, Object> child2 = new HashMap<>();
+    List<Map<String, Object>> children = Arrays.asList(child1, child2);
 
-        document.put(KEY, children);
+    document.put(KEY, children);
 
-        Stream<DocumentImplementation> childrenStream = document.children(KEY, DocumentImplementation::new);
-        assertNotNull(children);
-        assertEquals(2, childrenStream.count());
-    }
+    Stream<DocumentImplementation> childrenStream = document.children(KEY, DocumentImplementation::new);
+    assertNotNull(children);
+    assertEquals(2, childrenStream.count());
+  }
 
-    @Test
-    public void shouldRetrieveEmptyStreamForNonExistinChildren() {
-        Stream<DocumentImplementation> children = document.children(KEY, DocumentImplementation::new);
-        assertNotNull(children);
-        assertEquals(0, children.count());
-    }
+  @Test
+  public void shouldRetrieveEmptyStreamForNonExistingChildren() {
+    Stream<DocumentImplementation> children = document.children(KEY, DocumentImplementation::new);
+    assertNotNull(children);
+    assertEquals(0, children.count());
+  }
+
+  @Test
+  public void shouldIncludePropsInToString() {
+    Map<String, Object> props = new HashMap<>();
+    props.put(KEY, VALUE);
+    DocumentImplementation document = new DocumentImplementation(props);
+    assertNotNull(document.toString().contains(KEY));
+    assertNotNull(document.toString().contains(VALUE));
+  }
 
 }
diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java
new file mode 100644
index 000000000..787ae3aa6
--- /dev/null
+++ b/abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java
@@ -0,0 +1,37 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
+
+import org.junit.Test;
+
+/**
+ * Simple App test
+ */
+public class AppTest {
+
+  @Test
+  public void shouldExecuteAppWithoutException() {
+    App.main(null);
+  }
+
+}
diff --git a/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java b/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java
new file mode 100644
index 000000000..437244a3d
--- /dev/null
+++ b/abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java
@@ -0,0 +1,77 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * <p>
+ * 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.abstractdocument;
+
+import com.iluwatar.abstractdocument.domain.Car;
+import com.iluwatar.abstractdocument.domain.HasModel;
+import com.iluwatar.abstractdocument.domain.HasParts;
+import com.iluwatar.abstractdocument.domain.HasPrice;
+import com.iluwatar.abstractdocument.domain.HasType;
+import com.iluwatar.abstractdocument.domain.Part;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Test for Part and Car
+ */
+public class DomainTest {
+
+  private static final String TEST_PART_TYPE = "test-part-type";
+  private static final String TEST_PART_MODEL = "test-part-model";
+  private static final long TEST_PART_PRICE = 0L;
+
+  private static final String TEST_CAR_MODEL = "test-car-model";
+  private static final long TEST_CAR_PRICE = 1L;
+
+  @Test
+  public void shouldConstructPart() {
+    Map<String, Object> partProperties = new HashMap<>();
+    partProperties.put(HasType.PROPERTY, TEST_PART_TYPE);
+    partProperties.put(HasModel.PROPERTY, TEST_PART_MODEL);
+    partProperties.put(HasPrice.PROPERTY, TEST_PART_PRICE);
+    Part part = new Part(partProperties);
+
+    assertEquals(TEST_PART_TYPE, part.getType().get());
+    assertEquals(TEST_PART_MODEL, part.getModel().get());
+    assertEquals(TEST_PART_PRICE, part.getPrice().get());
+  }
+
+  @Test
+  public void shouldConstructCar() {
+    Map<String, Object> carProperties = new HashMap<>();
+    carProperties.put(HasModel.PROPERTY, TEST_CAR_MODEL);
+    carProperties.put(HasPrice.PROPERTY, TEST_CAR_PRICE);
+    carProperties.put(HasParts.PROPERTY, Arrays.asList(new HashMap<>(), new HashMap<>()));
+    Car car = new Car(carProperties);
+
+    assertEquals(TEST_CAR_MODEL, car.getModel().get());
+    assertEquals(TEST_CAR_PRICE, car.getPrice().get());
+    assertEquals(2, car.getParts().count());
+  }
+
+}
diff --git a/pom.xml b/pom.xml
index 362519090..0e3318fb6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -124,7 +124,7 @@
 		<module>mute-idiom</module>
 		<module>mutex</module>
 		<module>semaphore</module>
-                <module>hexagonal</module>
+		<module>hexagonal</module>
 		<module>abstract-document</module>
 	</modules>