Skip to content

Commit

Permalink
Add length of key to reference definitions. This makes the references…
Browse files Browse the repository at this point in the history
… more safe with complex model structures and migrations.
  • Loading branch information
jurmous committed Feb 18, 2024
1 parent 378d20b commit d5cf02c
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,12 @@ class ReferenceDefinition<DM : IsRootDataModel>(
default: Key<DM>? = null,
dataModel: Unit.() -> DM
) : this(required, final, unique, minValue, maxValue, default, dataModelReference = {
val dm = dataModel(Unit)
DataModelReference(dm.Meta.name) { dm } }
)
DataModelReference(dataModel(Unit))
})

override val propertyDefinitionType = PropertyDefinitionType.Reference
override val wireType = LENGTH_DELIMITED
override val byteSize get() = dataModel.Meta.keyByteSize
override val byteSize get() = internalDataModelReference.keyLength ?: dataModel.Meta.keyByteSize

override val internalDataModelReference by lazy {
dataModelReference.invoke()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ data class ContextualModelReferenceDefinition<DM : IsDataModel, in CX : IsProper
override val final = true
override val wireType = LENGTH_DELIMITED

override fun asString(value: IsDataModelReference<DM>, context: CX?) =
value.name
override fun asString(value: IsDataModelReference<DM>, context: CX?): String {
return value.name.let {
if (value.keyLength != null) {
"$it(${value.keyLength})"
} else {
it
}
}
}

override fun fromString(string: String, context: CX?) =
resolveContext(contextTransformer(Unit, context), string)
Expand Down Expand Up @@ -77,11 +84,19 @@ data class ContextualModelReferenceDefinition<DM : IsDataModel, in CX : IsProper
resolveContext(contextTransformer(Unit, context), initString(length, reader))

private fun resolveContext(context: CXI?, name: String): IsDataModelReference<DM> {
// read and remove keyLength from name
val value = name.split("(")
val keyLength = if (value.size > 1) {
value[1].removeSuffix(")").toInt()
} else {
null
}
val onlyName = value[0]
try {
return this.contextualResolver(Unit, context, name)
return this.contextualResolver(Unit, context, onlyName)
} catch (e: DefNotFoundException) {
return LazyDataModelReference(name) {
this.contextualResolver(Unit, context, name).also {
return LazyDataModelReference(onlyName, keyLength) {
this.contextualResolver(Unit, context, onlyName).also {
if (it is LazyDataModelReference<*>) {
throw DefNotFoundException("Could not resolve DataModel $name, was it processed before or provided in dependents in the context?")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ import maryk.core.models.IsValuesDataModel

interface IsDataModelReference<DM : IsDataModel> {
val name: String
val keyLength: Int?
val get: Unit.() -> DM
}

/** Reference to a ObjectDataModel */
class DataModelReference<DM : IsDataModel>(
override val name: String,
override val keyLength: Int? = null,
override val get: Unit.() -> DM
) : IsDataModelReference<DM> {

constructor(dataModel: DM) : this((dataModel as? IsStorableDataModel<*>)?.Meta?.name ?: dataModel::class.simpleName!!, { dataModel })
constructor(dataModel: DM) : this(
name = (dataModel as? IsStorableDataModel<*>)?.Meta?.name ?: dataModel::class.simpleName!!,
keyLength = (dataModel as? IsRootDataModel)?.Meta?.keyByteSize,
get = { dataModel }
)

override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand All @@ -37,7 +43,8 @@ class DataModelReference<DM : IsDataModel>(
/** Lazy reference to a ObjectDataModel */
class LazyDataModelReference<DM : IsDataModel>(
override val name: String,
getLater: () -> Unit.() -> DM
override val keyLength: Int?,
getLater: () -> Unit.() -> DM,
) : IsDataModelReference<DM> {
private val internal = lazy(getLater)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ class DefinitionsTest {
required: false
final: false
unique: false
dataModel: TestMarykModel
dataModel: TestMarykModel(7)
? 15: listOfString
: !List
required: false
Expand All @@ -324,7 +324,7 @@ class DefinitionsTest {
required: false
final: false
unique: false
dataModel: TestMarykModel
dataModel: TestMarykModel(7)
? 17: setOfString
: !Set
required: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ internal class RootDataModelTest {
"required": false,
"final": false,
"unique": false,
"dataModel": "TestMarykModel"
"dataModel": "TestMarykModel(7)"
}]
}, {
"index": 15,
Expand All @@ -319,7 +319,7 @@ internal class RootDataModelTest {
"required": false,
"final": false,
"unique": false,
"dataModel": "TestMarykModel"
"dataModel": "TestMarykModel(7)"
}]
}, {
"index": 17,
Expand Down Expand Up @@ -509,7 +509,7 @@ internal class RootDataModelTest {
required: false
final: false
unique: false
dataModel: TestMarykModel
dataModel: TestMarykModel(7)
? 15: listOfString
: !List
required: false
Expand All @@ -526,7 +526,7 @@ internal class RootDataModelTest {
required: false
final: false
unique: false
dataModel: TestMarykModel
dataModel: TestMarykModel(7)
? 17: setOfString
: !Set
required: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ internal class ReferenceDefinitionTest {
minValue: AAAAAAAAAA
maxValue: _________w
default: AQEBAQEBAQ
dataModel: TestMarykModel
dataModel: TestMarykModel(7)
""".trimIndent()
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package maryk.core.properties.definitions.contextual

import maryk.checkProtoBufConversion
import maryk.core.models.IsDataModel
import maryk.core.models.IsStorableDataModel
import maryk.core.query.RequestContext
import maryk.test.ByteCollector
import maryk.test.models.EmbeddedMarykModel
Expand Down Expand Up @@ -43,7 +42,7 @@ class ContextualModelReferenceDefinitionTest {
for (value in modelsToTest) {
checkProtoBufConversion(
bc,
DataModelReference((value as IsStorableDataModel<*>).Meta.name) { value },
DataModelReference(value),
this.def,
this.context
) { converted, original ->
Expand All @@ -55,7 +54,7 @@ class ContextualModelReferenceDefinitionTest {
@Test
fun convertString() {
for (namedDataModel in modelsToTest) {
val b = def.asString(DataModelReference((namedDataModel as IsStorableDataModel<*>).Meta.name) { namedDataModel }, this.context)
val b = def.asString(DataModelReference(namedDataModel), this.context)
expect(namedDataModel) { def.fromString(b, this.context).get.invoke(Unit) }
}
}
Expand Down

0 comments on commit d5cf02c

Please sign in to comment.