diff --git a/Jenkinsfile b/Jenkinsfile
index edb4c78..c84279b 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -17,7 +17,7 @@ node {
sh "mvn -B clean install"
stage 'Deploy'
- sh "mvn -s ${env.HOME}/usethesource-maven-settings.xml -B deploy"
+ sh "mvn -s ${env.HOME}/usethesource-maven-settings.xml -B deploy -DskipTests"
stage 'Archive'
step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true])
diff --git a/capsule-core/capsule-core.iml b/capsule-core/capsule-core.iml
new file mode 100644
index 0000000..e2b85dc
--- /dev/null
+++ b/capsule-core/capsule-core.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/capsule-core/pom.xml b/capsule-core/pom.xml
new file mode 100644
index 0000000..81af585
--- /dev/null
+++ b/capsule-core/pom.xml
@@ -0,0 +1,21 @@
+
+ 4.0.0
+
+
+ io.usethesource
+ capsule-pom-parent
+ 0.3.0.HETEROGENEOUS-SNAPSHOT
+
+
+ io.usethesource
+ capsule
+ 0.3.0.HETEROGENEOUS-SNAPSHOT
+ jar
+
+
+ ${project.parent.basedir}
+
+
+
\ No newline at end of file
diff --git a/capsule-core/src/main/java/io/usethesource/capsule/BinaryRelation.java b/capsule-core/src/main/java/io/usethesource/capsule/BinaryRelation.java
new file mode 100644
index 0000000..e65b952
--- /dev/null
+++ b/capsule-core/src/main/java/io/usethesource/capsule/BinaryRelation.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) Michael Steindorfer and Contributors.
+ * All rights reserved.
+ *
+ * This file is licensed under the BSD 2-Clause License, which accompanies this project
+ * and is available under https://opensource.org/licenses/BSD-2-Clause.
+ */
+package io.usethesource.capsule;
+
+public interface BinaryRelation extends SetMultimap {
+
+ BinaryRelation inverse();
+
+ SetMultimap toSetMultimap();
+
+ interface Immutable extends BinaryRelation, SetMultimap.Immutable {
+
+ @Override
+ boolean isTransientSupported();
+
+ @Override
+ BinaryRelation.Transient asTransient();
+
+ }
+
+ interface Transient extends BinaryRelation, SetMultimap.Transient {
+
+ @Override
+ BinaryRelation.Immutable freeze();
+
+ }
+
+}
diff --git a/capsule-core/src/main/java/io/usethesource/capsule/Map.java b/capsule-core/src/main/java/io/usethesource/capsule/Map.java
new file mode 100644
index 0000000..69e3db3
--- /dev/null
+++ b/capsule-core/src/main/java/io/usethesource/capsule/Map.java
@@ -0,0 +1,167 @@
+/**
+ * Copyright (c) Michael Steindorfer and Contributors.
+ * All rights reserved.
+ *
+ * This file is licensed under the BSD 2-Clause License, which accompanies this project
+ * and is available under https://opensource.org/licenses/BSD-2-Clause.
+ */
+package io.usethesource.capsule;
+
+import java.util.Iterator;
+
+import io.usethesource.capsule.core.PersistentTrieMap;
+
+public interface Map extends java.util.Map, MapEq {
+
+ @Override
+ int size();
+
+ @Override
+ boolean isEmpty();
+
+ @Override
+ boolean containsKey(final Object o);
+
+ @Override
+ boolean containsValue(final Object o);
+
+ @Override
+ V get(final Object o);
+
+ Iterator keyIterator();
+
+ Iterator valueIterator();
+
+ Iterator> entryIterator();
+
+ interface Immutable extends Map, MapEq.Immutable {
+
+ Map.Immutable __put(final K key, final V val);
+
+ Map.Immutable __remove(final K key);
+
+ Map.Immutable __putAll(final java.util.Map extends K, ? extends V> map);
+
+ boolean isTransientSupported();
+
+ Map.Transient asTransient();
+
+ static Map.Immutable of() {
+ return PersistentTrieMap.of();
+ }
+
+ static Map.Immutable of(K key, V value) {
+ return PersistentTrieMap.of(key, value);
+ }
+
+ static Map.Immutable of(K key0, V value0, K key1, V value1) {
+ return PersistentTrieMap.of(key0, value0, key1, value1);
+ }
+
+ }
+
+ interface Transient extends Map, MapEq.Transient {
+
+ V __put(final K key, final V val);
+
+ V __remove(final K key);
+
+ boolean __putAll(final java.util.Map extends K, ? extends V> map);
+
+// default boolean union(final Map extends K, ? extends V> map) {
+// boolean modified = false;
+//
+// for (java.util.Map.Entry extends K, ? extends V> entry : map.entrySet()) {
+// // NOTE: does only work when map does not support `null` values
+// if (this.__put(entry.getKey(), entry.getValue()) != null) {
+// modified |= true;
+// }
+// }
+//
+// return modified;
+// }
+//
+// default boolean intersect(final Map extends K, ? extends V> map) {
+// throw new UnsupportedOperationException("Not yet implemented @ Map.");
+// }
+//
+// default boolean complement(final Map extends K, ? extends V> map) {
+// throw new UnsupportedOperationException("Not yet implemented @ Map");
+// }
+
+ Map.Immutable freeze();
+
+ static Map.Transient of() {
+ return PersistentTrieMap.transientOf();
+ }
+
+ static Map.Transient of(K key0, V value0) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+
+ return tmp;
+ }
+
+ static Map.Transient of(K key0, V value0, K key1, V value1) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+ tmp.__put(key1, value1);
+
+ return tmp;
+ }
+
+ static Map.Transient of(K key0, V value0, K key1, V value1, K key2,
+ V value2) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+ tmp.__put(key1, value1);
+ tmp.__put(key2, value2);
+
+ return tmp;
+ }
+
+ static Map.Transient of(K key0, V value0, K key1, V value1, K key2,
+ V value2, K key3, V value3) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+ tmp.__put(key1, value1);
+ tmp.__put(key2, value2);
+ tmp.__put(key3, value3);
+
+ return tmp;
+ }
+
+ static Map.Transient of(K key0, V value0, K key1, V value1, K key2,
+ V value2, K key3, V value3, K key4, V value4) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+ tmp.__put(key1, value1);
+ tmp.__put(key2, value2);
+ tmp.__put(key3, value3);
+ tmp.__put(key4, value4);
+
+ return tmp;
+ }
+
+ static Map.Transient of(K key0, V value0, K key1, V value1, K key2,
+ V value2, K key3, V value3, K key4, V value4, K key5, V value5) {
+ final Map.Transient tmp = Map.Transient.of();
+
+ tmp.__put(key0, value0);
+ tmp.__put(key1, value1);
+ tmp.__put(key2, value2);
+ tmp.__put(key3, value3);
+ tmp.__put(key4, value4);
+ tmp.__put(key5, value5);
+
+ return tmp;
+ }
+
+ }
+
+}
diff --git a/capsule-core/src/main/java/io/usethesource/capsule/MapEq.java b/capsule-core/src/main/java/io/usethesource/capsule/MapEq.java
new file mode 100644
index 0000000..c9974ce
--- /dev/null
+++ b/capsule-core/src/main/java/io/usethesource/capsule/MapEq.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) Michael Steindorfer and Contributors.
+ * All rights reserved.
+ *
+ * This file is licensed under the BSD 2-Clause License, which accompanies this project
+ * and is available under https://opensource.org/licenses/BSD-2-Clause.
+ */
+package io.usethesource.capsule;
+
+import java.util.Comparator;
+
+/**
+ * Map extension providing methods that take a comparator. Closes over base (and not extended) map.
+ */
+@Deprecated
+public interface MapEq extends java.util.Map {
+
+ default boolean containsKeyEquivalent(final Object o, final Comparator