diff --git a/kmolecules-ddd/pom.xml b/kmolecules-ddd/pom.xml
new file mode 100644
index 0000000..f422939
--- /dev/null
+++ b/kmolecules-ddd/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+
+ org.jmolecules
+ jmolecules
+ 1.5.0-SNAPSHOT
+
+
+ kmolecules-ddd
+
+ kMolecules - DDD
+ Kotlin flavor of jMolecules DDD
+
+
+ org.kmolecules.ddd
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ ${kotlin.version}
+
+
+
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+
+ compile
+
+ compile
+
+
+
+
+ test-compile
+
+ test-compile
+
+
+
+
+
+
+
+
+
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/AggregateRoot.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/AggregateRoot.kt
new file mode 100644
index 0000000..724182e
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/AggregateRoot.kt
@@ -0,0 +1,22 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies an aggregate root, i.e. the root entity of an aggregate. An aggregate forms a cluster of consistent rules
+ * usually formed around a set of entities by defining invariants based on the properties of the aggregate that have to
+ * be met before and after operations on it. Aggregates usually refer to other aggregates by their identifier.
+ * References to aggregate internals should be avoided and at least not considered strongly consistent (i.e. a reference
+ * held could possibly have been gone or become invalid at any point in time). They also act as scope of consistency,
+ * i.e. changes on a single aggregate are expected to be strongly consistent while changes across multiple ones should
+ * only expect eventual consistency.
+ *
+ * Kotlin's counterpart of the Java's [AggregateRoot](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/AggregateRoot.java)
+ *
+ * @author Jocelyn Ntakpe
+ *
+ * See also : [Domain-Driven Design Reference (Evans) - Aggregates](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+@Entity
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class AggregateRoot
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Entity.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Entity.kt
new file mode 100644
index 0000000..d2dbd89
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Entity.kt
@@ -0,0 +1,18 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies an [Entity]. Entities represent a thread of continuity and identity, going through a lifecycle,
+ * though their attributes may change. Means of identification may come from the outside, or it may be an arbitrary
+ * identifier created by and for the system, but it must correspond to the identity distinctions in the model. The model
+ * must define what it means to be the same thing.
+ *
+ * Kotlin's counterpart of the Java's [Entity](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/Entity.java)
+ *
+ * @author Jocelyn Ntakpe
+ *
+ * See also : [Domain-Driven Design Reference (Evans) - Entities](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class Entity
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Factory.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Factory.kt
new file mode 100644
index 0000000..c9c1274
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Factory.kt
@@ -0,0 +1,17 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies a [Factory]. Factories encapsulate the responsibility of creating complex objects in general and
+ * Aggregates in particular. Objects returned by the factory methods are guaranteed to be in valid state.
+ *
+ * Kotlin's counterpart of the Java's [Factory](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/Factory.java)
+ *
+ * @author Jocelyn Ntakpe
+ *
+ * See also : [AggregateRoot]
+ * See also : [Domain-Driven Design Reference (Evans) - Factories](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class Factory
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Repository.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Repository.kt
new file mode 100644
index 0000000..3bea7a6
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Repository.kt
@@ -0,0 +1,21 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies a [Repository]. Repositories simulate a collection of aggregates to which aggregate instances can be
+ * added and removed. They usually also expose API to select a subset of aggregates matching certain criteria. Access to
+ * projections of an aggregate might be provided as well but also via a dedicated separate abstraction.
+ *
+ * Implementations use a dedicated persistence mechanism appropriate to the data structure and query requirements at
+ * hand. However, they should make sure that no persistence mechanism specific APIs leak into client code.
+ *
+ * Kotlin's counterpart of the Java's [Repository](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/Repository.java)
+ *
+ * @author Jocelyn Ntakpe
+ *
+ * See also : [AggregateRoot]
+ * See also : [Domain-Driven Design Reference (Evans) - Repositories](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class Repository
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Service.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Service.kt
new file mode 100644
index 0000000..f69e590
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/Service.kt
@@ -0,0 +1,17 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies a domain [Service]. A service is a significant process or transformation in the domain that is not a
+ * natural responsibility of an entity or value object, add an operation to the model as a standalone interface declared
+ * as a service. Define a service contract, a set of assertions about interactions with the service. (See assertions.)
+ * State these assertions in the ubiquitous language of a specific bounded context. Give the service a name, which also
+ * becomes part of the ubiquitous language.
+ *
+ * Kotlin's counterpart of the Java's [Service](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/Service.java)
+ *
+ * @author Jocelyn Ntakpe
+ */
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class Service
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/ValueObject.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/ValueObject.kt
new file mode 100644
index 0000000..b6f1840
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/annotation/ValueObject.kt
@@ -0,0 +1,16 @@
+package org.jmolecules.ddd.annotation
+
+/**
+ * Identifies a value object. Domain concepts that are modeled as value objects have no conceptual identity or
+ * lifecycle. Implementations should be immutable, operations on it are side effect free.
+ *
+ * Kotlin's counterpart of the Java's [ValueObject](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/annotation/ValueObject.java)
+ *
+ * @author Jocelyn Ntakpe
+ *
+ * See also : [Domain-Driven Design Reference (Evans) - Value objects](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+@Retention
+@MustBeDocumented
+@Target(AnnotationTarget.CLASS)
+annotation class ValueObject
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/AggregateRoot.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/AggregateRoot.kt
new file mode 100644
index 0000000..127c9b4
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/AggregateRoot.kt
@@ -0,0 +1,20 @@
+package org.jmolecules.ddd.types
+
+/**
+ * Identifies an aggregate root, i.e. the root entity of an aggregate. An aggregate forms a cluster of consistent rules
+ * usually formed around a set of entities by defining invariants based on the properties of the aggregate that have to
+ * be met before and after operations on it. Aggregates usually refer to other aggregates by their identifier.
+ * References to aggregate internals should be avoided and at least not considered strongly consistent (i.e. a reference
+ * held could possibly have been gone or become invalid at any point in time). They also act as scope of consistency,
+ * i.e. changes on a single aggregate are expected to be strongly consistent while changes across multiple ones should
+ * only expect eventual consistency.
+ *
+ * Kotlin's counterpart of Java's [AggregateRoot](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/AggregateRoot.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ *
+ * See also: [Domain-Driven Design Reference (Evans) - Aggregates](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ * See also: [John Sullivan - Advancing Enterprise DDD - Reinstating the Aggregate](https://scabl.blogspot.com/2015/04/aeddd-9.html)
+ */
+interface AggregateRoot, ID : Identifier> : Entity
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Association.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Association.kt
new file mode 100644
index 0000000..ab1b171
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Association.kt
@@ -0,0 +1,55 @@
+package org.jmolecules.ddd.types
+
+/**
+ * An association to an [AggregateRoot].
+ *
+ * Kotlin's counterpart of Java's [Association](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Association.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ * See also: [John Sullivan - Advancing Enterprise DDD - Reinstating the Aggregate](https://scabl.blogspot.com/2015/04/aeddd-9.html)
+ */
+interface Association, ID : Identifier> : Identifiable {
+
+ companion object {
+
+ /**
+ * Creates an [Association] pointing to the [Identifier] of the given [AggregateRoot].
+ *
+ * @param T the concrete [AggregateRoot] type.
+ * @param ID the concrete [Identifier] type.
+ * @param aggregate used to create the association
+ * @return an [Association] pointing to the [Identifier] of the given [AggregateRoot].
+ * @since 1.3
+ */
+ @JvmStatic
+ fun , ID : Identifier> forAggregate(aggregate: T): Association {
+ return SimpleAssociation { aggregate.id }
+ }
+
+ /**
+ * Creates an [Association] pointing to the given [Identifier].
+ *
+ * @param T the concrete [AggregateRoot] type.
+ * @param ID the concrete [Identifier] type.
+ * @param identifier used to create the association
+ * @return an [Association] pointing to the given [Identifier].
+ * @since 1.3
+ */
+ @JvmStatic
+ fun , ID : Identifier> forId(identifier: ID): Association {
+ return SimpleAssociation { identifier }
+ }
+ }
+
+ /**
+ * Returns whether the current [Association] points to the same [AggregateRoot] as the given one. Unlike
+ * [equals] and [hashCode] that also check for type equality of the [Association]
+ * itself, this only compares the target [Identifier] instances.
+ *
+ * @param other association compared with the current instance
+ * @return whether the current [Association] points to the same [AggregateRoot] as the given one.
+ * @since 1.3
+ */
+ fun pointsToSameAggregateAs(other: Association<*, ID>): Boolean = id == other.id
+}
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Entity.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Entity.kt
new file mode 100644
index 0000000..fd8056a
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Entity.kt
@@ -0,0 +1,17 @@
+package org.jmolecules.ddd.types
+
+/**
+ * Identifies an [Entity]. Entities represent a thread of continuity and identity, going through a lifecycle,
+ * though their attributes may change. Means of identification may come from the outside, or it may be an arbitrary
+ * identifier created by and for the system, but it must correspond to the identity distinctions in the model. The model
+ * must define what it means to be the same thing.
+ *
+ * Kotlin's counterpart of Java's [Entity](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Entity.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ *
+ * See also: [Domain-Driven Design Reference (Evans) - Entities](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ * See also: [John Sullivan - Advancing Enterprise DDD - Reinstating the Aggregate](https://scabl.blogspot.com/2015/04/aeddd-9.html)
+ */
+interface Entity, ID> : Identifiable
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifiable.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifiable.kt
new file mode 100644
index 0000000..28392bc
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifiable.kt
@@ -0,0 +1,17 @@
+package org.jmolecules.ddd.types
+
+/**
+ * An identifiable type, i.e. anything that exposes an [Identifier].
+ *
+ * Kotlin's counterpart of Java's [Identifiable](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Identifiable.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ */
+interface Identifiable {
+
+ /**
+ * Identifier
+ */
+ val id: ID
+}
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifier.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifier.kt
new file mode 100644
index 0000000..5ede48e
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Identifier.kt
@@ -0,0 +1,13 @@
+package org.jmolecules.ddd.types
+
+/**
+ * Marker interface for identifiers. Exists primarily to easily identify types that are supposed to be identifiers
+ * within the code base and let the compiler verify the correctness of declared relationships.
+ *
+ * Kotlin's counterpart of Java's [Identifier](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Identifier.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ * @see Identifiable
+ */
+interface Identifier
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Repository.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Repository.kt
new file mode 100644
index 0000000..53d5570
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/Repository.kt
@@ -0,0 +1,19 @@
+package org.jmolecules.ddd.types
+
+/**
+ * Identifies a [Repository]. Repositories simulate a collection of aggregates to which aggregate instances can be
+ * added and removed. They usually also expose API to select a subset of aggregates matching certain criteria. Access to
+ * projections of an aggregate might be provided as well but also via a dedicated separate abstraction.
+ *
+ * Implementations use a dedicated persistence mechanism appropriate to the data structure and query requirements at
+ * hand. However, they should make sure that no persistence mechanism specific APIs leak into client code.
+ *
+ * Kotlin's counterpart of Java's [Repository](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Repository.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ * @see [AggregateRoot]
+ *
+ * See also: [Domain-Driven Design Reference (Evans) - Repositories](https://domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf)
+ */
+interface Repository, ID : Identifier>
diff --git a/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/SimpleAssociation.kt b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/SimpleAssociation.kt
new file mode 100644
index 0000000..2ef48df
--- /dev/null
+++ b/kmolecules-ddd/src/main/kotlin/org/jmolecules/ddd/types/SimpleAssociation.kt
@@ -0,0 +1,34 @@
+package org.jmolecules.ddd.types
+
+/**
+ * Simple implementation of [Association] to effectively only define [equals] and
+ * [hashCode] on [Association]'s static factory methods.
+ *
+ * Kotlin's equivalent of Java's [SimpleAssociation](https://github.com/xmolecules/jmolecules/blob/main/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/SimpleAssociation.java)
+ *
+ * @author Jocelyn Ntakpe
+ * @since 1.0
+ * @see Association.forId
+ * @see Association.forAggregate
+ */
+class SimpleAssociation, ID : Identifier>(private val identifier: () -> ID) :
+ Association {
+
+ override val id: ID
+ get() = identifier()
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as SimpleAssociation<*, *>
+
+ if (id != other.id) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int = id.hashCode()
+
+ override fun toString(): String = id.toString()
+}
diff --git a/kmolecules-ddd/src/test/kotlin/org/jmolecules/ddd/types/AssociationTest.kt b/kmolecules-ddd/src/test/kotlin/org/jmolecules/ddd/types/AssociationTest.kt
new file mode 100644
index 0000000..1bda92e
--- /dev/null
+++ b/kmolecules-ddd/src/test/kotlin/org/jmolecules/ddd/types/AssociationTest.kt
@@ -0,0 +1,56 @@
+package org.jmolecules.ddd.types
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+/**
+ * Unit tests for [Association]
+ *
+ * @author Jocelyn Ntakpe
+ */
+internal class AssociationTest {
+
+ @Test
+ fun `creates association from identifier`() {
+ val id = SampleIdentifier()
+ assertThat(Association.forId(id).id).isEqualTo(id)
+ }
+
+ @Test
+ fun `creates association from aggregate`() {
+ val id = SampleIdentifier()
+ val aggregate = SampleAggregate(id)
+ assertThat(Association.forAggregate(aggregate).id).isEqualTo(id)
+ }
+
+ @Test
+ fun `associations equal if they point to the same id`() {
+ val id = SampleIdentifier()
+ val aggregate = SampleAggregate(id)
+ assertThat(Association.forId(id)).isEqualTo(
+ Association.forAggregate(
+ aggregate
+ )
+ )
+ assertThat(Association.forAggregate(aggregate)).isEqualTo(
+ Association.forId(
+ id
+ )
+ )
+ }
+
+ @Test
+ fun `points to same aggregate`() {
+ val id = SampleIdentifier()
+ val simpleAssociation: Association = Association.forId(id)
+ val sampleAssociation = SampleAssociation(id)
+ assertThat(simpleAssociation.pointsToSameAggregateAs(sampleAssociation)).isTrue
+ assertThat(sampleAssociation.pointsToSameAggregateAs(simpleAssociation)).isTrue
+ }
+
+ class SampleIdentifier : Identifier
+
+ class SampleAggregate(override val id: SampleIdentifier) : AggregateRoot
+
+ class SampleAssociation(override val id: SampleIdentifier) : Association
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 98e3ae6..812dbce 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,12 +15,14 @@
jmolecules-ddd
jmolecules-events
jmolecules-architecture
+ kmolecules-ddd
UTF-8
3.20.2
5.7.2
+ 1.6.21