Skip to content

Commit

Permalink
Indicate runtime model type (#18)
Browse files Browse the repository at this point in the history
We add a function `modelType` to `Class` interface so that
users can retrieve the runtime type of an instance.

Fixes #15.

We used [aas-core-codegen 8d1185e].

[aas-core-codegen 8d1185e]: aas-core-works/aas-core-codegen@8d1185e
  • Loading branch information
mristin committed Jan 25, 2024
1 parent 3314cfa commit faf7ee5
Show file tree
Hide file tree
Showing 4 changed files with 1,606 additions and 0 deletions.
173 changes: 173 additions & 0 deletions dev_scripts/test_codegen/generate_test_for_model_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
"""Generate the test code for the ``descendOnce`` methods."""

import io
import os
import pathlib
import sys
from typing import List

import aas_core_codegen
import aas_core_codegen.common
import aas_core_codegen.naming
import aas_core_codegen.parse
import aas_core_codegen.run
from aas_core_codegen import intermediate
from aas_core_codegen.common import Stripped, Identifier
from aas_core_codegen.typescript import (
common as typescript_common,
naming as typescript_naming,
)
from aas_core_codegen.typescript.common import (
INDENT as I,
INDENT2 as II,
INDENT3 as III,
INDENT4 as IIII,
)

import test_codegen.common


def main() -> int:
"""Execute the main routine."""
symbol_table = test_codegen.common.load_symbol_table()

this_path = pathlib.Path(os.path.realpath(__file__))
repo_root = this_path.parent.parent.parent

warning = test_codegen.common.generate_warning_comment(
this_path.relative_to(repo_root)
)

blocks = [
Stripped(
"""\
/**
* Test `modelType()` methods.
*/"""
),
warning,
Stripped(
"""\
import * as AasTypes from "../src/types";
import * as AasStringification from "../src/stringification";
import * as TestCommonJsonization from "./commonJsonization";"""
),
] # type: List[Stripped]

from_string = typescript_naming.function_name(
Identifier("model_type_from_string")
)

must_to_string = typescript_naming.function_name(
Identifier("must_model_type_to_string")
)

model_type_enum = typescript_naming.enum_name(Identifier("Model_type"))

for concrete_cls in symbol_table.concrete_classes:
cls_name_typescript = typescript_naming.class_name(concrete_cls.name)

load_minimal_name = typescript_naming.function_name(
Identifier(f"load_minimal_{concrete_cls.name}")
)

model_type_literal = typescript_naming.enum_literal_name(concrete_cls.name)

blocks.append(
Stripped(
f"""\
test("model type of {cls_name_typescript}", () => {{
{I}const instance = TestCommonJsonization.{load_minimal_name}();
{I}expect(instance.modelType()).toStrictEqual(
{II}AasTypes.{model_type_enum}.{model_type_literal}
{I});
}});"""
)
)

string_literal = typescript_common.string_literal(
typescript_naming.enum_literal_name(concrete_cls.name)
)

blocks.append(
Stripped(
f"""\
test("model type from string of {cls_name_typescript}", () => {{
{I}const text = {string_literal};
{I}const literal = AasStringification.{from_string}(
{II}text
{I});
{I}expect(literal).toStrictEqual(
{II}AasTypes.{model_type_enum}.{model_type_literal}
{I});
}});"""
)
)

blocks.append(
Stripped(
f"""\
test("model type to string of {cls_name_typescript}", () => {{
{I}const text = AasStringification.{must_to_string}(
{II}AasTypes.{model_type_enum}.{model_type_literal}
{I});
{I}expect(text).toStrictEqual(
{II}{string_literal}
{I});
}});"""
)
)

blocks.append(
Stripped(
f"""\
test("model type from invalid string", () => {{
{I}const text = "This is definitely not a valid model type.";
{I}const literal = AasStringification.{from_string}(
{II}text
{I});
{I}expect(literal).toBeNull();
}});"""
)
)

to_string = typescript_naming.function_name(
Identifier("model_type_to_string")
)

blocks.append(
Stripped(
f"""\
test("invalid model type to string", () => {{
{I}// The number 9007199254740991 is the maximum safe integer.
{I}const literal = <AasTypes.{model_type_enum}>9007199254740991;
{I}const text = AasStringification.{to_string}(
{II}literal
{I});
{I}expect(text).toBeNull();
}});"""
)
)

writer = io.StringIO()
for i, block in enumerate(blocks):
if i > 0:
writer.write("\n\n")

writer.write(block)

writer.write("\n")

target_pth = repo_root / "test/types.modelType.spec.ts"
target_pth.write_text(writer.getvalue(), encoding="utf-8")

return 0


if __name__ == "__main__":
sys.exit(main())
140 changes: 140 additions & 0 deletions src/stringification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,146 @@

import * as AasTypes from "./types";

const MODEL_TYPE_FROM_STRING = new Map<string, AasTypes.ModelType>([
["Extension", AasTypes.ModelType.Extension],
["AdministrativeInformation", AasTypes.ModelType.AdministrativeInformation],
["Qualifier", AasTypes.ModelType.Qualifier],
["AssetAdministrationShell", AasTypes.ModelType.AssetAdministrationShell],
["AssetInformation", AasTypes.ModelType.AssetInformation],
["Resource", AasTypes.ModelType.Resource],
["SpecificAssetId", AasTypes.ModelType.SpecificAssetId],
["Submodel", AasTypes.ModelType.Submodel],
["RelationshipElement", AasTypes.ModelType.RelationshipElement],
["SubmodelElementList", AasTypes.ModelType.SubmodelElementList],
["SubmodelElementCollection", AasTypes.ModelType.SubmodelElementCollection],
["Property", AasTypes.ModelType.Property],
["MultiLanguageProperty", AasTypes.ModelType.MultiLanguageProperty],
["Range", AasTypes.ModelType.Range],
["ReferenceElement", AasTypes.ModelType.ReferenceElement],
["Blob", AasTypes.ModelType.Blob],
["File", AasTypes.ModelType.File],
["AnnotatedRelationshipElement", AasTypes.ModelType.AnnotatedRelationshipElement],
["Entity", AasTypes.ModelType.Entity],
["EventPayload", AasTypes.ModelType.EventPayload],
["BasicEventElement", AasTypes.ModelType.BasicEventElement],
["Operation", AasTypes.ModelType.Operation],
["OperationVariable", AasTypes.ModelType.OperationVariable],
["Capability", AasTypes.ModelType.Capability],
["ConceptDescription", AasTypes.ModelType.ConceptDescription],
["Reference", AasTypes.ModelType.Reference],
["Key", AasTypes.ModelType.Key],
["LangStringNameType", AasTypes.ModelType.LangStringNameType],
["LangStringTextType", AasTypes.ModelType.LangStringTextType],
["Environment", AasTypes.ModelType.Environment],
["EmbeddedDataSpecification", AasTypes.ModelType.EmbeddedDataSpecification],
["LevelType", AasTypes.ModelType.LevelType],
["ValueReferencePair", AasTypes.ModelType.ValueReferencePair],
["ValueList", AasTypes.ModelType.ValueList],
[
"LangStringPreferredNameTypeIec61360",
AasTypes.ModelType.LangStringPreferredNameTypeIec61360
],
[
"LangStringShortNameTypeIec61360",
AasTypes.ModelType.LangStringShortNameTypeIec61360
],
[
"LangStringDefinitionTypeIec61360",
AasTypes.ModelType.LangStringDefinitionTypeIec61360
],
["DataSpecificationIec61360", AasTypes.ModelType.DataSpecificationIec61360]
]);

/**
* Parse `text` as a string representation of {@link types!ModelType}.
*
* @param text - string representation of {@link types!ModelType}
* @returns literal of {@link types!ModelType}, if valid, and `null` otherwise
*/
export function modelTypeFromString(text: string): AasTypes.ModelType | null {
const result = MODEL_TYPE_FROM_STRING.get(text);
return result !== undefined ? result : null;
}

const MODEL_TYPE_TO_STRING = new Map<AasTypes.ModelType, string>([
[AasTypes.ModelType.Extension, "Extension"],
[AasTypes.ModelType.AdministrativeInformation, "AdministrativeInformation"],
[AasTypes.ModelType.Qualifier, "Qualifier"],
[AasTypes.ModelType.AssetAdministrationShell, "AssetAdministrationShell"],
[AasTypes.ModelType.AssetInformation, "AssetInformation"],
[AasTypes.ModelType.Resource, "Resource"],
[AasTypes.ModelType.SpecificAssetId, "SpecificAssetId"],
[AasTypes.ModelType.Submodel, "Submodel"],
[AasTypes.ModelType.RelationshipElement, "RelationshipElement"],
[AasTypes.ModelType.SubmodelElementList, "SubmodelElementList"],
[AasTypes.ModelType.SubmodelElementCollection, "SubmodelElementCollection"],
[AasTypes.ModelType.Property, "Property"],
[AasTypes.ModelType.MultiLanguageProperty, "MultiLanguageProperty"],
[AasTypes.ModelType.Range, "Range"],
[AasTypes.ModelType.ReferenceElement, "ReferenceElement"],
[AasTypes.ModelType.Blob, "Blob"],
[AasTypes.ModelType.File, "File"],
[AasTypes.ModelType.AnnotatedRelationshipElement, "AnnotatedRelationshipElement"],
[AasTypes.ModelType.Entity, "Entity"],
[AasTypes.ModelType.EventPayload, "EventPayload"],
[AasTypes.ModelType.BasicEventElement, "BasicEventElement"],
[AasTypes.ModelType.Operation, "Operation"],
[AasTypes.ModelType.OperationVariable, "OperationVariable"],
[AasTypes.ModelType.Capability, "Capability"],
[AasTypes.ModelType.ConceptDescription, "ConceptDescription"],
[AasTypes.ModelType.Reference, "Reference"],
[AasTypes.ModelType.Key, "Key"],
[AasTypes.ModelType.LangStringNameType, "LangStringNameType"],
[AasTypes.ModelType.LangStringTextType, "LangStringTextType"],
[AasTypes.ModelType.Environment, "Environment"],
[AasTypes.ModelType.EmbeddedDataSpecification, "EmbeddedDataSpecification"],
[AasTypes.ModelType.LevelType, "LevelType"],
[AasTypes.ModelType.ValueReferencePair, "ValueReferencePair"],
[AasTypes.ModelType.ValueList, "ValueList"],
[
AasTypes.ModelType.LangStringPreferredNameTypeIec61360,
"LangStringPreferredNameTypeIec61360"
],
[
AasTypes.ModelType.LangStringShortNameTypeIec61360,
"LangStringShortNameTypeIec61360"
],
[
AasTypes.ModelType.LangStringDefinitionTypeIec61360,
"LangStringDefinitionTypeIec61360"
],
[AasTypes.ModelType.DataSpecificationIec61360, "DataSpecificationIec61360"]
]);

/**
* Translate {@link types!ModelType} to a string.
*
* @param value - to be stringified
* @returns string representation of {@link types!ModelType},
* if `value` valid, and `null` otherwise
*/
export function modelTypeToString(value: AasTypes.ModelType): string | null {
const result = MODEL_TYPE_TO_STRING.get(value);
return result !== undefined ? result : null;
}

/**
* Translate {@link types!ModelType} to a string.
*
* @param value - to be stringified
* @returns string representation of {@link types!ModelType}
* @throws
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error|Error}
* if the `value` is invalid
*/
export function mustModelTypeToString(value: AasTypes.ModelType): string {
const result = MODEL_TYPE_TO_STRING.get(value);
if (result === undefined) {
throw new Error(`Invalid literal of ModelType: ${value}`);
}
return result;
}

const MODELLING_KIND_FROM_STRING = new Map<string, AasTypes.ModellingKind>([
["Template", AasTypes.ModellingKind.Template],
["Instance", AasTypes.ModellingKind.Instance]
Expand Down
Loading

0 comments on commit faf7ee5

Please sign in to comment.