aas-core-codegen 0.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aas_core_codegen/__init__.py +6 -0
- aas_core_codegen/__main__.py +8 -0
- aas_core_codegen/common.py +500 -0
- aas_core_codegen/cpp/__init__.py +1 -0
- aas_core_codegen/cpp/aas_common/__init__.py +6 -0
- aas_core_codegen/cpp/aas_common/_generate.py +713 -0
- aas_core_codegen/cpp/common.py +681 -0
- aas_core_codegen/cpp/constants/__init__.py +6 -0
- aas_core_codegen/cpp/constants/_generate.py +568 -0
- aas_core_codegen/cpp/description.py +654 -0
- aas_core_codegen/cpp/enhancing/__init__.py +4 -0
- aas_core_codegen/cpp/enhancing/_generate.py +993 -0
- aas_core_codegen/cpp/iteration/__init__.py +6 -0
- aas_core_codegen/cpp/iteration/_generate.py +2332 -0
- aas_core_codegen/cpp/jsonization/__init__.py +6 -0
- aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
- aas_core_codegen/cpp/main.py +694 -0
- aas_core_codegen/cpp/naming.py +170 -0
- aas_core_codegen/cpp/optionaling.py +557 -0
- aas_core_codegen/cpp/pattern/__init__.py +6 -0
- aas_core_codegen/cpp/pattern/_generate.py +508 -0
- aas_core_codegen/cpp/revm/__init__.py +6 -0
- aas_core_codegen/cpp/revm/_generate.py +1149 -0
- aas_core_codegen/cpp/stringification/__init__.py +5 -0
- aas_core_codegen/cpp/stringification/_generate.py +955 -0
- aas_core_codegen/cpp/structure/__init__.py +7 -0
- aas_core_codegen/cpp/structure/_generate.py +1503 -0
- aas_core_codegen/cpp/transpilation.py +1383 -0
- aas_core_codegen/cpp/unrolling.py +159 -0
- aas_core_codegen/cpp/verification/__init__.py +6 -0
- aas_core_codegen/cpp/verification/_generate.py +3073 -0
- aas_core_codegen/cpp/visitation/__init__.py +6 -0
- aas_core_codegen/cpp/visitation/_generate.py +521 -0
- aas_core_codegen/cpp/wstringification/__init__.py +5 -0
- aas_core_codegen/cpp/wstringification/_generate.py +586 -0
- aas_core_codegen/cpp/xmlization/__init__.py +6 -0
- aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
- aas_core_codegen/cpp/yielding.py +201 -0
- aas_core_codegen/csharp/__init__.py +1 -0
- aas_core_codegen/csharp/common.py +224 -0
- aas_core_codegen/csharp/constants/__init__.py +5 -0
- aas_core_codegen/csharp/constants/_generate.py +409 -0
- aas_core_codegen/csharp/copying/__init__.py +4 -0
- aas_core_codegen/csharp/copying/_generate.py +498 -0
- aas_core_codegen/csharp/description.py +1103 -0
- aas_core_codegen/csharp/enhancing/__init__.py +4 -0
- aas_core_codegen/csharp/enhancing/_generate.py +667 -0
- aas_core_codegen/csharp/jsonization/__init__.py +4 -0
- aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
- aas_core_codegen/csharp/main.py +421 -0
- aas_core_codegen/csharp/naming.py +157 -0
- aas_core_codegen/csharp/reporting/__init__.py +4 -0
- aas_core_codegen/csharp/reporting/_generate.py +266 -0
- aas_core_codegen/csharp/stringification/__init__.py +4 -0
- aas_core_codegen/csharp/stringification/_generate.py +243 -0
- aas_core_codegen/csharp/structure/__init__.py +6 -0
- aas_core_codegen/csharp/structure/_generate.py +1341 -0
- aas_core_codegen/csharp/transpilation.py +990 -0
- aas_core_codegen/csharp/unrolling.py +211 -0
- aas_core_codegen/csharp/verification/__init__.py +6 -0
- aas_core_codegen/csharp/verification/_generate.py +1457 -0
- aas_core_codegen/csharp/visitation/__init__.py +5 -0
- aas_core_codegen/csharp/visitation/_generate.py +579 -0
- aas_core_codegen/csharp/xmlization/__init__.py +4 -0
- aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
- aas_core_codegen/golang/__init__.py +1 -0
- aas_core_codegen/golang/aas_common/__init__.py +4 -0
- aas_core_codegen/golang/aas_common/_generate.py +152 -0
- aas_core_codegen/golang/common.py +303 -0
- aas_core_codegen/golang/constants/__init__.py +5 -0
- aas_core_codegen/golang/constants/_generate.py +339 -0
- aas_core_codegen/golang/description.py +501 -0
- aas_core_codegen/golang/enhancing/__init__.py +4 -0
- aas_core_codegen/golang/enhancing/_generate.py +527 -0
- aas_core_codegen/golang/jsonization/__init__.py +4 -0
- aas_core_codegen/golang/jsonization/_generate.py +1740 -0
- aas_core_codegen/golang/main.py +368 -0
- aas_core_codegen/golang/naming.py +412 -0
- aas_core_codegen/golang/pointering.py +631 -0
- aas_core_codegen/golang/reporting/__init__.py +4 -0
- aas_core_codegen/golang/reporting/_generate.py +218 -0
- aas_core_codegen/golang/stringification/__init__.py +4 -0
- aas_core_codegen/golang/stringification/_generate.py +394 -0
- aas_core_codegen/golang/structure/__init__.py +6 -0
- aas_core_codegen/golang/structure/_generate.py +1493 -0
- aas_core_codegen/golang/transpilation.py +1191 -0
- aas_core_codegen/golang/unrolling.py +159 -0
- aas_core_codegen/golang/verification/__init__.py +6 -0
- aas_core_codegen/golang/verification/_generate.py +1513 -0
- aas_core_codegen/golang/xmlization/__init__.py +4 -0
- aas_core_codegen/golang/xmlization/_generate.py +2507 -0
- aas_core_codegen/infer_for_schema/__init__.py +21 -0
- aas_core_codegen/infer_for_schema/_inline.py +693 -0
- aas_core_codegen/infer_for_schema/_len.py +527 -0
- aas_core_codegen/infer_for_schema/_pattern.py +311 -0
- aas_core_codegen/infer_for_schema/_set.py +394 -0
- aas_core_codegen/infer_for_schema/_stringify.py +201 -0
- aas_core_codegen/infer_for_schema/_types.py +135 -0
- aas_core_codegen/infer_for_schema/match.py +122 -0
- aas_core_codegen/intermediate/__init__.py +78 -0
- aas_core_codegen/intermediate/_hierarchy.py +397 -0
- aas_core_codegen/intermediate/_stringify.py +989 -0
- aas_core_codegen/intermediate/_translate.py +5128 -0
- aas_core_codegen/intermediate/_types.py +2901 -0
- aas_core_codegen/intermediate/construction.py +750 -0
- aas_core_codegen/intermediate/doc.py +344 -0
- aas_core_codegen/intermediate/pattern_verification.py +428 -0
- aas_core_codegen/intermediate/revm.py +985 -0
- aas_core_codegen/intermediate/type_inference.py +2266 -0
- aas_core_codegen/java/__init__.py +1 -0
- aas_core_codegen/java/common.py +197 -0
- aas_core_codegen/java/constants/__init__.py +5 -0
- aas_core_codegen/java/constants/_generate.py +334 -0
- aas_core_codegen/java/copying/__init__.py +4 -0
- aas_core_codegen/java/copying/_generate.py +502 -0
- aas_core_codegen/java/description.py +774 -0
- aas_core_codegen/java/enhancing/__init__.py +4 -0
- aas_core_codegen/java/enhancing/_generate.py +820 -0
- aas_core_codegen/java/generation/__init__.py +5 -0
- aas_core_codegen/java/generation/_generate.py +285 -0
- aas_core_codegen/java/jsonization/__init__.py +4 -0
- aas_core_codegen/java/jsonization/_generate.py +1472 -0
- aas_core_codegen/java/main.py +438 -0
- aas_core_codegen/java/naming.py +187 -0
- aas_core_codegen/java/optional.py +514 -0
- aas_core_codegen/java/reporting/__init__.py +4 -0
- aas_core_codegen/java/reporting/_generate.py +248 -0
- aas_core_codegen/java/stringification/__init__.py +4 -0
- aas_core_codegen/java/stringification/_generate.py +212 -0
- aas_core_codegen/java/structure/__init__.py +6 -0
- aas_core_codegen/java/structure/_generate.py +1767 -0
- aas_core_codegen/java/transpilation.py +1111 -0
- aas_core_codegen/java/verification/__init__.py +6 -0
- aas_core_codegen/java/verification/_generate.py +1536 -0
- aas_core_codegen/java/visitation/__init__.py +5 -0
- aas_core_codegen/java/visitation/_generate.py +689 -0
- aas_core_codegen/java/xmlization/__init__.py +4 -0
- aas_core_codegen/java/xmlization/_generate.py +2274 -0
- aas_core_codegen/jsonld/__init__.py +1 -0
- aas_core_codegen/jsonld/main.py +455 -0
- aas_core_codegen/jsonschema/__init__.py +1 -0
- aas_core_codegen/jsonschema/main.py +982 -0
- aas_core_codegen/main.py +245 -0
- aas_core_codegen/naming.py +133 -0
- aas_core_codegen/opcua/__init__.py +1 -0
- aas_core_codegen/opcua/main.py +1525 -0
- aas_core_codegen/opcua/naming.py +126 -0
- aas_core_codegen/parse/__init__.py +46 -0
- aas_core_codegen/parse/_rules.py +796 -0
- aas_core_codegen/parse/_stringify.py +532 -0
- aas_core_codegen/parse/_translate.py +3940 -0
- aas_core_codegen/parse/_types.py +973 -0
- aas_core_codegen/parse/retree/__init__.py +46 -0
- aas_core_codegen/parse/retree/_fix.py +434 -0
- aas_core_codegen/parse/retree/_parse.py +1143 -0
- aas_core_codegen/parse/retree/_render.py +298 -0
- aas_core_codegen/parse/retree/_stringify.py +199 -0
- aas_core_codegen/parse/retree/_types.py +362 -0
- aas_core_codegen/parse/retree/_visitor.py +70 -0
- aas_core_codegen/parse/tree.py +1303 -0
- aas_core_codegen/protobuf/__init__.py +1 -0
- aas_core_codegen/protobuf/common.py +225 -0
- aas_core_codegen/protobuf/description.py +1102 -0
- aas_core_codegen/protobuf/main.py +115 -0
- aas_core_codegen/protobuf/naming.py +143 -0
- aas_core_codegen/protobuf/structure/__init__.py +6 -0
- aas_core_codegen/protobuf/structure/_generate.py +502 -0
- aas_core_codegen/py.typed +1 -0
- aas_core_codegen/python/__init__.py +1 -0
- aas_core_codegen/python/aas_common/__init__.py +4 -0
- aas_core_codegen/python/aas_common/_generate.py +63 -0
- aas_core_codegen/python/common.py +406 -0
- aas_core_codegen/python/constants/__init__.py +5 -0
- aas_core_codegen/python/constants/_generate.py +377 -0
- aas_core_codegen/python/description.py +508 -0
- aas_core_codegen/python/jsonization/__init__.py +4 -0
- aas_core_codegen/python/jsonization/_generate.py +1391 -0
- aas_core_codegen/python/main.py +323 -0
- aas_core_codegen/python/naming.py +255 -0
- aas_core_codegen/python/stringification/__init__.py +4 -0
- aas_core_codegen/python/stringification/_generate.py +129 -0
- aas_core_codegen/python/structure/__init__.py +6 -0
- aas_core_codegen/python/structure/_generate.py +1801 -0
- aas_core_codegen/python/transpilation.py +958 -0
- aas_core_codegen/python/unrolling.py +156 -0
- aas_core_codegen/python/verification/__init__.py +6 -0
- aas_core_codegen/python/verification/_generate.py +1471 -0
- aas_core_codegen/python/xmlization/__init__.py +4 -0
- aas_core_codegen/python/xmlization/_generate.py +3003 -0
- aas_core_codegen/python_protobuf/__init__.py +1 -0
- aas_core_codegen/python_protobuf/main.py +1424 -0
- aas_core_codegen/python_protobuf/naming.py +85 -0
- aas_core_codegen/rdf_shacl/__init__.py +1 -0
- aas_core_codegen/rdf_shacl/_description.py +351 -0
- aas_core_codegen/rdf_shacl/common.py +206 -0
- aas_core_codegen/rdf_shacl/main.py +114 -0
- aas_core_codegen/rdf_shacl/naming.py +145 -0
- aas_core_codegen/rdf_shacl/rdf.py +435 -0
- aas_core_codegen/rdf_shacl/shacl.py +453 -0
- aas_core_codegen/run.py +124 -0
- aas_core_codegen/smoke/__init__.py +1 -0
- aas_core_codegen/smoke/main.py +219 -0
- aas_core_codegen/specific_implementations.py +72 -0
- aas_core_codegen/stringify.py +333 -0
- aas_core_codegen/typescript/__init__.py +1 -0
- aas_core_codegen/typescript/aas_common/__init__.py +4 -0
- aas_core_codegen/typescript/aas_common/_generate.py +472 -0
- aas_core_codegen/typescript/common.py +340 -0
- aas_core_codegen/typescript/constants/__init__.py +5 -0
- aas_core_codegen/typescript/constants/_generate.py +347 -0
- aas_core_codegen/typescript/description.py +530 -0
- aas_core_codegen/typescript/jsonization/__init__.py +4 -0
- aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
- aas_core_codegen/typescript/main.py +258 -0
- aas_core_codegen/typescript/naming.py +189 -0
- aas_core_codegen/typescript/stringification/__init__.py +4 -0
- aas_core_codegen/typescript/stringification/_generate.py +367 -0
- aas_core_codegen/typescript/structure/__init__.py +6 -0
- aas_core_codegen/typescript/structure/_generate.py +2500 -0
- aas_core_codegen/typescript/transpilation.py +1051 -0
- aas_core_codegen/typescript/unrolling.py +159 -0
- aas_core_codegen/typescript/verification/__init__.py +6 -0
- aas_core_codegen/typescript/verification/_generate.py +1578 -0
- aas_core_codegen/xsd/__init__.py +1 -0
- aas_core_codegen/xsd/main.py +1187 -0
- aas_core_codegen/xsd/naming.py +83 -0
- aas_core_codegen/yielding/__init__.py +1 -0
- aas_core_codegen/yielding/flow.py +139 -0
- aas_core_codegen/yielding/linear.py +754 -0
- aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
- aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
- aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
- aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
- aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
- aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
- aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
- dev/continuous_integration/__init__.py +1 -0
- dev/continuous_integration/check_help_in_readme.py +208 -0
- dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
- dev/continuous_integration/precommit.py +400 -0
- dev/dev_scripts/__init__.py +1 -0
- dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
- dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
- dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
- dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
- dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
- dev/dev_scripts/run_tests_with_rerecord.py +69 -0
- dev/dev_scripts/update_to_aas_core_meta.py +174 -0
- dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
- dev/integration_tests/input/meta_model.py +38 -0
- dev/integration_tests/input/python/boilerplate/main.py +153 -0
- dev/integration_tests/main.py +258 -0
- dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges_mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
- dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
- dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
- dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
- dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
- dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
- dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
- dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
- dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
- dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
- dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
- dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
- dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
- dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
- dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
- dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
- dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
- dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
- dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
- dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
- dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
- dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
- dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
- dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
- dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
- dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
- dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
- dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
- dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
- dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/default/meta_model.py +9 -0
- dev/test_data/parse/expected/method/description/meta_model.py +8 -0
- dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
- dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
- dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
- dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
- dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
- dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
- dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
- dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
- dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
- dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
- dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
- dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
- dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/dot/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/literal/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
- dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
- dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
- dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
- dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
- dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
- dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
- dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
- dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
- dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
- dev/tests/__init__.py +1 -0
- dev/tests/common.py +197 -0
- dev/tests/cpp/__init__.py +0 -0
- dev/tests/cpp/test_common.py +32 -0
- dev/tests/cpp/test_main.py +144 -0
- dev/tests/cpp/test_pattern.py +188 -0
- dev/tests/cpp/test_verification.py +189 -0
- dev/tests/cpp/test_yielding.py +225 -0
- dev/tests/csharp/__init__.py +0 -0
- dev/tests/csharp/live_test_main.py +109 -0
- dev/tests/csharp/test_common.py +28 -0
- dev/tests/csharp/test_description.py +684 -0
- dev/tests/csharp/test_main.py +129 -0
- dev/tests/csharp/test_structure.py +93 -0
- dev/tests/csharp/test_verification.py +82 -0
- dev/tests/description.py +29 -0
- dev/tests/golang/__init__.py +0 -0
- dev/tests/golang/test_common.py +78 -0
- dev/tests/golang/test_main.py +128 -0
- dev/tests/infer_for_schema/__init__.py +0 -0
- dev/tests/infer_for_schema/common.py +47 -0
- dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
- dev/tests/infer_for_schema/test_len_on_self.py +580 -0
- dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
- dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
- dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
- dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
- dev/tests/intermediate/__init__.py +0 -0
- dev/tests/intermediate/test_constructor.py +719 -0
- dev/tests/intermediate/test_hierarchy.py +221 -0
- dev/tests/intermediate/test_revm.py +134 -0
- dev/tests/intermediate/test_translate.py +337 -0
- dev/tests/intermediate/test_type_inference.py +333 -0
- dev/tests/intermediate/test_types.py +169 -0
- dev/tests/java/__init__.py +0 -0
- dev/tests/java/test_common.py +20 -0
- dev/tests/java/test_description.py +128 -0
- dev/tests/java/test_main.py +234 -0
- dev/tests/jsonld_context/test_main.py +79 -0
- dev/tests/opcua/__init__.py +3 -0
- dev/tests/opcua/test_main.py +110 -0
- dev/tests/our_jsonschema/__init__.py +3 -0
- dev/tests/our_jsonschema/test_main.py +232 -0
- dev/tests/parse/__init__.py +0 -0
- dev/tests/parse/test_parse.py +503 -0
- dev/tests/parse/test_retree.py +272 -0
- dev/tests/proto/__init__.py +0 -0
- dev/tests/proto/test_main.py +112 -0
- dev/tests/python/__init__.py +0 -0
- dev/tests/python/test_common.py +124 -0
- dev/tests/python/test_main.py +126 -0
- dev/tests/python/test_xml_playground.py +254 -0
- dev/tests/python_protobuf/__init__.py +0 -0
- dev/tests/python_protobuf/test_main.py +111 -0
- dev/tests/rdf_shacl/__init__.py +0 -0
- dev/tests/rdf_shacl/test_common.py +32 -0
- dev/tests/rdf_shacl/test_description.py +223 -0
- dev/tests/rdf_shacl/test_main.py +194 -0
- dev/tests/smoke/__init__.py +0 -0
- dev/tests/smoke/test_main.py +83 -0
- dev/tests/test_common.py +94 -0
- dev/tests/typescript/__init__.py +0 -0
- dev/tests/typescript/test_common.py +108 -0
- dev/tests/typescript/test_main.py +125 -0
- dev/tests/xsd/__init__.py +0 -0
- dev/tests/xsd/test_main.py +227 -0
- dev/tests/yielding/__init__.py +0 -0
- dev/tests/yielding/test_linear.py +558 -0
|
@@ -0,0 +1,1472 @@
|
|
|
1
|
+
"""Generate Java code for JSON-ization based on the intermediate representation."""
|
|
2
|
+
|
|
3
|
+
import io
|
|
4
|
+
import textwrap
|
|
5
|
+
from typing import Tuple, Optional, List
|
|
6
|
+
|
|
7
|
+
from icontract import ensure
|
|
8
|
+
|
|
9
|
+
from aas_core_codegen import intermediate, naming, specific_implementations
|
|
10
|
+
from aas_core_codegen.common import (
|
|
11
|
+
Error,
|
|
12
|
+
Stripped,
|
|
13
|
+
Identifier,
|
|
14
|
+
assert_never,
|
|
15
|
+
indent_but_first_line,
|
|
16
|
+
)
|
|
17
|
+
from aas_core_codegen.java import (
|
|
18
|
+
common as java_common,
|
|
19
|
+
naming as java_naming,
|
|
20
|
+
)
|
|
21
|
+
from aas_core_codegen.java.common import (
|
|
22
|
+
INDENT as I,
|
|
23
|
+
INDENT2 as II,
|
|
24
|
+
INDENT3 as III,
|
|
25
|
+
INDENT4 as IIII,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _generate_from_method_for_enumeration(
|
|
30
|
+
enumeration: intermediate.Enumeration,
|
|
31
|
+
) -> Stripped:
|
|
32
|
+
"""Generate the deserialization method for an enumeration."""
|
|
33
|
+
name = java_naming.enum_name(identifier=enumeration.name)
|
|
34
|
+
var_name = java_naming.variable_name(identifier=enumeration.name)
|
|
35
|
+
method_name = java_naming.method_name(Identifier(f"{enumeration.name}_from_string"))
|
|
36
|
+
|
|
37
|
+
message_literal = java_common.string_literal(
|
|
38
|
+
f"Not a valid JSON representation of {name}"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return Stripped(
|
|
42
|
+
f"""\
|
|
43
|
+
/**
|
|
44
|
+
* Deserialize the enumeration {name} from the {{@code node}}.
|
|
45
|
+
*
|
|
46
|
+
* @param node JSON node to be parsed
|
|
47
|
+
*/
|
|
48
|
+
private static Result<{name}> try{name}From(JsonNode node) {{
|
|
49
|
+
{I}final Result<String> textResult = tryStringFrom(node);
|
|
50
|
+
{I}if (textResult.isError()) {{
|
|
51
|
+
{II}return textResult.castTo({name}.class);
|
|
52
|
+
{I}}}
|
|
53
|
+
{I}final Optional<{name}> {var_name} = Stringification.{method_name}(textResult.getResult());
|
|
54
|
+
{I}if (!{var_name}.isPresent()) {{
|
|
55
|
+
{II}final Reporting.Error error = new Reporting.Error({message_literal});
|
|
56
|
+
{II}return Result.failure(error);
|
|
57
|
+
{I}}}
|
|
58
|
+
{I}return Result.success({var_name}.get());
|
|
59
|
+
}}"""
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _generate_from_method_for_interface(
|
|
64
|
+
interface: intermediate.Interface,
|
|
65
|
+
) -> Stripped:
|
|
66
|
+
"""Generate the deserialization method for an interface."""
|
|
67
|
+
name = java_naming.interface_name(interface.name)
|
|
68
|
+
interface_name = java_naming.interface_name(interface.name)
|
|
69
|
+
|
|
70
|
+
blocks = [
|
|
71
|
+
Stripped(
|
|
72
|
+
f"""\
|
|
73
|
+
if (node == null || !node.isObject()) {{
|
|
74
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
75
|
+
{II}"Expected a JsonObject, but got " + (node == null ? "null" : node.getNodeType()));
|
|
76
|
+
{I}return Result.failure(error);
|
|
77
|
+
}}
|
|
78
|
+
|
|
79
|
+
final JsonNode modelTypeNode = node.get("modelType");
|
|
80
|
+
if (modelTypeNode == null) {{
|
|
81
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
82
|
+
{III}"Expected a model type, but none is present");
|
|
83
|
+
{I}return Result.failure(error);
|
|
84
|
+
}}
|
|
85
|
+
final Result<String> modelTypeResult = tryStringFrom(modelTypeNode);
|
|
86
|
+
if (modelTypeResult.isError()) {{
|
|
87
|
+
{I}return modelTypeResult.castTo({interface_name}.class);
|
|
88
|
+
}}"""
|
|
89
|
+
),
|
|
90
|
+
] # type: List[Stripped]
|
|
91
|
+
|
|
92
|
+
# region Write the switch block
|
|
93
|
+
|
|
94
|
+
switch_writer = io.StringIO()
|
|
95
|
+
switch_writer.write(
|
|
96
|
+
"""\
|
|
97
|
+
switch (modelTypeResult.getResult())
|
|
98
|
+
{
|
|
99
|
+
"""
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
for implementer in interface.implementers:
|
|
103
|
+
model_type = naming.json_model_type(implementer.name)
|
|
104
|
+
implementer_name = java_naming.class_name(implementer.name)
|
|
105
|
+
switch_writer.write(
|
|
106
|
+
f"""\
|
|
107
|
+
{I}case {java_common.string_literal(model_type)}: {{
|
|
108
|
+
{II}return try{implementer_name}From(node);
|
|
109
|
+
}}"""
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
switch_writer.write(
|
|
113
|
+
f"""\
|
|
114
|
+
{I}default: {{
|
|
115
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
116
|
+
{III}"Unexpected model type for {name}: " + modelTypeResult.getResult());
|
|
117
|
+
{II}return Result.failure(error);
|
|
118
|
+
{I}}}
|
|
119
|
+
}}"""
|
|
120
|
+
)
|
|
121
|
+
blocks.append(Stripped(switch_writer.getvalue()))
|
|
122
|
+
|
|
123
|
+
# endregion
|
|
124
|
+
|
|
125
|
+
writer = io.StringIO()
|
|
126
|
+
|
|
127
|
+
writer.write(
|
|
128
|
+
f"""\
|
|
129
|
+
/**
|
|
130
|
+
* Deserialize an instance of {name} by dispatching
|
|
131
|
+
* based on {{@code modelType}} property of the {{@code node}}.
|
|
132
|
+
*
|
|
133
|
+
* @param node JSON node to be parsed
|
|
134
|
+
*/
|
|
135
|
+
public static Result<? extends {name}> try{name}From(JsonNode node) {{
|
|
136
|
+
"""
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
for i, block in enumerate(blocks):
|
|
140
|
+
if i > 0:
|
|
141
|
+
writer.write("\n\n")
|
|
142
|
+
writer.write(textwrap.indent(block, I))
|
|
143
|
+
|
|
144
|
+
writer.write("\n}")
|
|
145
|
+
|
|
146
|
+
return Stripped(writer.getvalue())
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
_PARSE_METHOD_BY_PRIMITIVE_TYPE = {
|
|
150
|
+
intermediate.PrimitiveType.BOOL: "tryBooleanFrom",
|
|
151
|
+
intermediate.PrimitiveType.INT: "tryLongFrom",
|
|
152
|
+
intermediate.PrimitiveType.FLOAT: "tryDoubleFrom",
|
|
153
|
+
intermediate.PrimitiveType.STR: "tryStringFrom",
|
|
154
|
+
intermediate.PrimitiveType.BYTEARRAY: "tryBytesFrom",
|
|
155
|
+
}
|
|
156
|
+
assert all(
|
|
157
|
+
literal in _PARSE_METHOD_BY_PRIMITIVE_TYPE for literal in intermediate.PrimitiveType
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _parse_method_for_atomic_value(
|
|
162
|
+
type_annotation: intermediate.AtomicTypeAnnotation,
|
|
163
|
+
) -> Stripped:
|
|
164
|
+
"""Determine the parse method for deserializing an atomic non-optional value."""
|
|
165
|
+
parse_method = None # type: Optional[str]
|
|
166
|
+
|
|
167
|
+
if isinstance(type_annotation, intermediate.PrimitiveTypeAnnotation):
|
|
168
|
+
parse_method = _PARSE_METHOD_BY_PRIMITIVE_TYPE[type_annotation.a_type]
|
|
169
|
+
|
|
170
|
+
elif isinstance(type_annotation, intermediate.OurTypeAnnotation):
|
|
171
|
+
our_type = type_annotation.our_type
|
|
172
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
173
|
+
enum_name = java_naming.enum_name(our_type.name)
|
|
174
|
+
parse_method = f"try{enum_name}From"
|
|
175
|
+
|
|
176
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
177
|
+
parse_method = _PARSE_METHOD_BY_PRIMITIVE_TYPE[our_type.constrainee]
|
|
178
|
+
|
|
179
|
+
elif isinstance(
|
|
180
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
181
|
+
):
|
|
182
|
+
if our_type.interface is not None:
|
|
183
|
+
interface_name = java_naming.interface_name(our_type.interface.name)
|
|
184
|
+
parse_method = f"try{interface_name}From"
|
|
185
|
+
else:
|
|
186
|
+
cls_name = java_naming.class_name(our_type.name)
|
|
187
|
+
parse_method = f"try{cls_name}From"
|
|
188
|
+
|
|
189
|
+
else:
|
|
190
|
+
assert_never(our_type)
|
|
191
|
+
else:
|
|
192
|
+
assert_never(type_annotation)
|
|
193
|
+
|
|
194
|
+
return Stripped(parse_method)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
198
|
+
def _generate_deserialize_constructor_argument(
|
|
199
|
+
arg: intermediate.Argument,
|
|
200
|
+
cls: intermediate.ConcreteClass,
|
|
201
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
202
|
+
"""Generate the code snippet for de-serializing the constructor argument ``arg``."""
|
|
203
|
+
type_anno = intermediate.beneath_optional(arg.type_annotation)
|
|
204
|
+
|
|
205
|
+
# Prefix the variables to avoid naming conflicts
|
|
206
|
+
target_var = java_naming.variable_name(Identifier(f"the_{arg.name}"))
|
|
207
|
+
|
|
208
|
+
json_name = naming.json_property(arg.name)
|
|
209
|
+
assert not java_common.needs_escaping(json_name)
|
|
210
|
+
|
|
211
|
+
json_literal = java_common.string_literal(json_name)
|
|
212
|
+
|
|
213
|
+
parse_block = None # type: Optional[Stripped]
|
|
214
|
+
if isinstance(
|
|
215
|
+
type_anno,
|
|
216
|
+
(intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
|
|
217
|
+
):
|
|
218
|
+
parse_method = _parse_method_for_atomic_value(type_anno)
|
|
219
|
+
|
|
220
|
+
value_type = java_common.generate_type(type_anno)
|
|
221
|
+
|
|
222
|
+
cls_name = java_naming.class_name(cls.name)
|
|
223
|
+
|
|
224
|
+
parse_block = Stripped(
|
|
225
|
+
f"""\
|
|
226
|
+
final Result<? extends {value_type}> {target_var}Result = {parse_method}(currentNode.getValue());
|
|
227
|
+
if ({target_var}Result.isError()) {{
|
|
228
|
+
{I}{target_var}Result.getError()
|
|
229
|
+
{II}.prependSegment(new Reporting.NameSegment("{json_name}"));
|
|
230
|
+
{I}return {target_var}Result.castTo({cls_name}.class);
|
|
231
|
+
}}
|
|
232
|
+
{target_var} = {target_var}Result.getResult();"""
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
236
|
+
assert not isinstance(
|
|
237
|
+
type_anno.items,
|
|
238
|
+
(intermediate.OptionalTypeAnnotation, intermediate.ListTypeAnnotation),
|
|
239
|
+
), (
|
|
240
|
+
"We chose to implement only a very limited pattern matching; "
|
|
241
|
+
"see intermediate._translate_._verify_only_simple_type_patterns"
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
item_type = java_common.generate_type(type_anno.items)
|
|
245
|
+
|
|
246
|
+
array_var = java_naming.variable_name(Identifier(f"array_{arg.name}"))
|
|
247
|
+
index_var = java_naming.variable_name(Identifier(f"index_{arg.name}"))
|
|
248
|
+
|
|
249
|
+
cls_name = java_naming.class_name(cls.name)
|
|
250
|
+
|
|
251
|
+
parse_method = _parse_method_for_atomic_value(type_anno.items)
|
|
252
|
+
|
|
253
|
+
parse_block = Stripped(
|
|
254
|
+
f"""\
|
|
255
|
+
final JsonNode {array_var} = currentNode.getValue();
|
|
256
|
+
if (!{array_var}.isArray()) {{
|
|
257
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
258
|
+
{II}"Expected a JsonArray, but got " + {array_var}.getNodeType());
|
|
259
|
+
{I}error.prependSegment(
|
|
260
|
+
{II}new Reporting.NameSegment(
|
|
261
|
+
{III}{json_literal}));
|
|
262
|
+
{I}return Result.failure(error);
|
|
263
|
+
}}
|
|
264
|
+
{target_var} = new ArrayList<>(
|
|
265
|
+
{I}{array_var}.size());
|
|
266
|
+
int {index_var} = 0;
|
|
267
|
+
for (JsonNode item : {array_var}) {{
|
|
268
|
+
{I}if (item == null) {{
|
|
269
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
270
|
+
{III}"Expected a non-null item, but got a null");
|
|
271
|
+
{II}error.prependSegment(
|
|
272
|
+
{III}new Reporting.IndexSegment(
|
|
273
|
+
{IIII}{index_var}));
|
|
274
|
+
{II}error.prependSegment(
|
|
275
|
+
{III}new Reporting.NameSegment(
|
|
276
|
+
{IIII}{json_literal}));
|
|
277
|
+
{II}return Result.failure(error);
|
|
278
|
+
{I}}}
|
|
279
|
+
{I}final Result<? extends {item_type}> parsedItemResult =
|
|
280
|
+
{II}{parse_method}(item);
|
|
281
|
+
{I}if (parsedItemResult.isError()) {{
|
|
282
|
+
{II}parsedItemResult
|
|
283
|
+
{III}.getError()
|
|
284
|
+
{III}.prependSegment(
|
|
285
|
+
{III}new Reporting.IndexSegment(
|
|
286
|
+
{IIII}{index_var}));
|
|
287
|
+
{II}parsedItemResult
|
|
288
|
+
{III}.getError()
|
|
289
|
+
{III}.prependSegment(
|
|
290
|
+
{III}new Reporting.NameSegment(
|
|
291
|
+
{IIII}{json_literal}));
|
|
292
|
+
{II}return parsedItemResult.castTo({cls_name}.class);
|
|
293
|
+
{I}}}
|
|
294
|
+
{I}{target_var}.add(
|
|
295
|
+
{II}parsedItemResult.getResult());
|
|
296
|
+
{I}{index_var}++;
|
|
297
|
+
}}"""
|
|
298
|
+
)
|
|
299
|
+
else:
|
|
300
|
+
assert_never(arg.type_annotation)
|
|
301
|
+
|
|
302
|
+
return parse_block, None
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
306
|
+
def _generate_from_method_for_class(
|
|
307
|
+
cls: intermediate.ConcreteClass,
|
|
308
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
309
|
+
"""Generate the deserialization method for a concrete class."""
|
|
310
|
+
errors = [] # type: List[Error]
|
|
311
|
+
|
|
312
|
+
name = java_naming.class_name(cls.name)
|
|
313
|
+
|
|
314
|
+
blocks = [
|
|
315
|
+
Stripped(
|
|
316
|
+
f"""\
|
|
317
|
+
if (node == null || !node.isObject()) {{
|
|
318
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
319
|
+
{II}"Expected a JsonObject, but got " + (node == null ? "null" : node.getNodeType()));
|
|
320
|
+
{I}return Result.failure(error);
|
|
321
|
+
}}"""
|
|
322
|
+
),
|
|
323
|
+
] # type: List[Stripped]
|
|
324
|
+
|
|
325
|
+
# region Initialize argument variables to null
|
|
326
|
+
|
|
327
|
+
args_init_writer = io.StringIO()
|
|
328
|
+
for i, arg in enumerate(cls.constructor.arguments):
|
|
329
|
+
arg_var = java_naming.variable_name(Identifier(f"the_{arg.name}"))
|
|
330
|
+
type_anno = intermediate.beneath_optional(arg.type_annotation)
|
|
331
|
+
arg_type = java_common.generate_type(type_anno)
|
|
332
|
+
|
|
333
|
+
if i > 0:
|
|
334
|
+
args_init_writer.write("\n")
|
|
335
|
+
args_init_writer.write(f"{arg_type} {arg_var} = null;")
|
|
336
|
+
|
|
337
|
+
blocks.append(Stripped(args_init_writer.getvalue()))
|
|
338
|
+
|
|
339
|
+
if cls.serialization.with_model_type:
|
|
340
|
+
blocks.append(Stripped("String modelType = null;"))
|
|
341
|
+
|
|
342
|
+
# endregion
|
|
343
|
+
|
|
344
|
+
# region Switch on property name
|
|
345
|
+
|
|
346
|
+
cases = [] # type: List[Stripped]
|
|
347
|
+
for arg in cls.constructor.arguments:
|
|
348
|
+
case_body, error = _generate_deserialize_constructor_argument(arg=arg, cls=cls)
|
|
349
|
+
if error is not None:
|
|
350
|
+
errors.append(error)
|
|
351
|
+
else:
|
|
352
|
+
assert case_body is not None
|
|
353
|
+
json_name = naming.json_property(arg.name)
|
|
354
|
+
|
|
355
|
+
# NOTE (empwilli, 2024-01-18):
|
|
356
|
+
# We put ``if (currentNode.getValue() == null)`` here instead of the outer loop
|
|
357
|
+
# since we want to detect the unexpected additional properties even
|
|
358
|
+
# though their value can be set to null.
|
|
359
|
+
|
|
360
|
+
cases.append(
|
|
361
|
+
Stripped(
|
|
362
|
+
f"""\
|
|
363
|
+
case {java_common.string_literal(json_name)}: {{
|
|
364
|
+
{I}if (currentNode.getValue() == null) {{
|
|
365
|
+
{II}continue;
|
|
366
|
+
{I}}}
|
|
367
|
+
|
|
368
|
+
{I}{indent_but_first_line(case_body, I)}
|
|
369
|
+
{I}break;
|
|
370
|
+
}}"""
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
if len(errors) > 0:
|
|
375
|
+
return None, errors
|
|
376
|
+
|
|
377
|
+
if cls.serialization.with_model_type:
|
|
378
|
+
cls_name = java_naming.class_name(cls.name)
|
|
379
|
+
model_type = naming.json_model_type(cls.name)
|
|
380
|
+
|
|
381
|
+
cases.append(
|
|
382
|
+
Stripped(
|
|
383
|
+
f"""\
|
|
384
|
+
case "modelType": {{
|
|
385
|
+
{I}if (currentNode.getValue() == null) {{
|
|
386
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
387
|
+
{III}"Expected a model type, but got null");
|
|
388
|
+
{II}return Result.failure(error);
|
|
389
|
+
{I}}}
|
|
390
|
+
{I}final Result<? extends String> modelTypeResult =
|
|
391
|
+
{II}DeserializeImplementation.tryStringFrom(currentNode.getValue());
|
|
392
|
+
{I}if (modelTypeResult.isError()) {{
|
|
393
|
+
{II}modelTypeResult.getError()
|
|
394
|
+
{III}.prependSegment(new Reporting.NameSegment("modelType"));
|
|
395
|
+
{II}return modelTypeResult.castTo({cls_name}.class);
|
|
396
|
+
{I}}}
|
|
397
|
+
{I}modelType = modelTypeResult.getResult();
|
|
398
|
+
|
|
399
|
+
{I}if (!modelType.equals("{model_type}")) {{
|
|
400
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
401
|
+
{III}"Expected the model type '{model_type}', " +
|
|
402
|
+
{III}"but got '" + modelType + "'");
|
|
403
|
+
{III}error.prependSegment(new Reporting.NameSegment("modelType"));
|
|
404
|
+
{III}return Result.failure(error);
|
|
405
|
+
{I}}}
|
|
406
|
+
{I}break;
|
|
407
|
+
}}"""
|
|
408
|
+
)
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
cases.append(
|
|
412
|
+
Stripped(
|
|
413
|
+
f"""\
|
|
414
|
+
default: {{
|
|
415
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
416
|
+
{II}"Unexpected property: " + currentNode.getKey());
|
|
417
|
+
{I}return Result.failure(error);
|
|
418
|
+
}}"""
|
|
419
|
+
)
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
foreach_writer = io.StringIO()
|
|
423
|
+
foreach_writer.write(
|
|
424
|
+
f"""\
|
|
425
|
+
for (Iterator<Map.Entry<String, JsonNode>> iterator = node.fields(); iterator.hasNext(); ) {{
|
|
426
|
+
{I}Map.Entry<String, JsonNode> currentNode = iterator.next();
|
|
427
|
+
|
|
428
|
+
{I}switch (currentNode.getKey()) {{"""
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
for case_block in cases:
|
|
432
|
+
foreach_writer.write("\n")
|
|
433
|
+
foreach_writer.write(textwrap.indent(case_block, II))
|
|
434
|
+
|
|
435
|
+
foreach_writer.write(f"\n{I}}}\n}}")
|
|
436
|
+
|
|
437
|
+
blocks.append(Stripped(foreach_writer.getvalue()))
|
|
438
|
+
|
|
439
|
+
# endregion
|
|
440
|
+
|
|
441
|
+
# region Check required
|
|
442
|
+
|
|
443
|
+
if cls.serialization.with_model_type:
|
|
444
|
+
blocks.append(
|
|
445
|
+
Stripped(
|
|
446
|
+
f"""\
|
|
447
|
+
if (modelType == null) {{
|
|
448
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
449
|
+
{II}"Required property \\"modelType\\" is missing");
|
|
450
|
+
{I}return Result.failure(error);
|
|
451
|
+
}}"""
|
|
452
|
+
)
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
required_check_writer = io.StringIO()
|
|
456
|
+
for i, arg in enumerate(cls.constructor.arguments):
|
|
457
|
+
if isinstance(arg.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
arg_var = java_naming.variable_name(Identifier(f"the_{arg.name}"))
|
|
461
|
+
json_name = naming.json_property(arg.name)
|
|
462
|
+
assert not java_common.needs_escaping(json_name)
|
|
463
|
+
|
|
464
|
+
if i > 0:
|
|
465
|
+
required_check_writer.write("\n\n")
|
|
466
|
+
|
|
467
|
+
required_check_writer.write(
|
|
468
|
+
f"""\
|
|
469
|
+
if ({arg_var} == null) {{
|
|
470
|
+
{I}final Reporting.Error error = new Reporting.Error(
|
|
471
|
+
{II}"Required property \\\"{json_name}\\\" is missing");
|
|
472
|
+
{I}return Result.failure(error);
|
|
473
|
+
}}"""
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
blocks.append(Stripped(required_check_writer.getvalue()))
|
|
477
|
+
|
|
478
|
+
# endregion
|
|
479
|
+
|
|
480
|
+
# region Pass in arguments to the constructor
|
|
481
|
+
|
|
482
|
+
property_names = [prop.name for prop in cls.properties]
|
|
483
|
+
constructor_argument_names = [arg.name for arg in cls.constructor.arguments]
|
|
484
|
+
|
|
485
|
+
# fmt: off
|
|
486
|
+
assert (
|
|
487
|
+
set(prop.name for prop in cls.properties)
|
|
488
|
+
== set(arg.name for arg in cls.constructor.arguments)
|
|
489
|
+
), (
|
|
490
|
+
f"Expected the properties to coincide with constructor arguments, "
|
|
491
|
+
f"but they do not for {cls.name!r}:"
|
|
492
|
+
f"{property_names=}, {constructor_argument_names=}"
|
|
493
|
+
)
|
|
494
|
+
# fmt: on
|
|
495
|
+
|
|
496
|
+
if len(cls.constructor.arguments) == 0:
|
|
497
|
+
blocks.append(Stripped(f"return Result.success(new{name}());"))
|
|
498
|
+
else:
|
|
499
|
+
init_writer = io.StringIO()
|
|
500
|
+
init_writer.write(f"return Result.success(new {name}(\n")
|
|
501
|
+
|
|
502
|
+
for i, arg in enumerate(cls.constructor.arguments):
|
|
503
|
+
prop = cls.properties_by_name[arg.name]
|
|
504
|
+
|
|
505
|
+
# NOTE (empwilli, 2024-01-18):
|
|
506
|
+
# The argument to the constructor may be optional while the property
|
|
507
|
+
# might be required, since we can set the default value in the body of
|
|
508
|
+
# the constructor. However, we can not have an optional property and a
|
|
509
|
+
# required constructor argument as we then would not know how to create
|
|
510
|
+
# the instance.
|
|
511
|
+
|
|
512
|
+
if not (
|
|
513
|
+
intermediate.type_annotations_equal(
|
|
514
|
+
arg.type_annotation, prop.type_annotation
|
|
515
|
+
)
|
|
516
|
+
or intermediate.type_annotations_equal(
|
|
517
|
+
intermediate.beneath_optional(arg.type_annotation),
|
|
518
|
+
prop.type_annotation,
|
|
519
|
+
)
|
|
520
|
+
):
|
|
521
|
+
errors.append(
|
|
522
|
+
Error(
|
|
523
|
+
arg.parsed.node,
|
|
524
|
+
f"Expected type annotation for property {prop.name!r} "
|
|
525
|
+
f"and constructor argument {arg.name!r} "
|
|
526
|
+
f"of the class {cls.name!r} to have matching types, "
|
|
527
|
+
f"but they do not: "
|
|
528
|
+
f"property type is {prop.type_annotation} "
|
|
529
|
+
f"and argument type is {arg.type_annotation}. "
|
|
530
|
+
f"Hence we do not know how to generate the call "
|
|
531
|
+
f"to the constructor in the JSON de-serialization.",
|
|
532
|
+
)
|
|
533
|
+
)
|
|
534
|
+
continue
|
|
535
|
+
|
|
536
|
+
arg_var = java_naming.variable_name(Identifier(f"the_{arg.name}"))
|
|
537
|
+
|
|
538
|
+
init_writer.write(f"{I}{arg_var}")
|
|
539
|
+
|
|
540
|
+
if i < len(cls.constructor.arguments) - 1:
|
|
541
|
+
init_writer.write(",\n")
|
|
542
|
+
else:
|
|
543
|
+
init_writer.write("));")
|
|
544
|
+
|
|
545
|
+
if len(errors) > 0:
|
|
546
|
+
return None, errors
|
|
547
|
+
|
|
548
|
+
blocks.append(Stripped(init_writer.getvalue()))
|
|
549
|
+
# endregion
|
|
550
|
+
|
|
551
|
+
writer = io.StringIO()
|
|
552
|
+
|
|
553
|
+
writer.write(
|
|
554
|
+
f"""\
|
|
555
|
+
/**
|
|
556
|
+
* Deserialize an instance of {name} from {{@param node}}.
|
|
557
|
+
*
|
|
558
|
+
* @param node JSON node to be parsed
|
|
559
|
+
* @param elem Error, if any, during the deserialization
|
|
560
|
+
*/
|
|
561
|
+
private static Result<{name}> try{name}From(JsonNode node) {{
|
|
562
|
+
"""
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
for i, block in enumerate(blocks):
|
|
566
|
+
if i > 0:
|
|
567
|
+
writer.write("\n\n")
|
|
568
|
+
writer.write(textwrap.indent(block, I))
|
|
569
|
+
|
|
570
|
+
writer.write("\n}")
|
|
571
|
+
|
|
572
|
+
return Stripped(writer.getvalue()), None
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
576
|
+
def _generate_deserialize_impl(
|
|
577
|
+
symbol_table: intermediate.SymbolTable,
|
|
578
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
579
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
580
|
+
"""Generate the implementation of the deserialization."""
|
|
581
|
+
errors = [] # type: List[Error]
|
|
582
|
+
blocks = [
|
|
583
|
+
Stripped(
|
|
584
|
+
f"""\
|
|
585
|
+
/** Convert {{@code value}} to a string.
|
|
586
|
+
* @param node JSON node to be parsed
|
|
587
|
+
*/
|
|
588
|
+
private static Result<String> tryStringFrom(JsonNode value) {{
|
|
589
|
+
{I}if (!value.isTextual()) {{
|
|
590
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
591
|
+
{III}"Expected a JsonValue of String, but got " + value.getNodeType());
|
|
592
|
+
{II}return Result.failure(error);
|
|
593
|
+
{I}}}
|
|
594
|
+
{I}return Result.success(value.asText());
|
|
595
|
+
}}"""
|
|
596
|
+
),
|
|
597
|
+
Stripped(
|
|
598
|
+
f"""\
|
|
599
|
+
/** Convert {{@code value}} to a boolean.
|
|
600
|
+
* @param node JSON node to be parsed
|
|
601
|
+
*/
|
|
602
|
+
private static Result<Boolean> tryBooleanFrom(JsonNode value) {{
|
|
603
|
+
{I}if (!value.isBoolean()) {{
|
|
604
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
605
|
+
{III}"Expected a JsonValue of Boolean, but got " + value.getNodeType());
|
|
606
|
+
{II}return Result.failure(error);
|
|
607
|
+
{I}}}
|
|
608
|
+
{I}return Result.success(value.asBoolean());
|
|
609
|
+
}}"""
|
|
610
|
+
),
|
|
611
|
+
Stripped(
|
|
612
|
+
f"""\
|
|
613
|
+
/** Convert {{@code value}} to a long 64-bit integer.
|
|
614
|
+
* @param node JSON node to be parsed
|
|
615
|
+
*/
|
|
616
|
+
private static Result<Long> tryLongFrom(JsonNode value) {{
|
|
617
|
+
{I}if (!value.isLong()) {{
|
|
618
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
619
|
+
{III}"Expected a JsonValue of Long, but got " + value.getNodeType());
|
|
620
|
+
{II}return Result.failure(error);
|
|
621
|
+
{I}}}
|
|
622
|
+
{I}return Result.success(value.asLong());
|
|
623
|
+
}}"""
|
|
624
|
+
),
|
|
625
|
+
Stripped(
|
|
626
|
+
f"""\
|
|
627
|
+
/** Convert {{@code value}} to a double-precision 64-bit float.
|
|
628
|
+
* @param node JSON node to be parsed
|
|
629
|
+
*/
|
|
630
|
+
private static Result<Double> tryDoubleFrom(JsonNode value) {{
|
|
631
|
+
{I}if (!value.isDouble()) {{
|
|
632
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
633
|
+
{III}"Expected a JsonValue of Double, but got " + value.getNodeType());
|
|
634
|
+
{II}return Result.failure(error);
|
|
635
|
+
{I}}}
|
|
636
|
+
{I}return Result.success(value.asDouble());
|
|
637
|
+
}}"""
|
|
638
|
+
),
|
|
639
|
+
Stripped(
|
|
640
|
+
f"""\
|
|
641
|
+
private static Result<byte[]> tryBytesFrom(JsonNode value) {{
|
|
642
|
+
{I}if (!value.isTextual()) {{
|
|
643
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
644
|
+
{III}"Expected a JsonValue of String, but got " + value.getNodeType());
|
|
645
|
+
{II}return Result.failure(error);
|
|
646
|
+
{I}}}
|
|
647
|
+
{I}final byte[] decodedData;
|
|
648
|
+
{I}Base64.Decoder decoder = Base64.getDecoder();
|
|
649
|
+
|
|
650
|
+
{I}try {{
|
|
651
|
+
{II}decodedData = decoder.decode(value.textValue());
|
|
652
|
+
{I}}} catch (Exception exception) {{
|
|
653
|
+
{II}final Reporting.Error error = new Reporting.Error(
|
|
654
|
+
{III}"Expected Base-64 encoded bytes, but the conversion failed " +
|
|
655
|
+
{IIII}"because: " + exception.getMessage());
|
|
656
|
+
{II}return Result.failure(error);
|
|
657
|
+
{I}}}
|
|
658
|
+
|
|
659
|
+
{I}return Result.success(decodedData);
|
|
660
|
+
}}"""
|
|
661
|
+
),
|
|
662
|
+
] # type: List[Stripped]
|
|
663
|
+
|
|
664
|
+
for our_type in symbol_table.our_types:
|
|
665
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
666
|
+
blocks.append(_generate_from_method_for_enumeration(enumeration=our_type))
|
|
667
|
+
|
|
668
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
669
|
+
continue
|
|
670
|
+
|
|
671
|
+
elif isinstance(
|
|
672
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
673
|
+
):
|
|
674
|
+
if our_type.interface is not None:
|
|
675
|
+
blocks.append(
|
|
676
|
+
_generate_from_method_for_interface(interface=our_type.interface)
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
if isinstance(our_type, intermediate.ConcreteClass):
|
|
680
|
+
if our_type.is_implementation_specific:
|
|
681
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
682
|
+
f"Jsonization/DeserializeImplementation/{our_type.name}_from.java"
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
686
|
+
if implementation is None:
|
|
687
|
+
errors.append(
|
|
688
|
+
Error(
|
|
689
|
+
our_type.parsed.node,
|
|
690
|
+
f"The jsonization snippet is missing "
|
|
691
|
+
f"for the implementation-specific "
|
|
692
|
+
f"class {our_type.name}: {implementation_key}",
|
|
693
|
+
)
|
|
694
|
+
)
|
|
695
|
+
continue
|
|
696
|
+
|
|
697
|
+
blocks.append(spec_impls[implementation_key])
|
|
698
|
+
else:
|
|
699
|
+
block, cls_errors = _generate_from_method_for_class(cls=our_type)
|
|
700
|
+
if cls_errors is not None:
|
|
701
|
+
errors.extend(cls_errors)
|
|
702
|
+
continue
|
|
703
|
+
else:
|
|
704
|
+
assert block is not None
|
|
705
|
+
blocks.append(block)
|
|
706
|
+
else:
|
|
707
|
+
assert_never(our_type)
|
|
708
|
+
|
|
709
|
+
if len(errors) > 0:
|
|
710
|
+
return None, errors
|
|
711
|
+
|
|
712
|
+
writer = io.StringIO()
|
|
713
|
+
|
|
714
|
+
writer.write(
|
|
715
|
+
"""\
|
|
716
|
+
/**
|
|
717
|
+
* Implement the deserialization of meta-model classes from JSON nodes.
|
|
718
|
+
*
|
|
719
|
+
* <p>The implementation propagates an {@link Reporting.Error} instead
|
|
720
|
+
* of relying on exceptions. Under the assumption that incorrect data is much
|
|
721
|
+
* less frequent than correct data, this makes the deserialization more
|
|
722
|
+
* efficient.
|
|
723
|
+
*
|
|
724
|
+
* However, we do not want to force the client to deal with
|
|
725
|
+
* the {@link Reporting.Error} class as this is not intuitive. Therefore
|
|
726
|
+
* we distinguish the implementation, realized in
|
|
727
|
+
* {@link DeserializeImplementation}, and the facade given in
|
|
728
|
+
* {@link Deserialize} class.
|
|
729
|
+
*/
|
|
730
|
+
private static class DeserializeImplementation {
|
|
731
|
+
"""
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
for i, block in enumerate(blocks):
|
|
735
|
+
if i > 0:
|
|
736
|
+
writer.write("\n\n")
|
|
737
|
+
writer.write(textwrap.indent(block, I))
|
|
738
|
+
|
|
739
|
+
writer.write("\n}")
|
|
740
|
+
|
|
741
|
+
return Stripped(writer.getvalue()), None
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
def _generate_deserialize_from(name: str) -> Stripped:
|
|
745
|
+
"""Generate the facade deserialization method for the type with C# ``name``."""
|
|
746
|
+
writer = io.StringIO()
|
|
747
|
+
writer.write(
|
|
748
|
+
f"""\
|
|
749
|
+
/**
|
|
750
|
+
* Deserialize an instance of {name} from {{@code node}}.
|
|
751
|
+
*
|
|
752
|
+
* @param node JSON node to be parsed
|
|
753
|
+
*/
|
|
754
|
+
"""
|
|
755
|
+
)
|
|
756
|
+
|
|
757
|
+
writer.write(
|
|
758
|
+
f"""\
|
|
759
|
+
public static {name} deserialize{name}(JsonNode node) {{
|
|
760
|
+
{I}final Result<? extends {name}> result =
|
|
761
|
+
{II}DeserializeImplementation.try{name}From(
|
|
762
|
+
{III}node);
|
|
763
|
+
|
|
764
|
+
{I}return result.onError(error -> {{
|
|
765
|
+
{II}throw new DeserializeException(
|
|
766
|
+
{III}Reporting.generateJsonPath(error.getPathSegments()),
|
|
767
|
+
{III}error.getCause());
|
|
768
|
+
{I}}});
|
|
769
|
+
}}"""
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
return Stripped(writer.getvalue())
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
def _generate_deserialize(
|
|
776
|
+
symbol_table: intermediate.SymbolTable,
|
|
777
|
+
) -> Stripped:
|
|
778
|
+
"""Generate the deserializer with a deserialization method for each class."""
|
|
779
|
+
blocks = [] # type: List[Stripped]
|
|
780
|
+
for our_type in symbol_table.our_types:
|
|
781
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
782
|
+
blocks.append(
|
|
783
|
+
_generate_deserialize_from(name=java_naming.enum_name(our_type.name))
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
787
|
+
continue
|
|
788
|
+
|
|
789
|
+
elif isinstance(
|
|
790
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
791
|
+
):
|
|
792
|
+
if our_type.interface is not None:
|
|
793
|
+
blocks.append(
|
|
794
|
+
_generate_deserialize_from(
|
|
795
|
+
name=java_naming.interface_name(our_type.interface.name)
|
|
796
|
+
)
|
|
797
|
+
)
|
|
798
|
+
|
|
799
|
+
if isinstance(our_type, intermediate.ConcreteClass):
|
|
800
|
+
blocks.append(
|
|
801
|
+
_generate_deserialize_from(
|
|
802
|
+
name=java_naming.class_name(our_type.name)
|
|
803
|
+
)
|
|
804
|
+
)
|
|
805
|
+
else:
|
|
806
|
+
assert_never(our_type)
|
|
807
|
+
|
|
808
|
+
writer = io.StringIO()
|
|
809
|
+
|
|
810
|
+
writer.write(
|
|
811
|
+
"""\
|
|
812
|
+
/**
|
|
813
|
+
* Deserialize instances of meta-model classes from JSON nodes.
|
|
814
|
+
*
|
|
815
|
+
"""
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
first_cls = (
|
|
819
|
+
symbol_table.classes[0] if len(symbol_table.classes) > 0 else None
|
|
820
|
+
) # type: Optional[intermediate.ClassUnion]
|
|
821
|
+
|
|
822
|
+
if first_cls is not None:
|
|
823
|
+
cls_name = None # type: Optional[str]
|
|
824
|
+
if isinstance(first_cls, intermediate.AbstractClass):
|
|
825
|
+
cls_name = java_naming.interface_name(first_cls.name)
|
|
826
|
+
elif isinstance(first_cls, intermediate.ConcreteClass):
|
|
827
|
+
cls_name = java_naming.class_name(first_cls.name)
|
|
828
|
+
else:
|
|
829
|
+
assert_never(first_cls)
|
|
830
|
+
|
|
831
|
+
an_instance_variable = java_naming.variable_name(Identifier("an_instance"))
|
|
832
|
+
|
|
833
|
+
writer.write(
|
|
834
|
+
f"""\
|
|
835
|
+
* Here is an example how to parse an instance of {cls_name}:
|
|
836
|
+
* <pre>{{@code
|
|
837
|
+
* String someString = "... some JSON ...";
|
|
838
|
+
* ObjectMapper objectMapper = new ObjectMapper();
|
|
839
|
+
* JsonNode node = objectMapper.readTree(someString);
|
|
840
|
+
* {cls_name} {an_instance_variable} = Deserialize.deserialize{cls_name}(
|
|
841
|
+
* {I}node);
|
|
842
|
+
* }}</pre>
|
|
843
|
+
*/
|
|
844
|
+
"""
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
writer.write(
|
|
848
|
+
"""\
|
|
849
|
+
public static class Deserialize
|
|
850
|
+
{
|
|
851
|
+
"""
|
|
852
|
+
)
|
|
853
|
+
|
|
854
|
+
for i, block in enumerate(blocks):
|
|
855
|
+
if i > 0:
|
|
856
|
+
writer.write("\n\n")
|
|
857
|
+
writer.write(textwrap.indent(block, I))
|
|
858
|
+
|
|
859
|
+
writer.write("\n}")
|
|
860
|
+
|
|
861
|
+
return Stripped(writer.getvalue())
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
def _generate_serialize_primitive_value(
|
|
865
|
+
primitive_type: intermediate.PrimitiveType, source_expr: Stripped
|
|
866
|
+
) -> Stripped:
|
|
867
|
+
"""
|
|
868
|
+
Generate the snippet to serialize ``source_expr`` to JSON.
|
|
869
|
+
|
|
870
|
+
Source expression is expected to be of ``primitive_type``.
|
|
871
|
+
"""
|
|
872
|
+
if primitive_type is intermediate.PrimitiveType.BOOL:
|
|
873
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
874
|
+
return Stripped(
|
|
875
|
+
f"""\
|
|
876
|
+
JsonNodeFactory.instance.booleanNode(
|
|
877
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
878
|
+
)
|
|
879
|
+
elif primitive_type is intermediate.PrimitiveType.FLOAT:
|
|
880
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
881
|
+
return Stripped(
|
|
882
|
+
f"""\
|
|
883
|
+
JsonNodeFactory.instance.numberNode(
|
|
884
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
885
|
+
)
|
|
886
|
+
elif primitive_type is intermediate.PrimitiveType.STR:
|
|
887
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
888
|
+
return Stripped(
|
|
889
|
+
f"""\
|
|
890
|
+
JsonNodeFactory.instance.textNode(
|
|
891
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
892
|
+
)
|
|
893
|
+
elif primitive_type is intermediate.PrimitiveType.INT:
|
|
894
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
895
|
+
return Stripped(
|
|
896
|
+
f"""\
|
|
897
|
+
Transformer.toJsonValue(
|
|
898
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
899
|
+
)
|
|
900
|
+
elif primitive_type is intermediate.PrimitiveType.BYTEARRAY:
|
|
901
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
902
|
+
return Stripped(
|
|
903
|
+
f"""\
|
|
904
|
+
JsonNodeFactory.instance.textNode(
|
|
905
|
+
{II}Base64.getEncoder()
|
|
906
|
+
{III}.encodeToString({indent_but_first_line(source_expr, II)}))"""
|
|
907
|
+
)
|
|
908
|
+
else:
|
|
909
|
+
assert_never(primitive_type)
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
def _generate_serialize_atomic_value(
|
|
913
|
+
type_annotation: intermediate.AtomicTypeAnnotation, source_expr: Stripped
|
|
914
|
+
) -> Stripped:
|
|
915
|
+
"""Generate the snippet to serialize ``source_expr`` to JSON."""
|
|
916
|
+
if isinstance(type_annotation, intermediate.PrimitiveTypeAnnotation):
|
|
917
|
+
return _generate_serialize_primitive_value(
|
|
918
|
+
primitive_type=type_annotation.a_type, source_expr=source_expr
|
|
919
|
+
)
|
|
920
|
+
elif isinstance(type_annotation, intermediate.OurTypeAnnotation):
|
|
921
|
+
our_type = type_annotation.our_type
|
|
922
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
923
|
+
method_name = java_naming.method_name(
|
|
924
|
+
Identifier(f"{our_type.name}_to_json_value")
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
928
|
+
return Stripped(
|
|
929
|
+
f"""\
|
|
930
|
+
Serialize.{method_name}(
|
|
931
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
932
|
+
)
|
|
933
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
934
|
+
return _generate_serialize_primitive_value(
|
|
935
|
+
primitive_type=our_type.constrainee, source_expr=source_expr
|
|
936
|
+
)
|
|
937
|
+
elif isinstance(
|
|
938
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
939
|
+
):
|
|
940
|
+
# We can not use textwrap due to indent_but_first_line.
|
|
941
|
+
return Stripped(
|
|
942
|
+
f"""\
|
|
943
|
+
transform(
|
|
944
|
+
{I}{indent_but_first_line(source_expr, I)})"""
|
|
945
|
+
)
|
|
946
|
+
else:
|
|
947
|
+
assert_never(our_type)
|
|
948
|
+
else:
|
|
949
|
+
assert_never(type_annotation)
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
953
|
+
def _generate_transform_property(
|
|
954
|
+
prop: intermediate.Property,
|
|
955
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
956
|
+
"""Generate the snippet to transform a property into a JSON node."""
|
|
957
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
958
|
+
|
|
959
|
+
stmts = [] # type: List[Stripped]
|
|
960
|
+
|
|
961
|
+
getter_name = java_naming.getter_name(prop.name)
|
|
962
|
+
prop_literal = java_common.string_literal(naming.json_property(prop.name))
|
|
963
|
+
|
|
964
|
+
source_expr: Stripped
|
|
965
|
+
|
|
966
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
967
|
+
source_expr = Stripped(f"that.{getter_name}().get()")
|
|
968
|
+
else:
|
|
969
|
+
source_expr = Stripped(f"that.{getter_name}()")
|
|
970
|
+
|
|
971
|
+
if isinstance(
|
|
972
|
+
type_anno,
|
|
973
|
+
intermediate.PrimitiveTypeAnnotation,
|
|
974
|
+
):
|
|
975
|
+
conversion_expr = _generate_serialize_atomic_value(
|
|
976
|
+
type_annotation=type_anno, source_expr=source_expr
|
|
977
|
+
)
|
|
978
|
+
|
|
979
|
+
# NOTE (empwilli, 2024-02-06):
|
|
980
|
+
# We have to use ObjectNode.put for Strings but the function is deprecated for JsonObjects.
|
|
981
|
+
if type_anno.a_type == intermediate.PrimitiveType.STR:
|
|
982
|
+
stmts.append(Stripped(f"result.put({prop_literal}, {conversion_expr});"))
|
|
983
|
+
else:
|
|
984
|
+
stmts.append(Stripped(f"result.set({prop_literal}, {conversion_expr});"))
|
|
985
|
+
elif isinstance(
|
|
986
|
+
type_anno,
|
|
987
|
+
intermediate.OurTypeAnnotation,
|
|
988
|
+
):
|
|
989
|
+
conversion_expr = _generate_serialize_atomic_value(
|
|
990
|
+
type_annotation=type_anno, source_expr=source_expr
|
|
991
|
+
)
|
|
992
|
+
stmts.append(Stripped(f"result.set({prop_literal}, {conversion_expr});"))
|
|
993
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
994
|
+
assert not isinstance(
|
|
995
|
+
type_anno.items,
|
|
996
|
+
(intermediate.OptionalTypeAnnotation, intermediate.ListTypeAnnotation),
|
|
997
|
+
), (
|
|
998
|
+
"We chose to implement only a very limited pattern matching; "
|
|
999
|
+
"see intermediate._translate._verify_only_simple_type_patterns."
|
|
1000
|
+
)
|
|
1001
|
+
|
|
1002
|
+
item_type = java_common.generate_type(type_anno.items)
|
|
1003
|
+
array_var = java_naming.variable_name(Identifier(f"array_{prop.name}"))
|
|
1004
|
+
|
|
1005
|
+
item_conversion_expr = _generate_serialize_atomic_value(
|
|
1006
|
+
type_annotation=type_anno.items, source_expr=Stripped("item")
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
# We cannot use textwrap due to indent_but_first_line.
|
|
1010
|
+
stmts.append(
|
|
1011
|
+
Stripped(
|
|
1012
|
+
f"""\
|
|
1013
|
+
final ArrayNode {array_var} = JsonNodeFactory.instance.arrayNode();
|
|
1014
|
+
for ({item_type} item : {source_expr}) {{
|
|
1015
|
+
{I}{array_var}.add(
|
|
1016
|
+
{II}{indent_but_first_line(item_conversion_expr, II)});
|
|
1017
|
+
}}
|
|
1018
|
+
result.set({prop_literal}, {array_var});"""
|
|
1019
|
+
)
|
|
1020
|
+
)
|
|
1021
|
+
else:
|
|
1022
|
+
assert_never(type_anno)
|
|
1023
|
+
|
|
1024
|
+
serialize_block = Stripped("\n".join(stmts))
|
|
1025
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
1026
|
+
return (
|
|
1027
|
+
Stripped(
|
|
1028
|
+
f"""\
|
|
1029
|
+
if (that.{getter_name}().isPresent()) {{
|
|
1030
|
+
{I}{indent_but_first_line(serialize_block, I)}
|
|
1031
|
+
}}"""
|
|
1032
|
+
),
|
|
1033
|
+
None,
|
|
1034
|
+
)
|
|
1035
|
+
else:
|
|
1036
|
+
return serialize_block, None
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1040
|
+
def _generate_transform_for_class(
|
|
1041
|
+
cls: intermediate.ConcreteClass,
|
|
1042
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
1043
|
+
"""Generate the transform method to a JSON object for the given concrete class."""
|
|
1044
|
+
errors = [] # type: List[Error]
|
|
1045
|
+
|
|
1046
|
+
blocks = [
|
|
1047
|
+
Stripped("final ObjectNode result = JsonNodeFactory.instance.objectNode();"),
|
|
1048
|
+
] # type: List[Stripped]
|
|
1049
|
+
|
|
1050
|
+
for prop in cls.properties:
|
|
1051
|
+
block, error = _generate_transform_property(prop=prop)
|
|
1052
|
+
if error is not None:
|
|
1053
|
+
errors.append(error)
|
|
1054
|
+
else:
|
|
1055
|
+
assert block is not None
|
|
1056
|
+
blocks.append(block)
|
|
1057
|
+
|
|
1058
|
+
if len(errors) > 0:
|
|
1059
|
+
return None, errors
|
|
1060
|
+
|
|
1061
|
+
if cls.serialization is not None and cls.serialization.with_model_type:
|
|
1062
|
+
model_type = java_common.string_literal(naming.json_model_type(cls.name))
|
|
1063
|
+
blocks.append(Stripped(f"""result.put("modelType", {model_type});"""))
|
|
1064
|
+
|
|
1065
|
+
blocks.append(Stripped("return result;"))
|
|
1066
|
+
|
|
1067
|
+
writer = io.StringIO()
|
|
1068
|
+
|
|
1069
|
+
interface_name = java_naming.interface_name(cls.name)
|
|
1070
|
+
transform_name = java_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
1071
|
+
|
|
1072
|
+
writer.write(
|
|
1073
|
+
f"""\
|
|
1074
|
+
@Override
|
|
1075
|
+
public JsonNode {transform_name}(
|
|
1076
|
+
{I}{interface_name} that
|
|
1077
|
+
) {{
|
|
1078
|
+
"""
|
|
1079
|
+
)
|
|
1080
|
+
|
|
1081
|
+
for i, stmt in enumerate(blocks):
|
|
1082
|
+
if i > 0:
|
|
1083
|
+
writer.write("\n\n")
|
|
1084
|
+
writer.write(textwrap.indent(stmt, I))
|
|
1085
|
+
|
|
1086
|
+
writer.write("\n}")
|
|
1087
|
+
|
|
1088
|
+
return Stripped(writer.getvalue()), None
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1092
|
+
def _generate_transformer(
|
|
1093
|
+
symbol_table: intermediate.SymbolTable,
|
|
1094
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1095
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
1096
|
+
"""Generate a transformer which transforms instances of the meta-model to JSON."""
|
|
1097
|
+
errors = [] # type: List[Error]
|
|
1098
|
+
|
|
1099
|
+
blocks = [
|
|
1100
|
+
Stripped(
|
|
1101
|
+
f"""\
|
|
1102
|
+
/**
|
|
1103
|
+
* Convert {{@code that}} 64-bit long integer to a JSON value.
|
|
1104
|
+
*
|
|
1105
|
+
* @param that value to be converted
|
|
1106
|
+
*/
|
|
1107
|
+
private static JsonNode toJsonNode(Long that) {{
|
|
1108
|
+
{I}// We need to check that we can perform a lossless conversion.
|
|
1109
|
+
{I}long primitiveThat = that.longValue();
|
|
1110
|
+
{I}if ((long)((double)primitiveThat) != primitiveThat) {{
|
|
1111
|
+
{II}throw new IllegalArgumentException(
|
|
1112
|
+
{III}"The number can not be losslessly represented in JSON: " + that);
|
|
1113
|
+
{I}}}
|
|
1114
|
+
{I}return JsonNodeFactory.instance.numberNode(that);
|
|
1115
|
+
}}"""
|
|
1116
|
+
),
|
|
1117
|
+
] # type: List[Stripped]
|
|
1118
|
+
|
|
1119
|
+
for our_type in symbol_table.our_types:
|
|
1120
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
1121
|
+
continue
|
|
1122
|
+
|
|
1123
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
1124
|
+
continue
|
|
1125
|
+
|
|
1126
|
+
elif isinstance(our_type, intermediate.AbstractClass):
|
|
1127
|
+
# The abstract classes are directly dispatched by the transformer,
|
|
1128
|
+
# so we do not need to handle them separately.
|
|
1129
|
+
pass
|
|
1130
|
+
|
|
1131
|
+
elif isinstance(our_type, intermediate.ConcreteClass):
|
|
1132
|
+
if our_type.is_implementation_specific:
|
|
1133
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
1134
|
+
f"Jsonization/Transformer/transform_{our_type.name}.java"
|
|
1135
|
+
)
|
|
1136
|
+
|
|
1137
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
1138
|
+
if implementation is None:
|
|
1139
|
+
errors.append(
|
|
1140
|
+
Error(
|
|
1141
|
+
our_type.parsed.node,
|
|
1142
|
+
f"The jsonization snippet is missing "
|
|
1143
|
+
f"for the implementation-specific "
|
|
1144
|
+
f"class {our_type.name}: {implementation_key}",
|
|
1145
|
+
)
|
|
1146
|
+
)
|
|
1147
|
+
continue
|
|
1148
|
+
|
|
1149
|
+
blocks.append(spec_impls[implementation_key])
|
|
1150
|
+
else:
|
|
1151
|
+
block, cls_errors = _generate_transform_for_class(cls=our_type)
|
|
1152
|
+
if cls_errors is not None:
|
|
1153
|
+
errors.extend(cls_errors)
|
|
1154
|
+
else:
|
|
1155
|
+
assert block is not None
|
|
1156
|
+
blocks.append(block)
|
|
1157
|
+
else:
|
|
1158
|
+
assert_never(our_type)
|
|
1159
|
+
|
|
1160
|
+
if len(errors) > 0:
|
|
1161
|
+
return None, errors
|
|
1162
|
+
|
|
1163
|
+
writer = io.StringIO()
|
|
1164
|
+
writer.write(
|
|
1165
|
+
"""\
|
|
1166
|
+
private static class Transformer extends AbstractTransformer<JsonNode> {
|
|
1167
|
+
"""
|
|
1168
|
+
)
|
|
1169
|
+
|
|
1170
|
+
for i, block in enumerate(blocks):
|
|
1171
|
+
if i > 0:
|
|
1172
|
+
writer.write("\n\n")
|
|
1173
|
+
writer.write(textwrap.indent(block, I))
|
|
1174
|
+
|
|
1175
|
+
writer.write("\n}")
|
|
1176
|
+
|
|
1177
|
+
return Stripped(writer.getvalue()), None
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
def _generate_serialize(
|
|
1181
|
+
symbol_table: intermediate.SymbolTable,
|
|
1182
|
+
) -> Stripped:
|
|
1183
|
+
"""Generate the static serializer."""
|
|
1184
|
+
blocks = [
|
|
1185
|
+
Stripped("private static final Transformer transformer = new Transformer();"),
|
|
1186
|
+
Stripped(
|
|
1187
|
+
f"""\
|
|
1188
|
+
/**
|
|
1189
|
+
* Serialize an instance of the meta-model into a JSON object.
|
|
1190
|
+
*/
|
|
1191
|
+
public static JsonNode toJsonObject(IClass that) {{
|
|
1192
|
+
{I}return transformer.transform(that);
|
|
1193
|
+
}}"""
|
|
1194
|
+
),
|
|
1195
|
+
] # type: List[Stripped]
|
|
1196
|
+
|
|
1197
|
+
for enum in symbol_table.enumerations:
|
|
1198
|
+
name = java_naming.enum_name(enum.name)
|
|
1199
|
+
method_name = java_naming.method_name(Identifier(f"{enum.name}_to_json_value"))
|
|
1200
|
+
blocks.append(
|
|
1201
|
+
Stripped(
|
|
1202
|
+
f"""\
|
|
1203
|
+
/**
|
|
1204
|
+
* Serialize a literal of {name} into a JSON string.
|
|
1205
|
+
*/
|
|
1206
|
+
public static JsonNode {method_name}({name} that) {{
|
|
1207
|
+
{I}Optional<String> text = Stringification.toString(that);
|
|
1208
|
+
{I}if (!text.isPresent()) {{
|
|
1209
|
+
{II}throw new IllegalArgumentException("Invalid {name}: " + that);
|
|
1210
|
+
{I}}}
|
|
1211
|
+
|
|
1212
|
+
{I}return JsonNodeFactory.instance.textNode(text.get());
|
|
1213
|
+
}}"""
|
|
1214
|
+
)
|
|
1215
|
+
)
|
|
1216
|
+
|
|
1217
|
+
writer = io.StringIO()
|
|
1218
|
+
|
|
1219
|
+
writer.write(
|
|
1220
|
+
"""\
|
|
1221
|
+
/**
|
|
1222
|
+
* Serialize instances of meta-model classes to JSON elements.
|
|
1223
|
+
*
|
|
1224
|
+
"""
|
|
1225
|
+
)
|
|
1226
|
+
|
|
1227
|
+
first_cls = (
|
|
1228
|
+
symbol_table.classes[0] if len(symbol_table.classes) > 0 else None
|
|
1229
|
+
) # type: Optional[intermediate.ClassUnion]
|
|
1230
|
+
|
|
1231
|
+
if first_cls is not None:
|
|
1232
|
+
cls_name = None # type: Optional[str]
|
|
1233
|
+
if isinstance(first_cls, intermediate.AbstractClass):
|
|
1234
|
+
cls_name = java_naming.interface_name(first_cls.name)
|
|
1235
|
+
elif isinstance(first_cls, intermediate.ConcreteClass):
|
|
1236
|
+
cls_name = java_naming.class_name(first_cls.name)
|
|
1237
|
+
else:
|
|
1238
|
+
assert_never(first_cls)
|
|
1239
|
+
|
|
1240
|
+
an_instance_variable = java_naming.variable_name(Identifier("an_instance"))
|
|
1241
|
+
|
|
1242
|
+
writer.write(
|
|
1243
|
+
f"""\
|
|
1244
|
+
* Here is an example how to serialize an instance of {cls_name}:
|
|
1245
|
+
* <pre>{{@code
|
|
1246
|
+
* {cls_name} {an_instance_variable} = new {cls_name}(
|
|
1247
|
+
* // ... some constructor arguments ...
|
|
1248
|
+
* );
|
|
1249
|
+
* JsonNode element = Jsonization.Serialize.toJsonObject(
|
|
1250
|
+
* {II}{an_instance_variable}));
|
|
1251
|
+
* }}</pre>
|
|
1252
|
+
*/
|
|
1253
|
+
"""
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1256
|
+
writer.write(
|
|
1257
|
+
"""\
|
|
1258
|
+
public static class Serialize
|
|
1259
|
+
{
|
|
1260
|
+
"""
|
|
1261
|
+
)
|
|
1262
|
+
|
|
1263
|
+
for i, block in enumerate(blocks):
|
|
1264
|
+
if i > 0:
|
|
1265
|
+
writer.write("\n\n")
|
|
1266
|
+
writer.write(textwrap.indent(block, I))
|
|
1267
|
+
|
|
1268
|
+
writer.write("\n}")
|
|
1269
|
+
|
|
1270
|
+
return Stripped(writer.getvalue())
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
# fmt: off
|
|
1274
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1275
|
+
@ensure(
|
|
1276
|
+
lambda result:
|
|
1277
|
+
not (result[0] is not None) or result[0].endswith('\n'),
|
|
1278
|
+
"Trailing newline mandatory for valid end-of-files"
|
|
1279
|
+
)
|
|
1280
|
+
# fmt: on
|
|
1281
|
+
def generate(
|
|
1282
|
+
symbol_table: intermediate.SymbolTable,
|
|
1283
|
+
package: java_common.PackageIdentifier,
|
|
1284
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1285
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
1286
|
+
"""
|
|
1287
|
+
Generate the Java code for the general serialization.
|
|
1288
|
+
|
|
1289
|
+
The ``package`` defines the AAS Java package.
|
|
1290
|
+
"""
|
|
1291
|
+
errors = [] # type: List[Error]
|
|
1292
|
+
|
|
1293
|
+
imports = [
|
|
1294
|
+
Stripped("import aas_core.aas3_0.reporting.Reporting;"),
|
|
1295
|
+
Stripped("import aas_core.aas3_0.types.enums.*;"),
|
|
1296
|
+
Stripped("import aas_core.aas3_0.types.impl.*;"),
|
|
1297
|
+
Stripped("import aas_core.aas3_0.types.model.*;"),
|
|
1298
|
+
Stripped("import aas_core.aas3_0.stringification.Stringification;"),
|
|
1299
|
+
Stripped("import aas_core.aas3_0.visitation.AbstractTransformer;"),
|
|
1300
|
+
Stripped("import com.fasterxml.jackson.databind.JsonNode;"),
|
|
1301
|
+
Stripped("import com.fasterxml.jackson.databind.node.ArrayNode;"),
|
|
1302
|
+
Stripped("import com.fasterxml.jackson.databind.node.JsonNodeFactory;"),
|
|
1303
|
+
Stripped("import com.fasterxml.jackson.databind.node.ObjectNode;"),
|
|
1304
|
+
Stripped("import java.util.*;"),
|
|
1305
|
+
Stripped("import java.util.function.Function;"),
|
|
1306
|
+
] # type: List[Stripped]
|
|
1307
|
+
|
|
1308
|
+
deserialize_impl_block, deserialize_impl_errors = _generate_deserialize_impl(
|
|
1309
|
+
symbol_table=symbol_table, spec_impls=spec_impls
|
|
1310
|
+
)
|
|
1311
|
+
if deserialize_impl_errors is not None:
|
|
1312
|
+
errors.extend(deserialize_impl_errors)
|
|
1313
|
+
|
|
1314
|
+
deserialize_block = _generate_deserialize(symbol_table=symbol_table)
|
|
1315
|
+
|
|
1316
|
+
transformer_block, transformer_errors = _generate_transformer(
|
|
1317
|
+
symbol_table=symbol_table, spec_impls=spec_impls
|
|
1318
|
+
)
|
|
1319
|
+
if transformer_errors is not None:
|
|
1320
|
+
errors.extend(transformer_errors)
|
|
1321
|
+
|
|
1322
|
+
if len(errors) > 0:
|
|
1323
|
+
return None, errors
|
|
1324
|
+
|
|
1325
|
+
assert deserialize_impl_block is not None
|
|
1326
|
+
assert deserialize_block is not None
|
|
1327
|
+
assert transformer_block is not None
|
|
1328
|
+
|
|
1329
|
+
serialize_block = _generate_serialize(
|
|
1330
|
+
symbol_table=symbol_table,
|
|
1331
|
+
)
|
|
1332
|
+
|
|
1333
|
+
exception_block = Stripped(
|
|
1334
|
+
f"""\
|
|
1335
|
+
/**
|
|
1336
|
+
* Represent a critical error during the deserialization.
|
|
1337
|
+
*/
|
|
1338
|
+
@SuppressWarnings("serial")
|
|
1339
|
+
{I}public static class DeserializeException extends RuntimeException {{
|
|
1340
|
+
{II}private final String path;
|
|
1341
|
+
{II}private final String reason;
|
|
1342
|
+
|
|
1343
|
+
{II}public DeserializeException(String path, String reason) {{
|
|
1344
|
+
{III}super(reason + " at: " + ("".equals(path) ? "the beginning" : path));
|
|
1345
|
+
{III}this.path = path;
|
|
1346
|
+
{III}this.reason = reason;
|
|
1347
|
+
{II}}}
|
|
1348
|
+
|
|
1349
|
+
{II}public Optional<String> getPath() {{
|
|
1350
|
+
{III}return Optional.ofNullable(path);
|
|
1351
|
+
{II}}}
|
|
1352
|
+
|
|
1353
|
+
{II}public Optional<String> getReason() {{
|
|
1354
|
+
{III}return Optional.ofNullable(reason);
|
|
1355
|
+
{II}}}
|
|
1356
|
+
{I}}}"""
|
|
1357
|
+
)
|
|
1358
|
+
|
|
1359
|
+
result_block = Stripped(
|
|
1360
|
+
f"""\
|
|
1361
|
+
private static class Result<T> {{
|
|
1362
|
+
{I}private final T result;
|
|
1363
|
+
{I}private final Reporting.Error error;
|
|
1364
|
+
{I}private final boolean success;
|
|
1365
|
+
|
|
1366
|
+
{I}private Result(T result, Reporting.Error error, boolean success) {{
|
|
1367
|
+
{II}this.result = result;
|
|
1368
|
+
{II}this.error = error;
|
|
1369
|
+
{II}this.success = success;
|
|
1370
|
+
{I}}}
|
|
1371
|
+
|
|
1372
|
+
{I}public static <T> Result<T> success(T result) {{
|
|
1373
|
+
{II}if (result == null) throw new IllegalArgumentException("Result must not be null.");
|
|
1374
|
+
{II}return new Result<>(result, null, true);
|
|
1375
|
+
{I}}}
|
|
1376
|
+
|
|
1377
|
+
{I}public static <T> Result<T> failure(Reporting.Error error) {{
|
|
1378
|
+
{II}if (error == null) throw new IllegalArgumentException("Error must not be null.");
|
|
1379
|
+
{II}return new Result<>(null, error, false);
|
|
1380
|
+
{I}}}
|
|
1381
|
+
|
|
1382
|
+
{I}@SuppressWarnings("unchecked")
|
|
1383
|
+
{I}public <I> Result<I> castTo(Class<I> type) {{
|
|
1384
|
+
{II}if (isError() || type.isInstance(result)) return (Result<I>) this;
|
|
1385
|
+
{II}throw new IllegalStateException("Result of type "
|
|
1386
|
+
{III}+ result.getClass().getName()
|
|
1387
|
+
{III}+ " is not an instance of "
|
|
1388
|
+
{III}+ type.getName());
|
|
1389
|
+
{I}}}
|
|
1390
|
+
|
|
1391
|
+
{I}public T getResult() {{
|
|
1392
|
+
{II}if (!isSuccess()) throw new IllegalStateException("Result is not present.");
|
|
1393
|
+
{II}return result;
|
|
1394
|
+
{I}}}
|
|
1395
|
+
|
|
1396
|
+
{I}public boolean isSuccess() {{
|
|
1397
|
+
{II}return success;
|
|
1398
|
+
{I}}}
|
|
1399
|
+
|
|
1400
|
+
{I}public boolean isError() {{
|
|
1401
|
+
{II}return !success;
|
|
1402
|
+
{I}}}
|
|
1403
|
+
|
|
1404
|
+
{I}public Reporting.Error getError() {{
|
|
1405
|
+
{II}if (isSuccess()) throw new IllegalStateException("Result is present.");
|
|
1406
|
+
{II}return error;
|
|
1407
|
+
{I}}}
|
|
1408
|
+
|
|
1409
|
+
{I}public <R> R map(Function<T, R> successFunction, Function<Reporting.Error, R> errorFunction) {{
|
|
1410
|
+
{II}return isSuccess() ? successFunction.apply(result) : errorFunction.apply(error);
|
|
1411
|
+
{I}}}
|
|
1412
|
+
|
|
1413
|
+
{I}public T onError(Function<Reporting.Error, T> errorFunction) {{
|
|
1414
|
+
{II}return map(Function.identity(), errorFunction);
|
|
1415
|
+
{I}}}
|
|
1416
|
+
}}"""
|
|
1417
|
+
)
|
|
1418
|
+
|
|
1419
|
+
jsonization_blocks = [
|
|
1420
|
+
deserialize_impl_block,
|
|
1421
|
+
exception_block,
|
|
1422
|
+
result_block,
|
|
1423
|
+
deserialize_block,
|
|
1424
|
+
transformer_block,
|
|
1425
|
+
serialize_block,
|
|
1426
|
+
] # type: List[Stripped]
|
|
1427
|
+
|
|
1428
|
+
jsonization_writer = io.StringIO()
|
|
1429
|
+
jsonization_writer.write(
|
|
1430
|
+
"""\
|
|
1431
|
+
/**
|
|
1432
|
+
* Provide de/serialization of meta-model classes to/from JSON.
|
|
1433
|
+
*
|
|
1434
|
+
* <p>We can not use one-pass deserialization for JSON since the object
|
|
1435
|
+
* properties do not have fixed order, and hence we can not read
|
|
1436
|
+
* {@code modelType} property ahead of the remaining properties.
|
|
1437
|
+
*/
|
|
1438
|
+
public class Jsonization {
|
|
1439
|
+
"""
|
|
1440
|
+
)
|
|
1441
|
+
|
|
1442
|
+
for i, deserialize_block in enumerate(jsonization_blocks):
|
|
1443
|
+
if i > 0:
|
|
1444
|
+
jsonization_writer.write("\n\n")
|
|
1445
|
+
|
|
1446
|
+
jsonization_writer.write(textwrap.indent(deserialize_block, II))
|
|
1447
|
+
|
|
1448
|
+
jsonization_writer.write("\n}")
|
|
1449
|
+
|
|
1450
|
+
if len(errors) > 0:
|
|
1451
|
+
return None, errors
|
|
1452
|
+
|
|
1453
|
+
blocks = [
|
|
1454
|
+
java_common.WARNING,
|
|
1455
|
+
Stripped(f"package {package}.jsonization;"),
|
|
1456
|
+
Stripped("\n".join(imports)),
|
|
1457
|
+
Stripped(jsonization_writer.getvalue()),
|
|
1458
|
+
java_common.WARNING,
|
|
1459
|
+
] # type: List[Stripped]
|
|
1460
|
+
|
|
1461
|
+
writer = io.StringIO()
|
|
1462
|
+
for i, block in enumerate(blocks):
|
|
1463
|
+
if i > 0:
|
|
1464
|
+
writer.write("\n\n")
|
|
1465
|
+
|
|
1466
|
+
assert not block.startswith("\n")
|
|
1467
|
+
assert not block.endswith("\n")
|
|
1468
|
+
writer.write(block)
|
|
1469
|
+
|
|
1470
|
+
writer.write("\n")
|
|
1471
|
+
|
|
1472
|
+
return writer.getvalue(), None
|