From acfd7e87452f5b6d9af4861ac35ea70a1f5ac300 Mon Sep 17 00:00:00 2001 From: Federico Tomassetti Date: Tue, 4 Jul 2023 11:29:46 +0200 Subject: [PATCH] supporting the recognition of internal classes when mapping to EMF --- .../com/strumenta/kolasu/emf/Metamodel.kt | 2 +- .../strumenta/kolasu/emf/MetamodelBuilder.kt | 23 ++++++++++++++++--- .../com/strumenta/kolasu/emf/MetamodelTest.kt | 23 ++++++++++++++++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/emf/src/main/kotlin/com/strumenta/kolasu/emf/Metamodel.kt b/emf/src/main/kotlin/com/strumenta/kolasu/emf/Metamodel.kt index 9020947b6..e972f6c9d 100644 --- a/emf/src/main/kotlin/com/strumenta/kolasu/emf/Metamodel.kt +++ b/emf/src/main/kotlin/com/strumenta/kolasu/emf/Metamodel.kt @@ -115,7 +115,7 @@ val KClass<*>.eClassifierName: String val Class<*>.eClassifierName: String get() = if (this.enclosingClass != null) { - "${this.enclosingClass.simpleName}${this.simpleName}" + "${this.enclosingClass.simpleName}.${this.simpleName}" } else { this.simpleName } diff --git a/emf/src/main/kotlin/com/strumenta/kolasu/emf/MetamodelBuilder.kt b/emf/src/main/kotlin/com/strumenta/kolasu/emf/MetamodelBuilder.kt index a0c9e3efd..9181656c5 100644 --- a/emf/src/main/kotlin/com/strumenta/kolasu/emf/MetamodelBuilder.kt +++ b/emf/src/main/kotlin/com/strumenta/kolasu/emf/MetamodelBuilder.kt @@ -1,6 +1,7 @@ package com.strumenta.kolasu.emf import com.strumenta.kolasu.model.PropertyTypeDescription +import com.strumenta.kolasu.model.isANode import com.strumenta.kolasu.model.processProperties import org.eclipse.emf.ecore.* import org.eclipse.emf.ecore.resource.Resource @@ -13,12 +14,23 @@ import kotlin.reflect.full.withNullability private val KClass<*>.packageName: String? get() { - val qname = this.qualifiedName ?: throw IllegalStateException("The class has no qualified name: $this") + val isInternal = this.java.name.contains('$') + val qname = if (isInternal) { + this.java.name.split("$").first() + } else { + this.qualifiedName ?: throw IllegalStateException("The class has no qualified name: $this") + } return if (qname == this.simpleName) { null } else { - require(qname.endsWith(".${this.simpleName}")) - qname.removeSuffix(".${this.simpleName}") + if (isInternal) { + val last = qname.split(".").last() + require(qname.endsWith(".$last")) + qname.removeSuffix(".$last") + } else { + require(qname.endsWith(".${this.simpleName}")) + qname.removeSuffix(".${this.simpleName}") + } } } @@ -347,6 +359,11 @@ class MetamodelBuilder(packageName: String, nsURI: String, nsPrefix: String, res queue.add(it) } } + kClass.nestedClasses.forEach { + if (it.isANode()) { + queue.add(it) + } + } } while (queue.isNotEmpty()) { provideClass(queue.removeFirst()) diff --git a/emf/src/test/kotlin/com/strumenta/kolasu/emf/MetamodelTest.kt b/emf/src/test/kotlin/com/strumenta/kolasu/emf/MetamodelTest.kt index 48c39a329..a7ef8a52a 100644 --- a/emf/src/test/kotlin/com/strumenta/kolasu/emf/MetamodelTest.kt +++ b/emf/src/test/kotlin/com/strumenta/kolasu/emf/MetamodelTest.kt @@ -148,7 +148,6 @@ class MetamodelTest { ) metamodelBuilder.provideClass(NodeWithReference::class) val ePackage = metamodelBuilder.generate() - println(ePackage.saveAsJsonObject().toString()) assertEquals("com.strumenta.kolasu.emf", ePackage.name) assertEquals(1, ePackage.eClassifiers.size) @@ -162,4 +161,26 @@ class MetamodelTest { val pointers = nodeWithReference.eStructuralFeatures.find { it.name == "pointers" } as EReference assertEquals(true, pointers.isContainment) } + + @Test + fun internalClasses() { + val metamodelBuilder = MetamodelBuilder( + "com.strumenta.kolasu.emf", + "https://strumenta.com/simplemm", "simplemm" + ) + metamodelBuilder.provideClass(MyClassWithInternalClasses::class) + val ePackage = metamodelBuilder.generate() + assertEquals("com.strumenta.kolasu.emf", ePackage.name) + assertEquals(2, ePackage.eClassifiers.size) + val MyClassWithInternalClasses = ePackage.eClassifiers[0] + val Internal = ePackage.eClassifiers[1] + assertEquals("MyClassWithInternalClasses", MyClassWithInternalClasses.name) + assertEquals("MyClassWithInternalClasses.Internal", Internal.name) + } +} + +class MyClassWithInternalClasses : Node() { + class Internal : Node() + + class InternalWhichIsNotANode }