Skip to content

Commit e40a684

Browse files
committed
non-optional references are now generated with a non-nullable type
There is also a '_raw_...' property generated of type `INode?`.
1 parent e30acb0 commit e40a684

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

metamodel-generator/src/main/kotlin/org/modelix/metamodel/generator/MetaModelGenerator.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,13 @@ class MetaModelGenerator(val outputDir: Path) {
8181
.addType(generateNodeWrapperInterface(concept))
8282
.addType(generateNodeWrapperImpl(concept))
8383
.addImport(PropertyAccessor::class.asClassName().packageName, PropertyAccessor::class.asClassName().simpleName)
84-
.addImport(ReferenceAccessor::class.asClassName().packageName, ReferenceAccessor::class.asClassName().simpleName)
84+
.addImport(RawPropertyAccessor::class.asClassName().packageName, RawPropertyAccessor::class.asClassName().simpleName)
85+
.addImport(IntPropertyAccessor::class.asClassName().packageName, IntPropertyAccessor::class.asClassName().simpleName)
86+
.addImport(StringPropertyAccessor::class.asClassName().packageName, StringPropertyAccessor::class.asClassName().simpleName)
87+
.addImport(BooleanPropertyAccessor::class.asClassName().packageName, BooleanPropertyAccessor::class.asClassName().simpleName)
88+
.addImport(MandatoryReferenceAccessor::class.asClassName().packageName, MandatoryReferenceAccessor::class.asClassName().simpleName)
89+
.addImport(OptionalReferenceAccessor::class.asClassName().packageName, OptionalReferenceAccessor::class.asClassName().simpleName)
90+
.addImport(RawReferenceAccessor::class.asClassName().packageName, RawReferenceAccessor::class.asClassName().simpleName)
8591
.build().write()
8692
}
8793

@@ -265,10 +271,16 @@ class MetaModelGenerator(val outputDir: Path) {
265271
.build())
266272
}
267273
is ReferenceLinkData -> {
268-
addProperty(PropertySpec.builder(feature.validName, data.type.parseConceptRef(concept.language).nodeWrapperInterfaceType().copy(nullable = true))
274+
val accessorClass = if (data.optional) OptionalReferenceAccessor::class else MandatoryReferenceAccessor::class
275+
addProperty(PropertySpec.builder(feature.validName, data.type.parseConceptRef(concept.language).nodeWrapperInterfaceType().copy(nullable = data.optional))
269276
.addModifiers(KModifier.OVERRIDE)
270277
.mutable(true)
271-
.delegate("""${ReferenceAccessor::class.qualifiedName}(${ITypedNode::unwrap.name}(), "${feature.originalName}", ${data.type.nodeWrapperInterfaceName()}::class)""")
278+
.delegate("""${accessorClass.qualifiedName}(${ITypedNode::unwrap.name}(), "${feature.originalName}", ${data.type.nodeWrapperInterfaceName()}::class)""")
279+
.build())
280+
addProperty(PropertySpec.builder("_raw_" + feature.validName, INode::class.asTypeName().copy(nullable = true))
281+
.addModifiers(KModifier.OVERRIDE)
282+
.mutable(true)
283+
.delegate("""${RawReferenceAccessor::class.qualifiedName}(${ITypedNode::unwrap.name}(), "${feature.originalName}")""")
272284
.build())
273285
}
274286
}
@@ -302,7 +314,10 @@ class MetaModelGenerator(val outputDir: Path) {
302314
.build())
303315
}
304316
is ReferenceLinkData -> {
305-
addProperty(PropertySpec.builder(feature.validName, data.type.parseConceptRef(concept.language).nodeWrapperInterfaceType().copy(nullable = true))
317+
addProperty(PropertySpec.builder(feature.validName, data.type.parseConceptRef(concept.language).nodeWrapperInterfaceType().copy(nullable = data.optional))
318+
.mutable(true)
319+
.build())
320+
addProperty(PropertySpec.builder("_raw_" + feature.validName, INode::class.asTypeName().copy(nullable = true))
306321
.mutable(true)
307322
.build())
308323
}

metamodel-runtime/src/commonMain/kotlin/org/modelix/metamodel/ReferenceAccessor.kt

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,44 @@ package org.modelix.metamodel
33
import org.modelix.model.api.INode
44
import kotlin.reflect.KClass
55
import kotlin.reflect.KProperty
6-
import kotlin.reflect.cast
76

8-
class ReferenceAccessor<SourceT, TargetT : ITypedNode>(
7+
class OptionalReferenceAccessor<SourceT, TargetT : ITypedNode>(
98
val node: INode,
109
val role: String,
1110
val targetType: KClass<TargetT>
1211
) {
1312
operator fun getValue(thisRef: SourceT, property: KProperty<*>): TargetT? {
14-
return node.getReferenceTarget(role)?.let { targetType.cast(it.typed()) }
13+
return node.getReferenceTarget(role)?.typed(targetType)
1514
}
1615

1716
operator fun setValue(thisRef: SourceT, property: KProperty<*>, target: TargetT?) {
1817
node.setReferenceTarget(role, target?.unwrap())
1918
}
19+
}
20+
21+
class MandatoryReferenceAccessor<SourceT, TargetT : ITypedNode>(
22+
val node: INode,
23+
val role: String,
24+
val targetType: KClass<TargetT>
25+
) {
26+
operator fun getValue(thisRef: SourceT, property: KProperty<*>): TargetT {
27+
return node.getReferenceTarget(role)?.typed(targetType) ?: throw RuntimeException("reference '$role' is not set")
28+
}
29+
30+
operator fun setValue(thisRef: SourceT, property: KProperty<*>, target: TargetT) {
31+
node.setReferenceTarget(role, target.unwrap())
32+
}
33+
}
34+
35+
class RawReferenceAccessor<SourceT>(
36+
val node: INode,
37+
val role: String
38+
) {
39+
operator fun getValue(thisRef: SourceT, property: KProperty<*>): INode? {
40+
return node.getReferenceTarget(role)
41+
}
42+
43+
operator fun setValue(thisRef: SourceT, property: KProperty<*>, target: INode?) {
44+
node.setReferenceTarget(role, target)
45+
}
2046
}

0 commit comments

Comments
 (0)