Skip to content

Commit

Permalink
lifecycle fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
coolsamson7 committed Sep 24, 2024
1 parent b1aec21 commit 92787f2
Show file tree
Hide file tree
Showing 17 changed files with 114 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/org/sirius/dorm/ObjectManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class ObjectManager() {
val descriptors = ConcurrentHashMap<String, ObjectDescriptor>()

@PersistenceContext
private lateinit var entityManager: EntityManager
lateinit var entityManager: EntityManager
@Autowired
private lateinit var transactionManager: PlatformTransactionManager
@Autowired
Expand Down Expand Up @@ -121,7 +121,7 @@ class ObjectManager() {
}

fun create(objectDescriptor: ObjectDescriptor) : DataObject {
return TransactionState.current().create(objectDescriptor.create())
return TransactionState.current().create(objectDescriptor.create(Status.CREATED))
}

fun delete(obj: DataObject) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/org/sirius/dorm/json/ObjectModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.module.SimpleDeserializers
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.module.SimpleSerializers
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import org.sirius.dorm.transaction.Status
import java.io.IOException
import java.util.concurrent.ConcurrentHashMap

Expand All @@ -29,7 +30,7 @@ class JSONReader(private val objectDescriptor: ObjectDescriptor) {
// public

fun read(node: JsonNode) : DataObject {
val obj = objectDescriptor.create()
val obj = objectDescriptor.create(Status.MANAGED)

for ( reader in readers)
reader(node, obj)
Expand Down
10 changes: 6 additions & 4 deletions src/main/kotlin/org/sirius/dorm/model/ObjectDescriptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package org.sirius.dorm.model
import org.sirius.dorm.`object`.DataObject
import org.sirius.dorm.ObjectManager
import org.sirius.dorm.`object`.Property
import org.sirius.dorm.transaction.ObjectState
import org.sirius.dorm.transaction.Status

class ObjectDescriptor(val name: String, val properties: Array<PropertyDescriptor<Any>>, var objectManager: ObjectManager? = null) {
// instance data
Expand All @@ -20,8 +22,8 @@ class ObjectDescriptor(val name: String, val properties: Array<PropertyDescripto

// public

fun createValues(obj: DataObject): Array<Property> {
return properties.map { property -> property.createProperty(obj, null) }.toTypedArray()
fun createValues(obj: DataObject, status: Status): Array<Property> {
return properties.map { property -> property.createProperty(obj, status, null) }.toTypedArray()
}

fun resolve(objectManager: ObjectManager) {
Expand All @@ -32,8 +34,8 @@ class ObjectDescriptor(val name: String, val properties: Array<PropertyDescripto
}
}

fun create() : DataObject {
return DataObject(this, null) // TODO
fun create(status: Status) : DataObject {
return DataObject(this, status, null) // TODO anders
}

fun property(property: String) : PropertyDescriptor<Any> {
Expand Down
11 changes: 7 additions & 4 deletions src/main/kotlin/org/sirius/dorm/model/PropertyDescriptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import org.sirius.dorm.*
import org.sirius.dorm.persistence.entity.PropertyEntity
import org.sirius.common.type.Type
import org.sirius.dorm.`object`.*
import org.sirius.dorm.transaction.Status

abstract class PropertyDescriptor<T:Any>(val name: String) {
var index = 0

abstract fun createProperty(obj: DataObject, entity: PropertyEntity?) : Property
abstract fun createProperty(obj: DataObject, status: Status, entity: PropertyEntity?) : Property

abstract fun defaultValue() : Any?

Expand Down Expand Up @@ -44,7 +45,7 @@ class AttributeDescriptor<T:Any>(name: String, val type: Type<T>, val isPrimaryK

// override

override fun createProperty(obj: DataObject, entity: PropertyEntity?) : Property {
override fun createProperty(obj: DataObject, status: Status, entity: PropertyEntity?) : Property {
return Attribute(entity, defaultValue()!!)
}

Expand Down Expand Up @@ -80,8 +81,10 @@ open class RelationDescriptor<T:Any>(name: String, val target: String, val multi

// override

override fun createProperty(obj: DataObject, entity: PropertyEntity?) : Property {
return if ( multiplicity.mutliValued ) MultiValuedRelation(this, obj, entity, targetDescriptor!!) else SingleValuedRelation(this, obj, entity, targetDescriptor!!)
override fun createProperty(obj: DataObject, status: Status, entity: PropertyEntity?) : Property {
val relation = if ( multiplicity.mutliValued ) MultiValuedRelation(this, status, obj, entity, targetDescriptor!!) else SingleValuedRelation(this, status, obj, entity, targetDescriptor!!)

return relation
}

override fun resolve(objectManager: ObjectManager, descriptor: ObjectDescriptor) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/org/sirius/dorm/object/DataObject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import org.sirius.dorm.model.ObjectDescriptor
import org.sirius.dorm.model.PropertyDescriptor
import org.sirius.dorm.persistence.entity.EntityEntity
import org.sirius.dorm.transaction.ObjectState
import org.sirius.dorm.transaction.Status


class DataObject(val type: ObjectDescriptor, var state : ObjectState?) {
class DataObject(val type: ObjectDescriptor, status: Status, var state : ObjectState?) {
// instance data

var entity: EntityEntity? = null
val values = type.createValues(this)
val values = type.createValues(this, status)

// public

Expand Down Expand Up @@ -81,6 +82,6 @@ class DataObject(val type: ObjectDescriptor, var state : ObjectState?) {
}

companion object {
val NONE = DataObject(ObjectDescriptor("none", arrayOf()), null)
val NONE = DataObject(ObjectDescriptor("none", arrayOf()), Status.CREATED, null)
}
}
14 changes: 8 additions & 6 deletions src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ import org.sirius.dorm.model.ObjectDescriptor
import org.sirius.dorm.model.PropertyDescriptor
import org.sirius.dorm.model.RelationDescriptor
import org.sirius.dorm.persistence.entity.PropertyEntity
import org.sirius.dorm.transaction.Status
import org.sirius.dorm.transaction.TransactionState
import java.util.HashMap

class MultiValuedRelation(relation: RelationDescriptor<*>, val obj: DataObject, property: PropertyEntity?, targetDescriptor: ObjectDescriptor) : Relation(relation, targetDescriptor, property), MutableSet<DataObject> {
class MultiValuedRelation(relation: RelationDescriptor<*>, status: Status, val obj: DataObject, property: PropertyEntity?, targetDescriptor: ObjectDescriptor) : Relation(relation, targetDescriptor, property), MutableSet<DataObject> {
// instance data

private var objects : HashSet<DataObject>? = null
private var objects : HashSet<DataObject>? = if ( status == Status.CREATED) HashSet() else null

// private

private fun load(objectManager: ObjectManager) {
override fun load(objectManager: ObjectManager) {
objects = HashSet()
for ( target in relations() ) {
objects!!.add(objectManager.mapper.read(TransactionState.current(), targetDescriptor, target.entity))
}
if ( property !== null)
for ( target in relations() ) {
objects!!.add(objectManager.mapper.read(TransactionState.current(), targetDescriptor, target.entity))
}
}

private fun markDirty() {
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/org/sirius/dorm/object/Relation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ package org.sirius.dorm.`object`
* All rights reserved
*/

import org.sirius.dorm.ObjectManager
import org.sirius.dorm.model.ObjectDescriptor
import org.sirius.dorm.model.RelationDescriptor
import org.sirius.dorm.persistence.entity.PropertyEntity

abstract class Relation(val relation: RelationDescriptor<*>, val targetDescriptor: ObjectDescriptor, property: PropertyEntity?) : Property(property) {
abstract fun isLoaded(): Boolean

abstract fun load(objectManager: ObjectManager)

override fun save(): Any {
return this
}
Expand Down
32 changes: 21 additions & 11 deletions src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,32 @@ package org.sirius.dorm.`object`
*/

import org.sirius.dorm.ObjectManager
import org.sirius.dorm.ObjectManagerError
import org.sirius.dorm.model.ObjectDescriptor
import org.sirius.dorm.model.PropertyDescriptor
import org.sirius.dorm.model.RelationDescriptor
import org.sirius.dorm.persistence.entity.PropertyEntity
import org.sirius.dorm.transaction.Status
import org.sirius.dorm.transaction.TransactionState

class SingleValuedRelation(relation: RelationDescriptor<*>, val obj: DataObject, property: PropertyEntity?, targetDescriptor: ObjectDescriptor) : Relation(relation, targetDescriptor, property) {
class SingleValuedRelation(relation: RelationDescriptor<*>, status: Status, val obj: DataObject, property: PropertyEntity?, targetDescriptor: ObjectDescriptor) : Relation(relation, targetDescriptor, property) {
// instance data

var target: DataObject? = DataObject.NONE
var target: DataObject? = if ( status == Status.CREATED ) null else DataObject.NONE

// private

override fun load(objectManager: ObjectManager) {
if ( property !== null) {
if ( relations().size == 1) {
val targetProperty = relations().first()
target = objectManager.mapper.read(TransactionState.current(), targetDescriptor, targetProperty.entity)
}
else
target = null
}
else target = null
}

// implement Relation

Expand All @@ -33,19 +49,13 @@ class SingleValuedRelation(relation: RelationDescriptor<*>, val obj: DataObject,
}
else {
if ( !relation.multiplicity.optional)
throw Error("missing ...") // TODO
throw ObjectManagerError("relation ${obj.type.name}.${relation.name} is required")
}
}
}
override fun get(objectManager: ObjectManager) : Any? {
if ( !isLoaded() && property !== null) {
if ( relations().size == 1) {
val targetProperty = relations().first()
target = objectManager.mapper.read(TransactionState.current(), targetDescriptor, targetProperty.entity)
}
else
target = null
}
if ( !isLoaded())
load(objectManager)

return target
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.sirius.common.tracer.Tracer
import org.sirius.dorm.`object`.DataObject
import jakarta.persistence.EntityManager
import jakarta.persistence.PersistenceContext
import org.sirius.dorm.transaction.Status
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.util.concurrent.ConcurrentHashMap
Expand Down Expand Up @@ -58,9 +59,9 @@ class DataObjectMapper() {
fun create(state: TransactionState, obj: DataObject) {
val descriptor = obj.type

obj.entity = EntityEntity(0, descriptor.name, mapper.writeValueAsString(obj))
//obj.entity = EntityEntity(0, descriptor.name, mapper.writeValueAsString(obj))

entityManager.persist(obj.entity) // we need the id...is that required, think of a lifecycle hook?
//entityManager.persist(obj.entity) // we need the id...is that required, think of a lifecycle hook?

if ( Tracer.ENABLED)
Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "create %s[%d]", obj.type.name, obj.entity!!.id)
Expand Down Expand Up @@ -94,7 +95,7 @@ class DataObjectMapper() {
if ( Tracer.ENABLED)
Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "read %s", objectDescriptor.name)

val obj = objectDescriptor.create()
val obj = objectDescriptor.create(Status.MANAGED)

val id = entity.id
obj.entity = entity
Expand All @@ -116,7 +117,7 @@ class DataObjectMapper() {
if ( Tracer.ENABLED)
Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "read %s[%d]", objectDescriptor.name, attributes[start].entity.id)

val obj = objectDescriptor.create()
val obj = objectDescriptor.create(Status.MANAGED)

obj.entity = attributes[start].entity
val id = obj.entity!!.id
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/org/sirius/dorm/persistence/ObjectWriter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class ObjectWriter(private val descriptor: ObjectDescriptor) {
writer(state, obj, i++, attribute)

entityManager.persist(attribute)

//obj.entity!!.properties.add(attribute)
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.sirius.dorm.`object`.DataObject
import org.sirius.dorm.ObjectManager
import org.sirius.dorm.model.ObjectDescriptor
import org.sirius.dorm.persistence.DataObjectMapper
import org.sirius.dorm.persistence.entity.EntityEntity
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.TransactionDefinition
import org.springframework.transaction.TransactionStatus
Expand Down Expand Up @@ -94,11 +95,17 @@ class TransactionState(val objectManager: ObjectManager, val transactionManager:
}

fun create(obj: DataObject) : DataObject{
val state = ObjectState(obj, Status.MANAGED) // as soon as it is flushed it will be managed TODO ID
val state = ObjectState(obj, Status.CREATED)

obj.entity = EntityEntity(0, obj.type.name, "{}", ArrayList())

this.objectManager.entityManager.persist(obj.entity)

obj["id"] = obj.entity!!.id

// force flush

objectManager.mapper.create(this, obj)
//objectManager.mapper.create(this, obj)

states.put(obj.id, state)

Expand Down
12 changes: 7 additions & 5 deletions src/test/kotlin/org/sirius/dorm/AbstractTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class AbstractTest {
withTransaction {
if ( objectManager.findDescriptor("person") == null) {
val stringType = string().length(100)
val intType = int()
val intType = int().greaterEqual(0)

objectManager.type("person")
.attribute("name", stringType)
Expand Down Expand Up @@ -136,13 +136,15 @@ class AbstractTest {
return query.execute().getResultList()
}

protected fun createPerson(name: String, age: Int) {
protected fun createPerson(name: String, age: Int) : Int{
objectManager.begin()
try {
val person1 = objectManager.create(personDescriptor!!)
val person = objectManager.create(personDescriptor!!)

person1["name"] = name
person1["age"] = age
person["name"] = name
person["age"] = age

return person.id
}
finally {
objectManager.commit()
Expand Down
32 changes: 29 additions & 3 deletions src/test/kotlin/org/sirius/dorm/CreateUpdateDeleteTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,45 @@ package org.sirius.dorm
*/

import org.junit.jupiter.api.Test
import org.sirius.common.type.ValidationError
import kotlin.test.assertEquals


class CreateUpdateDeleteTests: AbstractTest() {
@Test
fun testOne() {
createPerson("Andi", 58)
val id = createPerson("Andi", 58)

withTransaction {
val person = objectManager.findById(personDescriptor!!, id)!!

assertEquals("Andi", person["name"])
assertEquals(58, person["age"])
}
}

@Test
fun testValidation() {
var caughtError = false
try {
withTransaction {
val person = objectManager.create(personDescriptor!!)

person["name"] = "Andi"
person["age"] = -1
}
}
catch(e: ValidationError) {
caughtError = true
}

assertEquals(true, caughtError)
}

@Test
fun testCreate() {
createPerson("Andi", 58)
createPerson("Sandra", 52)
val andiId = createPerson("Andi", 58)
val sandraId = createPerson("Sandra", 52)

// update

Expand Down
Loading

0 comments on commit 92787f2

Please sign in to comment.