From 1335824f6b864748247891a0bf05b8dabc5f0b6b Mon Sep 17 00:00:00 2001 From: JvD_Ericsson Date: Fri, 9 Aug 2024 10:38:46 +0100 Subject: [PATCH] Add classifiers and decorators Added classifiers and decorators Refactored code Issue-ID: SMO-162 Change-Id: I1cd982505abc7b47b58dbb3bf5472e99b053985b Signed-off-by: JvD_Ericsson --- .../charts/topology-exposure-inventory/values.yaml | 5 +- charts/smo/topology-exposure-inventory/values.yaml | 3 - .../antlr4/org/oran/smo/teiv/antlr4/tiesPath.g4 | 11 +- .../main/java/org/oran/smo/teiv/CustomMetrics.java | 28 +- .../availability/DependentServiceAvailability.java | 9 +- .../DependentServiceAvailabilityKafka.java | 11 +- .../org/oran/smo/teiv/config/DataSourceConfig.java | 5 + .../org/oran/smo/teiv/config/KafkaAdminConfig.java | 2 - .../java/org/oran/smo/teiv/config/KafkaConfig.java | 13 +- .../health/TiesExposureHealthIndicator.java | 28 +- .../controller/health/TiesHealthIndicator.java | 59 + .../health/TiesIngestionHealthIndicator.java | 45 +- .../exception/InvalidRelationshipException.java | 27 + .../org/oran/smo/teiv/exception/TiesException.java | 47 + .../oran/smo/teiv/exposure/audit/AuditInfo.java} | 29 +- .../oran/smo/teiv/exposure/audit/AuditMapper.java | 42 + .../smo/teiv/exposure/audit/LoggerHandler.java} | 35 +- .../classifiers/api/ClassifiersService.java | 33 + .../api/impl/ClassifiersServiceImpl.java | 124 ++ .../rest/controller/ClassifiersRestController.java | 67 +- .../ConsumerDataOperationRegistry.java | 69 + .../ConsumerDataRepository.java} | 44 +- .../consumerdata/ConsumerDataRepositoryImpl.java | 134 ++ .../consumerdata/ConsumerDataValidator.java | 101 ++ .../model/Classifiers.java} | 19 +- .../exposure/consumerdata/model/ConsumerData.java | 46 + .../exposure/consumerdata/model/Decorators.java | 31 + .../consumerdata/model/PersistableIdMap.java | 32 + .../operation/ClassifiersOperation.java | 60 + .../operation/ConsumerDataOperation.java | 160 ++ .../operation/DecoratorsOperation.java | 56 + .../operation/DeleteClassifiersOperation.java | 125 ++ .../operation/DeleteDecoratorsOperation.java | 119 ++ .../operation/MergeClassifiersOperation.java | 93 ++ .../operation/MergeDecoratorsOperation.java | 97 ++ .../smo/teiv/exposure/data/api/DataService.java | 60 +- .../exposure/data/api/impl/DataServiceImpl.java | 362 ++--- ...DataRestController.java => DataController.java} | 97 +- .../exposure/decorators/api/DecoratorsService.java | 33 + .../decorators/api/impl/DecoratorsServiceImpl.java | 142 ++ .../rest/controller/DecoratorsRestController.java | 67 +- .../{ModelSchemaService.java => ModelService.java} | 38 +- .../model/api/impl/ModelSchemaServiceImpl.java | 117 -- .../exposure/model/api/impl/ModelServiceImpl.java | 157 ++ ...emaRestController.java => ModelController.java} | 81 +- .../teiv/exposure/spi/DataPersistanceService.java | 197 --- .../oran/smo/teiv/exposure/spi/DataRepository.java | 130 ++ .../smo/teiv/exposure/spi/ModelRepository.java | 101 ++ .../smo/teiv/{schema => exposure/spi}/Module.java | 21 +- .../oran/smo/teiv/exposure/spi/ModuleStatus.java | 29 + .../spi/impl/DataPersistanceServiceImpl.java | 289 ---- .../teiv/exposure/spi/impl/DataRepositoryImpl.java | 191 +++ .../exposure/spi/impl/ModelRepositoryImpl.java | 170 ++ .../teiv/exposure/spi/mapper/ComplexMapper.java | 102 -- .../smo/teiv/exposure/spi/mapper/EntityMapper.java | 59 +- .../teiv/exposure/spi/mapper/MapperUtility.java | 209 --- .../smo/teiv/exposure/spi/mapper/PageMetaData.java | 51 - .../exposure/spi/mapper/PaginationMetaData.java | 74 - .../teiv/exposure/spi/mapper/QueryMetaData.java | 59 - .../exposure/spi/mapper/RelationshipMapper.java | 34 +- .../exposure/spi/mapper/RelationshipsMapper.java | 50 - .../teiv/exposure/spi/mapper/ResponseMapper.java | 68 +- .../tiespath/innerlanguage/AndOrLogicalBlock.java | 16 +- .../tiespath/innerlanguage/ConditionFactory.java | 495 ++++++ .../tiespath/innerlanguage/ContainerType.java | 22 +- .../tiespath/innerlanguage/EmptyLogicalBlock.java | 13 +- .../tiespath/innerlanguage/FilterCriteria.java | 65 +- .../innerlanguage/InnerFilterCriteria.java | 163 ++ .../tiespath/innerlanguage/LogicalBlock.java | 6 +- .../tiespath/innerlanguage/QueryFunction.java | 24 +- .../tiespath/innerlanguage/ScopeLogicalBlock.java | 110 +- .../tiespath/innerlanguage/ScopeObject.java | 24 +- .../tiespath/innerlanguage/TargetObject.java | 8 +- .../exposure/tiespath/refiner/AliasMapper.java | 86 ++ .../tiespath/refiner/BasePathRefinement.java | 735 ++++++++- .../tiespath/refiner/PathToJooqRefinement.java | 161 +- .../exposure/tiespath/resolver/PathResolver.java | 66 +- .../tiespath/resolver/ResolverDataType.java} | 10 +- .../exposure/tiespath/resolver/ResolverUtil.java | 87 ++ .../tiespath/resolver/ScopeFilterListener.java | 185 +++ .../exposure/tiespath/resolver/ScopeResolver.java | 99 ++ .../tiespath/resolver/TargetFilterListener.java | 109 ++ .../exposure/tiespath/resolver/TargetResolver.java | 93 +- .../smo/teiv/exposure/utils/PaginationDTO.java | 89 -- .../smo/teiv/exposure/utils/PaginationUtil.java | 159 ++ .../RequestDetails.java} | 29 +- .../smo/teiv/exposure/utils/RequestValidator.java | 17 +- .../smo/teiv/listener/CreateTopologyProcessor.java | 1 + .../smo/teiv/listener/DeleteTopologyProcessor.java | 28 +- .../smo/teiv/listener/MergeTopologyProcessor.java | 1 + .../SourceEntityDeleteTopologyProcessor.java | 6 +- .../SourceEntityDeleteTopologyProcessorV1.java | 112 -- .../oran/smo/teiv/listener/TopologyListener.java | 2 +- .../teiv/listener/TopologyProcessorRegistry.java | 9 +- .../org/oran/smo/teiv/schema/BidiDbNameMapper.java | 3 + .../oran/smo/teiv/schema/ConsumerDataCache.java | 12 +- .../java/org/oran/smo/teiv/schema/DataType.java | 2 + .../java/org/oran/smo/teiv/schema/EntityType.java | 111 +- .../java/org/oran/smo/teiv/schema/Persistable.java | 71 +- .../oran/smo/teiv/schema/PostgresSchemaLoader.java | 114 +- .../org/oran/smo/teiv/schema/RelationType.java | 122 +- .../org/oran/smo/teiv/schema/SchemaRegistry.java | 271 ++-- .../smo/teiv/schema/SchemaRegistryErrorCode.java | 31 + .../smo/teiv/schema/SchemaRegistryException.java | 36 + .../org/oran/smo/teiv/schema/YangDataTypes.java | 47 + .../smo/teiv/service/SchemaCleanUpService.java | 205 +++ .../oran/smo/teiv/service/TiesDbOperations.java | 152 +- .../org/oran/smo/teiv/service/TiesDbService.java | 8 - .../teiv/service/cloudevent/CloudEventParser.java | 122 +- .../smo/teiv/service/cloudevent/data/Entity.java | 6 +- .../teiv/service/cloudevent/data/ModuleObject.java | 6 +- .../cloudevent/data/ParsedCloudEventData.java | 22 + .../teiv/service/cloudevent/data/Relationship.java | 8 + .../service/kafka/KafkaAddressSupplierConfig.java | 2 - .../oran/smo/teiv/service/kafka/KafkaFactory.java | 6 +- .../smo/teiv/service/models/OperationResult.java | 77 +- .../org/oran/smo/teiv/startup/SchemaHandler.java | 15 + .../org/oran/smo/teiv/utils/CloudEventUtil.java | 12 + .../org/oran/smo/teiv/utils/JooqTypeConverter.java | 118 ++ .../org/oran/smo/teiv/utils/PersistableUtil.java | 34 + .../org/oran/smo/teiv/utils/TiesConstants.java | 16 +- .../java/org/oran/smo/teiv/utils/YangParser.java | 127 ++ .../oran/smo/teiv/utils/query/QueryElement.java | 126 -- .../org/oran/smo/teiv/utils/query/QueryMonad.java | 989 ------------ .../utils/query/exception/TiesPathException.java | 32 +- teiv/src/main/resources/application.yaml | 19 +- teiv/src/main/resources/logback-json.xml | 41 +- .../org/oran/smo/teiv/CoreApplicationTest.java | 48 +- .../health/TiesExposureHealthIndicatorTest.java | 37 +- .../health/TiesIngestionHealthIndicatorTest.java | 11 +- .../oran/smo/teiv/db/TestPostgresqlContainer.java | 12 +- .../smo/teiv/db/TestPostgresqlContainerV1.java | 85 + ...DataControllerE2EContainerizedNonXPathTest.java | 317 ---- .../e2e/DataControllerE2EContainerizedTest.java | 249 --- .../api/contract/TopologyExposureApiBase.java | 176 +-- .../contract/utils/RelationshipTestUtility.java | 86 -- .../contract/utils/TopologyObjectTestUtility.java | 164 -- .../data/api/impl/DataServiceImplTest.java | 654 -------- .../data/api/impl/ExposureMetricsTest.java | 139 +- .../rest/controller/DataRestControllerTest.java | 573 ------- ...nceServiceImplGETRequestsContainerizedTest.java | 1190 -------------- ...RepositoryImplGETRequestsContainerizedTest.java | 180 +++ .../exposure/spi/mapper/ComplexMapperTest.java | 77 - .../teiv/exposure/spi/mapper/EntityMapperTest.java | 60 +- .../exposure/spi/mapper/MapperUtilityTest.java | 178 --- .../spi/mapper/PaginationMetaDataTest.java | 139 -- .../spi/mapper/RelationshipMapperTest.java | 54 +- .../spi/mapper/RelationshipsMapperTest.java | 75 - .../tiespath/innerlanguage/DtoToJooqTest.java | 1214 +++++++++++++++ .../tiespath/innerlanguage/FilterCriteriaTest.java | 143 +- .../innerlanguage/ScopeLogicalBlockTest.java | 130 ++ .../tiespath/innerlanguage/SelectBlockTest.java | 250 +++ .../exposure/tiespath/refiner/AliasMapperTest.java | 46 + .../tiespath/refiner/BasePathRefinementTest.java | 1197 +++++++++++++-- .../tiespath/refiner/PathToJooqRefinementTest.java | 70 +- .../tiespath/resolver/ScopeResolverTest.java | 284 ++++ .../tiespath/resolver/TargetResolverTest.java | 61 +- .../teiv/exposure/utils/PaginationUtilTest.java | 120 ++ .../teiv/exposure/utils/RequestValidatorTest.java | 14 +- .../IngestionOperationValidatorTest.java | 173 +-- .../teiv/listener/CreateTopologyProcessorTest.java | 12 +- .../teiv/listener/DeleteTopologyProcessorTest.java | 38 +- .../teiv/listener/MergeTopologyProcessorTest.java | 21 +- .../SourceEntityDeleteTopologyProcessorTest.java | 84 +- .../SourceEntityDeleteTopologyProcessorV1Test.java | 196 --- .../smo/teiv/schema/ConsumerDataCacheTest.java | 19 +- .../org/oran/smo/teiv/schema/MockSchemaLoader.java | 651 ++------ .../schema/SchemaRegistryContainerizedTest.java | 402 ----- .../oran/smo/teiv/schema/SchemaRegistryTest.java | 496 ++++++ .../org/oran/smo/teiv/service/EndToEndApiTest.java | 263 ---- .../org/oran/smo/teiv/service/EndToEndDbTest.java | 367 +++-- .../smo/teiv/service/ModelSchemaServiceTest.java | 206 --- .../smo/teiv/service/SchemaCleanUpServiceTest.java | 112 ++ .../teiv/service/TiesDbOperationResultsTest.java | 347 +++-- .../service/TiesDbServiceContainerizedTest.java | 248 +-- .../service/cloudevent/CloudEventParserTest.java | 207 ++- .../cloudevent/data/ParsedCloudEventDataTest.java | 105 ++ .../smo/teiv/utils/ConvertToJooqTypeUtilTest.java | 58 - .../smo/teiv/utils/EndToEndExpectedResults.java | 68 +- .../org/oran/smo/teiv/utils/TiesTestConstants.java | 27 + .../utils/exposure/PaginationVerifierTestUtil.java | 58 - .../oran/smo/teiv/utils/query/QueryMonadTest.java | 1616 -------------------- .../smo/teiv/utils/query/QueryMonadTestUtil.java | 46 - teiv/src/test/resources/application.yaml | 18 +- .../resources/cloudeventdata/common/ce-arrays.json | 53 + .../cloudeventdata/common/ce-data-only.json | 104 -- .../common/ce-invalid-entity-attribute.json | 24 + .../ce-relationship-invalid-module-type-pair.json | 28 + .../common/ce-relationship-invalid-module.json | 28 + .../common/ce-relationship-invalid-type.json | 28 + .../common/ce-relationship-missing-a-side.json | 27 + .../common/ce-relationship-missing-b-side.json | 27 + .../common/ce-relationship-missing-both-sides.json | 26 + .../common/ce-relationship-missing-id.json | 27 + .../cloudeventdata/common/ce-with-data.json | 19 +- .../common/ce-with-invalid-relationship-ids.json | 75 + .../common/ce-with-invalid-relationship-ids2.json | 75 + .../common/ce-with-invalid-relationship-ids3.json | 75 + .../end-to-end/ce-create-geo-location.json | 6 +- .../end-to-end/ce-create-many-to-many.json | 14 +- .../end-to-end/ce-create-many-to-one.json | 12 +- .../end-to-end/ce-create-one-to-many.json | 16 +- .../end-to-end/ce-create-one-to-one.json | 6 +- ...create-relationship-connecting-same-entity.json | 10 +- .../end-to-end/ce-create-second-case.json | 22 +- .../end-to-end/ce-delete-managed-element.json | 20 + .../end-to-end/ce-delete-many-to-many.json | 6 +- .../end-to-end/ce-delete-many-to-one.json | 6 +- .../end-to-end/ce-delete-one-to-many.json | 6 +- .../end-to-end/ce-delete-one-to-one.json | 4 +- ...delete-relationship-connecting-same-entity.json | 6 +- .../end-to-end/ce-merge-long-names.json | 30 +- .../end-to-end/ce-merge-one-to-many.json | 101 ++ .../end-to-end/ce-merge-one-to-many2.json | 30 +- .../api/exp-create-many-to-many.json | 14 - .../api/exp-create-many-to-one.json | 5 - .../api/exp-create-one-to-many.json | 5 - ...create-relationship-connecting-same-entity.json | 11 - .../api/exp-create-second-case.json | 24 - .../api/exp-delete-many-to-many.json | 20 - .../api/exp-delete-many-to-one.json | 11 - .../api/exp-delete-one-to-many.json | 11 - ...delete-relationship-connecting-same-entity.json | 17 - .../api/exp-merge-one-to-many.json | 20 - .../api/exp-source-entity-delete-cm-handle.json | 14 - .../db/exp-create-many-to-many.json | 84 - .../db/exp-create-many-to-one2.json | 17 - .../db/exp-create-many-to-one3.json | 13 - .../db/exp-create-many-to-one5.json | 14 - .../expected-results/db/exp-create-one-to-one.json | 18 - .../db/exp-create-second-case.json | 169 -- .../expected-results/db/exp-delete-one-to-one.json | 15 - .../expected-results/db/exp-merge-one-to-many.json | 150 -- .../expected-results/exp-create-many-to-many.json | 98 ++ .../expected-results/exp-create-one-to-one.json | 22 + .../expected-results/exp-create-second-case.json | 185 +++ .../expected-results/exp-delete-one-to-one.json | 19 + .../expected-results/exp-merge-one-to-many.json | 142 ++ .../not-exp-delete-many-to-many.json | 18 + .../not-exp-delete-one-to-one.json | 11 + .../not-exp-source-entity-delete-cm-handle.json | 15 + .../end-to-end/olde2e/ce-create-geo-location.json | 31 + .../end-to-end/olde2e/ce-create-many-to-many.json | 137 ++ .../end-to-end/olde2e/ce-create-many-to-one.json | 76 + .../end-to-end/olde2e/ce-create-one-to-many.json | 56 + .../end-to-end/olde2e/ce-create-one-to-one.json | 61 + ...create-relationship-connecting-same-entity.json | 86 ++ .../end-to-end/olde2e/ce-create-second-case.json | 114 ++ .../olde2e/ce-delete-managed-element.json | 20 + .../end-to-end/olde2e/ce-delete-many-to-many.json | 36 + .../end-to-end/olde2e/ce-delete-many-to-one.json | 36 + .../end-to-end/olde2e/ce-delete-one-to-many.json | 36 + .../end-to-end/olde2e/ce-delete-one-to-one.json | 29 + ...delete-relationship-connecting-same-entity.json | 39 + .../end-to-end/olde2e/ce-merge-long-names.json | 364 +++++ .../ce-merge-one-to-many-deprecated-structure.json | 95 ++ .../end-to-end/olde2e/ce-merge-one-to-many2.json | 86 ++ .../olde2e/ce-source-entity-delete-cm-handle.json | 13 + .../olde2e/ce-source-entity-delete-cm-handle2.json | 13 + .../ce-create-many-to-one-geolocation.json | 54 + .../ce-create-many-to-one-geolocation2.json | 39 + .../many-to-one/ce-create-many-to-one.json | 58 +- .../many-to-one/ce-create-many-to-one2.json | 58 +- .../many-to-one/ce-create-many-to-one3.json | 44 +- .../many-to-one/ce-create-many-to-one4.json | 20 +- .../many-to-one/ce-create-many-to-one5.json | 38 +- .../many-to-one/ce-create-many-to-one6.json | 44 +- .../many-to-one/ce-create-many-to-one7.json | 20 +- .../many-to-one/ce-create-many-to-one8.json | 38 +- .../one-to-many/ce-create-one-to-many.json | 52 +- .../one-to-many/ce-create-one-to-many2.json | 52 +- .../one-to-many/ce-create-one-to-many3.json | 38 +- .../one-to-many/ce-create-one-to-many4.json | 20 +- .../one-to-many/ce-create-one-to-many5.json | 38 +- .../one-to-many/ce-create-one-to-many6.json | 38 +- .../one-to-many/ce-create-one-to-many7.json | 20 +- .../one-to-many/ce-create-one-to-many8.json | 38 +- .../one-to-one/ce-create-one-to-one.json | 6 +- .../one-to-one/ce-create-one-to-one2.json | 6 +- .../one-to-one/ce-create-one-to-one3.json | 38 +- .../one-to-one/ce-create-one-to-one4.json | 20 +- .../one-to-one/ce-create-one-to-one5.json | 38 +- .../one-to-one/ce-create-one-to-one6.json | 38 +- .../one-to-one/ce-create-one-to-one7.json | 20 +- .../one-to-one/ce-create-one-to-one8.json | 38 +- ...tClassifiers_getTopologyByEntityTypeName.groovy | 324 ++++ ...01_getClassifiers_getRelationshipsByType.groovy | 250 +++ .../02_getClassifiers_getEntitiesByDomain.groovy | 163 ++ .../classifiers/03_postClassifiers_merge.groovy | 129 ++ .../classifiers/04_postClassifiers_delete.groovy | 237 +++ .../contracts/data/00_getAllDomains.groovy | 240 +++ .../data/01_getTopologyEntityTypes.groovy | 534 +++++++ .../data/02_getTopologyByEntityTypeName.groovy | 1488 ++++++++++++++++++ .../contracts/data/03_getTopologyById.groovy | 110 ++ .../data/04_getAllRelationshipsForEntityId.groovy | 693 +++++++++ .../contracts/data/05_getRelationshipTypes.groovy | 589 +++++++ .../data/06_getRelationshipsByType.groovy | 707 +++++++++ .../contracts/data/07_getRelationshipById.groovy | 90 ++ .../contracts/data/08_getEntitiesByDomain.groovy | 784 ++++++++++ ...etDecorators_getTopologyByEntityTypeName.groovy | 236 +++ .../01_getDecorators_getRelationshipsByType.groovy | 236 +++ .../02_getDecorators_getEntitiesByDomain.groovy | 236 +++ .../decorators/03_postDecoratorsMerge.groovy | 310 ++++ .../decorators/04_postDecoratorsDelete.groovy | 301 ++++ .../ran/GNBDUFunction/getAllRelationships.groovy | 87 -- .../ran/GNBDUFunction/getTopologyById.groovy | 128 -- .../ran/GNBDUFunction/getTopologyByType.groovy | 162 -- .../contracts/ran/NRCellDU/getTopologyById.groovy | 122 -- .../contracts/ran/schemas/getAllSchemas.groovy | 65 - .../ran/schemas/getSchemasInDomain.groovy | 96 -- .../contracts/schemas/00_getAllSchemas.groovy | 534 +++++++ .../contracts/schemas/01_getSchemaContent.groovy | 177 +++ .../contracts/schemas/02_postSchemas.groovy | 1037 +++++++++++++ .../contracts/schemas/03_deleteSchemas.groovy | 66 + .../pgsqlschema/00_init-oran-smo-teiv-data-v1.sql | 1024 +++++++++++++ .../pgsqlschema/00_init-oran-smo-teiv-data.sql | 1088 ++++++++----- .../pgsqlschema/01_init-oran-smo-teiv-model-v1.sql | 430 ++++++ .../pgsqlschema/01_init-oran-smo-teiv-model.sql | 342 +++-- .../02_init-oran-smo-teiv-consumer-data-v1.sql | 48 + .../resources/pgsqlschema/consumer-data-v1.sql | 42 + .../{data => pgsqlschema}/data-deprecated.sql | 0 teiv/src/test/resources/pgsqlschema/data-v1.sql | 322 ++++ .../test/resources/{data => pgsqlschema}/data.sql | 116 +- teiv/src/test/resources/pgsqlschema/model.sql | 91 ++ 324 files changed, 28248 insertions(+), 14341 deletions(-) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesHealthIndicator.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exception/InvalidRelationshipException.java rename teiv/src/{test/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinementTest.java => main/java/org/oran/smo/teiv/exposure/audit/AuditInfo.java} (54%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditMapper.java rename teiv/src/{test/resources/contracts/ran/schemas/getSchemaByName.groovy => main/java/org/oran/smo/teiv/exposure/audit/LoggerHandler.java} (62%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/ClassifiersService.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/impl/ClassifiersServiceImpl.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataOperationRegistry.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/{tiespath/refiner/TiesPathQueryRefinement.java => consumerdata/ConsumerDataRepository.java} (57%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepositoryImpl.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataValidator.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/{spi/impl/StoredSchema.java => consumerdata/model/Classifiers.java} (74%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/ConsumerData.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Decorators.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/PersistableIdMap.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ClassifiersOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ConsumerDataOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DecoratorsOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteClassifiersOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteDecoratorsOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeClassifiersOperation.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeDecoratorsOperation.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/{DataRestController.java => DataController.java} (79%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/DecoratorsService.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/impl/DecoratorsServiceImpl.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/{ModelSchemaService.java => ModelService.java} (65%) delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelSchemaServiceImpl.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelServiceImpl.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/{ModelSchemaRestController.java => ModelController.java} (54%) delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataPersistanceService.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataRepository.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModelRepository.java rename teiv/src/main/java/org/oran/smo/teiv/{schema => exposure/spi}/Module.java (81%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModuleStatus.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistanceServiceImpl.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImpl.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/ModelRepositoryImpl.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapper.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtility.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PageMetaData.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaData.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/QueryMetaData.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapper.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ConditionFactory.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/InnerFilterCriteria.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapper.java rename teiv/src/main/java/org/oran/smo/teiv/{utils/query/TokenType.java => exposure/tiespath/resolver/ResolverDataType.java} (88%) create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverUtil.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeFilterListener.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolver.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetFilterListener.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationDTO.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationUtil.java rename teiv/src/main/java/org/oran/smo/teiv/exposure/{collection/rest/controller/TopologyGroupsRestController.java => utils/RequestDetails.java} (69%) delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryErrorCode.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryException.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/schema/YangDataTypes.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/service/SchemaCleanUpService.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/utils/JooqTypeConverter.java create mode 100644 teiv/src/main/java/org/oran/smo/teiv/utils/PersistableUtil.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryElement.java delete mode 100644 teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryMonad.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/db/TestPostgresqlContainerV1.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedNonXPathTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/RelationshipTestUtility.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/TopologyObjectTestUtility.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImplTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestControllerTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistenceServiceImplGETRequestsContainerizedTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImplGETRequestsContainerizedTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapperTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtilityTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaDataTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapperTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/DtoToJooqTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlockTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/SelectBlockTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapperTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolverTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/exposure/utils/PaginationUtilTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1Test.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryContainerizedTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/service/EndToEndApiTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/service/ModelSchemaServiceTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/service/SchemaCleanUpServiceTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventDataTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/utils/ConvertToJooqTypeUtilTest.java create mode 100644 teiv/src/test/java/org/oran/smo/teiv/utils/TiesTestConstants.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/utils/exposure/PaginationVerifierTestUtil.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTest.java delete mode 100644 teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTestUtil.java create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-arrays.json delete mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-data-only.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-invalid-entity-attribute.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module-type-pair.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-type.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-a-side.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-b-side.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-both-sides.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-id.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids2.json create mode 100644 teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids3.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-managed-element.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-one.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-one-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-relationship-connecting-same-entity.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-second-case.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-one.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-one-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-relationship-connecting-same-entity.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-merge-one-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-source-entity-delete-cm-handle.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-many.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one2.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one3.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one5.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-one-to-one.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-second-case.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-delete-one-to-one.json delete mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-merge-one-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-many-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-one-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-second-case.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-delete-one-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-merge-one-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-many-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-one-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-source-entity-delete-cm-handle.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-geo-location.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-relationship-connecting-same-entity.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-second-case.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-managed-element.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-many.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-one.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-relationship-connecting-same-entity.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-long-names.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many-deprecated-structure.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many2.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle.json create mode 100644 teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle2.json create mode 100644 teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation.json create mode 100644 teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation2.json create mode 100644 teiv/src/test/resources/contracts/classifiers/00_getClassifiers_getTopologyByEntityTypeName.groovy create mode 100644 teiv/src/test/resources/contracts/classifiers/01_getClassifiers_getRelationshipsByType.groovy create mode 100644 teiv/src/test/resources/contracts/classifiers/02_getClassifiers_getEntitiesByDomain.groovy create mode 100644 teiv/src/test/resources/contracts/classifiers/03_postClassifiers_merge.groovy create mode 100644 teiv/src/test/resources/contracts/classifiers/04_postClassifiers_delete.groovy create mode 100644 teiv/src/test/resources/contracts/data/00_getAllDomains.groovy create mode 100644 teiv/src/test/resources/contracts/data/01_getTopologyEntityTypes.groovy create mode 100644 teiv/src/test/resources/contracts/data/02_getTopologyByEntityTypeName.groovy create mode 100644 teiv/src/test/resources/contracts/data/03_getTopologyById.groovy create mode 100644 teiv/src/test/resources/contracts/data/04_getAllRelationshipsForEntityId.groovy create mode 100644 teiv/src/test/resources/contracts/data/05_getRelationshipTypes.groovy create mode 100644 teiv/src/test/resources/contracts/data/06_getRelationshipsByType.groovy create mode 100644 teiv/src/test/resources/contracts/data/07_getRelationshipById.groovy create mode 100644 teiv/src/test/resources/contracts/data/08_getEntitiesByDomain.groovy create mode 100644 teiv/src/test/resources/contracts/decorators/00_getDecorators_getTopologyByEntityTypeName.groovy create mode 100644 teiv/src/test/resources/contracts/decorators/01_getDecorators_getRelationshipsByType.groovy create mode 100644 teiv/src/test/resources/contracts/decorators/02_getDecorators_getEntitiesByDomain.groovy create mode 100644 teiv/src/test/resources/contracts/decorators/03_postDecoratorsMerge.groovy create mode 100644 teiv/src/test/resources/contracts/decorators/04_postDecoratorsDelete.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/GNBDUFunction/getAllRelationships.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyById.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyByType.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/NRCellDU/getTopologyById.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/schemas/getAllSchemas.groovy delete mode 100644 teiv/src/test/resources/contracts/ran/schemas/getSchemasInDomain.groovy create mode 100644 teiv/src/test/resources/contracts/schemas/00_getAllSchemas.groovy create mode 100644 teiv/src/test/resources/contracts/schemas/01_getSchemaContent.groovy create mode 100644 teiv/src/test/resources/contracts/schemas/02_postSchemas.groovy create mode 100644 teiv/src/test/resources/contracts/schemas/03_deleteSchemas.groovy create mode 100644 teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql create mode 100644 teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql create mode 100644 teiv/src/test/resources/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql create mode 100644 teiv/src/test/resources/pgsqlschema/consumer-data-v1.sql rename teiv/src/test/resources/{data => pgsqlschema}/data-deprecated.sql (100%) create mode 100644 teiv/src/test/resources/pgsqlschema/data-v1.sql rename teiv/src/test/resources/{data => pgsqlschema}/data.sql (62%) create mode 100644 teiv/src/test/resources/pgsqlschema/model.sql diff --git a/charts/smo/topology-exposure-inventory/charts/topology-exposure-inventory/values.yaml b/charts/smo/topology-exposure-inventory/charts/topology-exposure-inventory/values.yaml index fea5882..84d50af 100644 --- a/charts/smo/topology-exposure-inventory/charts/topology-exposure-inventory/values.yaml +++ b/charts/smo/topology-exposure-inventory/charts/topology-exposure-inventory/values.yaml @@ -156,7 +156,4 @@ application: retry-policies: deadlock: retry-attempts: 10 - retry-backoff-ms: 200 - - feature_flags: - use_alternate_delete_logic: false \ No newline at end of file + retry-backoff-ms: 200 \ No newline at end of file diff --git a/charts/smo/topology-exposure-inventory/values.yaml b/charts/smo/topology-exposure-inventory/values.yaml index 506c1de..e262d97 100644 --- a/charts/smo/topology-exposure-inventory/values.yaml +++ b/charts/smo/topology-exposure-inventory/values.yaml @@ -174,9 +174,6 @@ application: &applicationConfig retry-attempts: 10 retry-backoff-ms: 200 - feature_flags: - use_alternate_delete_logic: false - topology-exposure: name: topology-exposure namespace: default diff --git a/teiv/src/main/antlr4/org/oran/smo/teiv/antlr4/tiesPath.g4 b/teiv/src/main/antlr4/org/oran/smo/teiv/antlr4/tiesPath.g4 index 8a4046c..456a1fa 100644 --- a/teiv/src/main/antlr4/org/oran/smo/teiv/antlr4/tiesPath.g4 +++ b/teiv/src/main/antlr4/org/oran/smo/teiv/antlr4/tiesPath.g4 @@ -49,13 +49,15 @@ grammar tiesPath ; -tiesPath : ( prefix | incorrectPrefix ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? invalidPostFix? containerName? fieldLeaf?; +tiesPath : ( prefix | incorrectPrefix ) multipleLeafConditions? containsTextFunctionCondition? textFunctionCondition? containsFunctionCondition? ancestorAxis? invalidPostFix? containerName? fieldLeaf?; ancestorAxis : SLASH KW_ANCESTOR COLONCOLON ancestorPath ; ancestorPath : yangElement ( SLASH yangElement)* ; -textFunctionCondition : SLASH leafName OB KW_TEXT_FUNCTION EQ StringLiteral CB ; +textFunctionCondition : OB KW_TEXT_FUNCTION EQ StringLiteral CB ; + +containsTextFunctionCondition : OB KW_CONTAINS_FUNCTION OP KW_TEXT_FUNCTION COMMA StringLiteral CP CB ; containsFunctionCondition : OB KW_CONTAINS_FUNCTION OP AT leafName COMMA StringLiteral CP CB ; @@ -79,7 +81,8 @@ leafName : QName ; booleanOperators : ( KW_AND | KW_OR ) ; -comparativeOperators : ( EQ | GT | LT | GE | LE ) ; +// Onnly EQ supported for now +comparativeOperators : ( EQ /*| GT | LT | GE | LE */ ) ; invalidPostFix : (AT | CB | COLONCOLON | comparativeOperators ).+ ; @@ -165,4 +168,4 @@ fragment FragChar : '\u0009' | '\u000a' | '\u000d' Whitespace : ('\u000d' | '\u000a' | '\u0020' | '\u0009')+ -> skip ; // handle characters which failed to match any other token (otherwise Antlr will ignore them) -ErrorCharacter : . ; +ErrorCharacter : . ; \ No newline at end of file diff --git a/teiv/src/main/java/org/oran/smo/teiv/CustomMetrics.java b/teiv/src/main/java/org/oran/smo/teiv/CustomMetrics.java index 859dfe5..315247c 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/CustomMetrics.java +++ b/teiv/src/main/java/org/oran/smo/teiv/CustomMetrics.java @@ -24,19 +24,13 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import lombok.AccessLevel; import lombok.Data; -import lombok.Getter; import org.springframework.stereotype.Component; @Data @Component public class CustomMetrics { - @Getter(AccessLevel.PRIVATE) - private final AtomicLong tiesSubscriptionGaugeCounter = new AtomicLong(0L); - private final MeterRegistry meterRegistry; private final Counter numReceivedCloudEventCreate; @@ -115,6 +109,10 @@ public class CustomMetrics { private final Counter numUnsuccessfullyExposedDomainTypes; + private final Counter numUnsuccessfullyUpdatedClassifiers; + + private final Counter numUnsuccessfullyUpdatedDecorators; + private final Counter numIgnoredAttributes; public CustomMetrics(MeterRegistry meterRegistry) { @@ -208,6 +206,12 @@ public class CustomMetrics { numUnsuccessfullyExposedDomainTypes = Counter.builder("ties_exposure_http_get_domain_types_fail_total").register( meterRegistry); + numUnsuccessfullyUpdatedClassifiers = Counter.builder("ties_exposure_http_update_classifiers_fail_total").register( + meterRegistry); + + numUnsuccessfullyUpdatedDecorators = Counter.builder("ties_exposure_http_update_decorators_fail_total").register( + meterRegistry); + cloudEventMergePersistTime = Timer.builder("ties_ingestion_event_topology_merge_persist_seconds").register( meterRegistry); @@ -525,16 +529,12 @@ public class CustomMetrics { numUnsuccessfullyExposedDomainTypes.increment(); } - public void incrementNumReceivedTiesSubscriptions(int amountToAdd) { - tiesSubscriptionGaugeCounter.addAndGet(amountToAdd); - } - - public void resetNumReceivedTiesSubscriptions() { - tiesSubscriptionGaugeCounter.set(0); + public void incrementNumUnsuccessfullyUpdatedClassifiers() { + numUnsuccessfullyUpdatedClassifiers.increment(); } - public void setNumReceivedTiesSubscriptions(int amount) { - tiesSubscriptionGaugeCounter.set(amount); + public void incrementNumUnsuccessfullyUpdatedDecorators() { + numUnsuccessfullyUpdatedDecorators.increment(); } public void incrementNumIgnoredAttributes() { diff --git a/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailability.java b/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailability.java index 46291ff..837a06e 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailability.java +++ b/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailability.java @@ -29,8 +29,6 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public abstract class DependentServiceAvailability { - protected String serviceName; - protected int retryIntervalMs; protected int retryAttempts; @@ -41,7 +39,7 @@ public abstract class DependentServiceAvailability { * @return true once service is reached, false if max retries exhausted */ public boolean checkService() { - RetryTemplate retryTemplate = RetryOperationUtils.getRetryTemplate(serviceName, + RetryTemplate retryTemplate = RetryOperationUtils.getRetryTemplate(getServiceName(), UnsatisfiedExternalDependencyException.class, retryAttempts, retryIntervalMs); try { return retryTemplate.execute(retryContext -> isServiceAvailable()); @@ -51,5 +49,10 @@ public abstract class DependentServiceAvailability { return false; // exhausted retries } + /** + * @return Name of the service, e.g.: Kafka. + */ + protected abstract String getServiceName(); + abstract boolean isServiceAvailable() throws UnsatisfiedExternalDependencyException; } diff --git a/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailabilityKafka.java b/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailabilityKafka.java index 2af2d33..0e0748e 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailabilityKafka.java +++ b/teiv/src/main/java/org/oran/smo/teiv/availability/DependentServiceAvailabilityKafka.java @@ -20,11 +20,11 @@ */ package org.oran.smo.teiv.availability; +import lombok.RequiredArgsConstructor; import org.apache.kafka.clients.admin.AdminClient; import org.apache.kafka.clients.admin.ListTopicsOptions; import org.apache.kafka.clients.admin.ListTopicsResult; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Profile; import org.springframework.kafka.core.KafkaAdmin; import org.springframework.stereotype.Component; @@ -37,7 +37,7 @@ import lombok.extern.slf4j.Slf4j; @Component @Slf4j -@Profile("ingestion") +@RequiredArgsConstructor public class DependentServiceAvailabilityKafka extends DependentServiceAvailability { @Getter @@ -49,10 +49,9 @@ public class DependentServiceAvailabilityKafka extends DependentServiceAvailabil @Setter private Integer listTopicTimeout = null; - public DependentServiceAvailabilityKafka(KafkaAdminConfig kafkaAdminConfig, KafkaAdmin kafkaAdmin) { - this.kafkaAdminConfig = kafkaAdminConfig; - this.kafkaAdmin = kafkaAdmin; - serviceName = "Kafka"; + @Override + protected String getServiceName() { + return "Kafka"; } @Value("${kafka.availability.retry-interval-ms}") diff --git a/teiv/src/main/java/org/oran/smo/teiv/config/DataSourceConfig.java b/teiv/src/main/java/org/oran/smo/teiv/config/DataSourceConfig.java index a926a0f..f9d2b8f 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/config/DataSourceConfig.java +++ b/teiv/src/main/java/org/oran/smo/teiv/config/DataSourceConfig.java @@ -56,4 +56,9 @@ public class DataSourceConfig { public DSLContext dslContextRead() { return DSL.using(dataSourceRead(), SQLDialect.POSTGRES); } + + @Bean(name = "readWriteDataDslContext") + public DSLContext dslContextReadWrite() { + return DSL.using(dataSourceWrite(), SQLDialect.POSTGRES); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/config/KafkaAdminConfig.java b/teiv/src/main/java/org/oran/smo/teiv/config/KafkaAdminConfig.java index 66beb64..747c52e 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/config/KafkaAdminConfig.java +++ b/teiv/src/main/java/org/oran/smo/teiv/config/KafkaAdminConfig.java @@ -23,7 +23,6 @@ package org.oran.smo.teiv.config; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; import lombok.Data; @@ -31,7 +30,6 @@ import org.oran.smo.teiv.service.kafka.KafkaAddressSupplier; @Configuration @Data -@Profile("ingestion") @Slf4j public class KafkaAdminConfig { diff --git a/teiv/src/main/java/org/oran/smo/teiv/config/KafkaConfig.java b/teiv/src/main/java/org/oran/smo/teiv/config/KafkaConfig.java index b43f4b6..a263de6 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/config/KafkaConfig.java +++ b/teiv/src/main/java/org/oran/smo/teiv/config/KafkaConfig.java @@ -23,11 +23,9 @@ package org.oran.smo.teiv.config; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; @Configuration @Data -@Profile("ingestion") public class KafkaConfig { private final TopologyIngestion topologyIngestion; @@ -35,18 +33,21 @@ public class KafkaConfig { @Data @Configuration public static class TopologyIngestion { - @Value("${kafka.topology-ingestion.consumer.topic.name}") + @Value("${kafka.topology-ingestion.topic.name}") private String topicName; - @Value("${kafka.topology-ingestion.consumer.topic.partitions}") + @Value("${kafka.topology-ingestion.topic.partitions}") private int partitions; - @Value("${kafka.topology-ingestion.consumer.topic.replicas}") + @Value("${kafka.topology-ingestion.topic.replicas}") private int replicas; - @Value("${kafka.topology-ingestion.consumer.topic.retention-ms}") + @Value("${kafka.topology-ingestion.topic.retention-ms}") private String retention; + @Value("${kafka.topology-ingestion.topic.retention-bytes}") + private String retentionBytes; + @Value("${kafka.topology-ingestion.consumer.group-id}") private String groupId; diff --git a/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicator.java b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicator.java index 1863ff7..cdcf000 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicator.java +++ b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicator.java @@ -20,11 +20,8 @@ */ package org.oran.smo.teiv.controller.health; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - +import org.oran.smo.teiv.availability.DependentServiceAvailabilityKafka; import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @@ -32,26 +29,25 @@ import org.springframework.stereotype.Component; * Health Check component for TIES exposure. */ -@RequiredArgsConstructor @Component -@Slf4j @Profile("!ingestion") -public class TiesExposureHealthIndicator implements HealthIndicator { +public class TiesExposureHealthIndicator extends TiesHealthIndicator { - private final HealthStatus healthStatus; + public TiesExposureHealthIndicator(HealthStatus healthStatus, + DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka) { + super(healthStatus, dependentServiceAvailabilityKafka); + } - private static final String SERVICE_NAME = "topology-exposure-inventory"; + @Override + protected String getServiceName() { + return "topology-exposure-inventory"; + } @Override public Health health() { if (!healthStatus.isSchemaInitialized()) { - String errorMessage = SERVICE_NAME + " is DOWN because: Schema is yet to be initialized."; - log.error(errorMessage); - return Health.down().withDetail("Error", errorMessage).build(); - } else { - String message = SERVICE_NAME + " is UP and Healthy."; - log.debug(message); - return Health.up().withDetail("UP", message).build(); + return healthDown("Schema is yet to be initialized."); } + return healthUp(); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesHealthIndicator.java b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesHealthIndicator.java new file mode 100644 index 0000000..0beb247 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesHealthIndicator.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.controller.health; + +import org.oran.smo.teiv.availability.DependentServiceAvailabilityKafka; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class TiesHealthIndicator implements HealthIndicator { + + protected final HealthStatus healthStatus; + protected final DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka; + + protected abstract String getServiceName(); + + protected TiesHealthIndicator(HealthStatus healthStatus, + DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka) { + this.healthStatus = healthStatus; + this.dependentServiceAvailabilityKafka = dependentServiceAvailabilityKafka; + } + + protected Health healthUp() { + String message = getServiceName() + " is UP and Healthy."; + log.debug(message); + return Health.up().withDetail("UP", message).build(); + } + + protected Health healthDown(String reason) { + String errorMessage = getServiceName() + " is DOWN because: " + reason; + log.error(errorMessage); + return Health.down().withDetail("Error", errorMessage).build(); + } + + protected boolean isKafkaReachable() { + return dependentServiceAvailabilityKafka.checkService(); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicator.java b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicator.java index fbedaa0..4b891d2 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicator.java +++ b/teiv/src/main/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicator.java @@ -20,11 +20,7 @@ */ package org.oran.smo.teiv.controller.health; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @@ -34,43 +30,28 @@ import org.oran.smo.teiv.availability.DependentServiceAvailabilityKafka; * Health Check component for TIES ingestion. */ -@RequiredArgsConstructor @Component -@Slf4j @Profile("ingestion") -public class TiesIngestionHealthIndicator implements HealthIndicator { - - private final HealthStatus healthStatus; +public class TiesIngestionHealthIndicator extends TiesHealthIndicator { - private final DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka; + @Override + protected String getServiceName() { + return "top-exp-inv-ingestion"; + } - private static final String SERVICE_NAME = "top-exp-inv-ingestion"; + public TiesIngestionHealthIndicator(HealthStatus healthStatus, + DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka) { + super(healthStatus, dependentServiceAvailabilityKafka); + } @Override public Health health() { - String errorMessage = SERVICE_NAME + " is DOWN because:"; - boolean isHealthy = true; - if (!healthStatus.isSchemaInitialized()) { - errorMessage += " Schema is yet to be initialized."; - isHealthy = false; + return healthDown("Schema is yet to be initialized."); } - - if (!checkKafkaHealth()) { - errorMessage += " Kafka is unavailable."; - isHealthy = false; - } - - if (!isHealthy) { - log.error(errorMessage); - return Health.down().withDetail("Error", errorMessage).build(); - } else { - log.debug(SERVICE_NAME + " is UP and Healthy."); - return Health.up().withDetail("UP", SERVICE_NAME + " is UP and Healthy.").build(); + if (!isKafkaReachable()) { + return healthDown("Kafka is unavailable."); } - } - - private boolean checkKafkaHealth() { - return dependentServiceAvailabilityKafka.checkService(); + return healthUp(); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exception/InvalidRelationshipException.java b/teiv/src/main/java/org/oran/smo/teiv/exception/InvalidRelationshipException.java new file mode 100644 index 0000000..2943f44 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exception/InvalidRelationshipException.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exception; + +public class InvalidRelationshipException extends Exception { + public InvalidRelationshipException(final String message) { + super(message); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exception/TiesException.java b/teiv/src/main/java/org/oran/smo/teiv/exception/TiesException.java index 481a2b6..36d4bdb 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exception/TiesException.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exception/TiesException.java @@ -21,6 +21,9 @@ package org.oran.smo.teiv.exception; import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.springframework.http.HttpStatus; @@ -38,6 +41,11 @@ public class TiesException extends RuntimeException { return clientException("Unknown module", String.format("Unknown module: %s", module)); } + public static TiesException unknownTopologyObjectType(final String topologyObject) { + return serverException("Unknown topology object type", String.format("Unknown topology object type: %s", + topologyObject), null); + } + // Request validation public static TiesException unknownDomain(final String domain, final Collection domains) { return clientException("Unknown domain", String.format("Unknown domain: %s, known domains: %s", domain, domains)); @@ -74,6 +82,10 @@ public class TiesException extends RuntimeException { return clientException("Invalid schema name", String.format("Invalid schema name: %s", name)); } + public static TiesException invalidFileInput(final String error) { + return clientException("Invalid file input", String.format("Invalid file input: %s", error)); + } + public static TiesException schemaNotOwned(final String name) { return new TiesException("Forbidden", String.format("Schema %s is not owned by user", name), HttpStatus.FORBIDDEN, null); @@ -83,16 +95,51 @@ public class TiesException extends RuntimeException { return serverException("Sql exception during query execution", "Please check the logs for more details", null); } + public static TiesException unParsedTopologyObjectType(String topologyObjectName) { + return serverException(String.format("Un parsed topology object type: %s", topologyObjectName), + "Please check the logs for more details", null); + } + + public static TiesException invalidContainerType(String containerType) { + return serverException(String.format("Invalid container type: %s", containerType), + "Please check the logs for more details", null); + } + + public static TiesException invalidAssociationType(final String association) { + return serverException(String.format("Invalid association type: %s", association), + "Please check the logs for more details", null); + } + public static TiesException resourceNotFoundException() { return new TiesException("Resource Not Found", "The requested resource is not found", HttpStatus.NOT_FOUND, null); } + public static TiesException resourceNotFoundException(Set entityIds, Set relationshipIds) { + return new TiesException("Resource Not Found", String.format( + "The requested resource with the following ids cannot be found. Entities: %s Relationships: %s", entityIds, + relationshipIds), HttpStatus.NOT_FOUND, null); + } + + public static TiesException invalidClassifiersException(List classifiers) { + return new TiesException("Invalid classifiers", String.format("The provided classifiers are invalid %s", + classifiers), HttpStatus.NOT_FOUND, null); + } + + public static TiesException invalidDecoratorsException(Map problems) { + return new TiesException("Invalid decorators", String.format("The provided decorators are invalid %s", problems), + HttpStatus.NOT_FOUND, null); + } + public static TiesException invalidValueException(String valueName, Integer valueLimit, Boolean isLowerLimit) { return clientException("Invalid Value", String.format("%s cannot be %s than %d", valueName, isLowerLimit ? "larger" : "lower", valueLimit)); } + public static TiesException invalidJsonFormat(Exception exception) { + return serverException("Invalid json format", "Please check the logs for more details", exception); + } + public static TiesException serverException(String message, String details, Exception exception) { return new TiesException(message, details, HttpStatus.INTERNAL_SERVER_ERROR, exception); } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinementTest.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditInfo.java similarity index 54% rename from teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinementTest.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditInfo.java index 0a3d46f..c969727 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinementTest.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditInfo.java @@ -18,17 +18,26 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.exposure.tiespath.refiner; +package org.oran.smo.teiv.exposure.audit; -import org.oran.smo.teiv.utils.path.TiesPathQuery; -import org.apache.commons.lang3.NotImplementedException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import java.util.List; -public class TiesPathQueryRefinementTest { - @Test - void parseTiesPathQueryTest() { - Assertions.assertThrows(NotImplementedException.class, () -> TiesPathQueryRefinement.parseTiesPathQuery( - new TiesPathQuery())); +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; + +@AllArgsConstructor +public class AuditInfo { + private final String operation; + private final T consumerData; + private final List entityIds; + private final List relationshipIds; + private final HttpStatus status; + + @Override + public String toString() { + return String.format("%s %s=%s for entities=%s and relationships=%s (%s)", StringUtils.capitalize(operation), + consumerData instanceof List ? "classifiers" : "decorators", consumerData, entityIds, relationshipIds, + status.equals(HttpStatus.NO_CONTENT) ? "successful" : "failed"); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditMapper.java new file mode 100644 index 0000000..f581ccc --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/AuditMapper.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.audit; + +import java.util.List; +import java.util.Map; + +import lombok.experimental.UtilityClass; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.springframework.http.HttpStatus; + +@UtilityClass +public class AuditMapper { + public AuditInfo> fromClassifiersRequest(final OranTeivClassifier request, final HttpStatus status) { + return new AuditInfo<>(request.getOperation().toString(), request.getClassifiers(), request.getEntityIds(), request + .getRelationshipIds(), status); + } + + public AuditInfo> fromDecoratorsRequest(final OranTeivDecorator request, final HttpStatus status) { + return new AuditInfo<>(request.getOperation().toString(), request.getDecorators(), request.getEntityIds(), request + .getRelationshipIds(), status); + } +} diff --git a/teiv/src/test/resources/contracts/ran/schemas/getSchemaByName.groovy b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/LoggerHandler.java similarity index 62% rename from teiv/src/test/resources/contracts/ran/schemas/getSchemaByName.groovy rename to teiv/src/main/java/org/oran/smo/teiv/exposure/audit/LoggerHandler.java index 9aba34a..9ba5716 100644 --- a/teiv/src/test/resources/contracts/ran/schemas/getSchemaByName.groovy +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/audit/LoggerHandler.java @@ -18,23 +18,24 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package contracts.ran.schemas +package org.oran.smo.teiv.exposure.audit; -import org.springframework.cloud.contract.spec.Contract +import org.slf4j.Logger; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; -[ - Contract.make { - description "SUCCESS - 200: Get schema with name o-ran-smo-teiv-cloud-to-ran" - request { - method GET() - url("/topology-inventory/v1alpha11/schemas/o-ran-smo-teiv-cloud-to-ran/content") - } - response { - body("module o-ran-smo-teiv-cloud-to-ran { yang-version 1.1; }") - status OK() - headers { - contentType('text/plain') - } - } +@Component +public class LoggerHandler { + + public void logAudit(Logger log, String message, HttpServletRequest context) { + String requestInfo = getRequestInfo(context); + log.info("Audit Log: {} - Request Info: {}", message, requestInfo); + } + + private String getRequestInfo(HttpServletRequest context) { + String method = context.getMethod(); + String requestURI = context.getRequestURI(); + + return String.format("Method: %s, URI: %s", method, requestURI); } -] +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/ClassifiersService.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/ClassifiersService.java new file mode 100644 index 0000000..2f016ed --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/ClassifiersService.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.classifiers.api; + +import org.oran.smo.teiv.api.model.OranTeivClassifier; + +public interface ClassifiersService { + /** + * Updates the classifiers of the specified entities and/or relationships + * + * @param oranTeivClassifier + * holds information for updating classifiers + */ + void update(OranTeivClassifier oranTeivClassifier); +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/impl/ClassifiersServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/impl/ClassifiersServiceImpl.java new file mode 100644 index 0000000..a346280 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/api/impl/ClassifiersServiceImpl.java @@ -0,0 +1,124 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.classifiers.api.impl; + +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.classifiers.api.ClassifiersService; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataOperationRegistry; +import org.oran.smo.teiv.exposure.consumerdata.model.Classifiers; +import org.oran.smo.teiv.exposure.consumerdata.operation.ClassifiersOperation; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.schema.ConsumerDataCache; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import java.util.function.Consumer; + +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ClassifiersServiceImpl implements ClassifiersService { + + private final ModelRepository modelRepository; + private final ConsumerDataCache consumerDataCache; + private final ConsumerDataOperationRegistry consumerDataOperationRegistry; + + @Override + public void update(final OranTeivClassifier oranTeivClassifier) { + + log.debug(String.format("Executing %s on classifiers", oranTeivClassifier.getOperation())); + + List entityIds = oranTeivClassifier.getEntityIds(); + if (entityIds == null) { + entityIds = Collections.emptyList(); + } + + List relationshipIds = oranTeivClassifier.getRelationshipIds(); + if (relationshipIds == null) { + relationshipIds = Collections.emptyList(); + } + + final List classifierNames = oranTeivClassifier.getClassifiers(); + + final Classifiers classifierRecords = Classifiers.builder().data(classifierNames).entityIds(entityIds) + .relationshipIds(relationshipIds).build(); + + if (oranTeivClassifier.getOperation().equals(OranTeivClassifier.OperationEnum.MERGE)) { + runMethodSafe(this::validateMerge, classifierRecords); + } else { + runMethodSafe(this::validateDelete, classifierRecords); + } + + final ClassifiersOperation operation = consumerDataOperationRegistry.getClassifiersOperation(oranTeivClassifier + .getOperation()); + + List results = operation.execute(classifierRecords); + } + + private void validateMerge(final Classifiers classifiers) { + log.debug(String.format("Validating merging %s", classifiers)); + + final List problems = checkAvailability(classifiers); + + if (!problems.isEmpty()) { + throw TiesException.invalidClassifiersException(problems); + } + } + + private void validateDelete(final Classifiers classifiers) { + log.debug(String.format("Validating deleting %s", classifiers)); + + for (String classifier : classifiers.data()) { + final String schemaName = classifier.split(":")[0]; + if (!modelRepository.doesModuleExists(TIES_CONSUMER_DATA, schemaName)) { + throw TiesException.invalidSchema(schemaName); + } + } + } + + private List checkAvailability(final Classifiers classifiers) { + final List invalidClassifiers = new ArrayList<>(classifiers.data()); + + classifiers.data().stream().filter(classifier -> consumerDataCache.getClassifiers().contains(classifier)).forEach( + invalidClassifiers::remove); + + return invalidClassifiers; + } + + private void runMethodSafe(Consumer consumer, Classifiers classifiers) { + try { + consumer.accept(classifiers); + } catch (TiesException ex) { + log.error("Exception during validation", ex); + throw ex; + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/rest/controller/ClassifiersRestController.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/rest/controller/ClassifiersRestController.java index 8d4f66f..22e6acf 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/rest/controller/ClassifiersRestController.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/classifiers/rest/controller/ClassifiersRestController.java @@ -20,14 +20,79 @@ */ package org.oran.smo.teiv.exposure.classifiers.rest.controller; +import java.util.Collections; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import io.micrometer.core.annotation.Timed; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import jakarta.servlet.http.HttpServletRequest; + +import org.oran.smo.teiv.CustomMetrics; import org.oran.smo.teiv.api.ClassifiersApi; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.audit.AuditMapper; +import org.oran.smo.teiv.exposure.audit.LoggerHandler; +import org.oran.smo.teiv.exposure.classifiers.api.ClassifiersService; import org.oran.smo.teiv.utils.TiesConstants; - +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Slf4j @RestController @RequestMapping(TiesConstants.REQUEST_MAPPING) +@RequiredArgsConstructor public class ClassifiersRestController implements ClassifiersApi { + private final ClassifiersService classifiersService; + private final CustomMetrics customMetrics; + private final LoggerHandler loggerHandler; + private final HttpServletRequest context; + + @Value("${consumer-data.batch-size}") + private int limit; + + @Override + @Timed("ties_exposure_http_update_classifiers_seconds") + public ResponseEntity updateClassifier(final String accept, final String contentType, + final OranTeivClassifier oranTeivClassifier) { + return runWithFailCheck(() -> { + if (Optional.ofNullable(oranTeivClassifier.getEntityIds()).orElseGet(Collections::emptyList).size() + Optional + .ofNullable(oranTeivClassifier.getRelationshipIds()).orElseGet(Collections::emptyList).size() > limit) { + throw TiesException.clientException("Limit exceeded", + "Number of entities and relationships exceeded the limit"); + } + runSafeMethod(() -> classifiersService.update(oranTeivClassifier), status -> loggerHandler.logAudit(log, + AuditMapper.fromClassifiersRequest(oranTeivClassifier, status).toString(), context)); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + }, customMetrics::incrementNumUnsuccessfullyUpdatedClassifiers); + } + + private T runWithFailCheck(final Supplier supp, final Runnable runnable) { + try { + return supp.get(); + } catch (Exception ex) { + log.error("Exception during service call", ex); + runnable.run(); + throw ex; + } + } + + protected void runSafeMethod(final Runnable runnable, final Consumer logAudit) { + try { + runnable.run(); + logAudit.accept(HttpStatus.NO_CONTENT); + } catch (TiesException ex) { + logAudit.accept(ex.getStatus()); + log.error("Exception during service call", ex); + throw ex; + } + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataOperationRegistry.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataOperationRegistry.java new file mode 100644 index 0000000..27877db --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataOperationRegistry.java @@ -0,0 +1,69 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata; + +import lombok.RequiredArgsConstructor; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exposure.consumerdata.operation.ClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DecoratorsOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteDecoratorsOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.MergeClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.MergeDecoratorsOperation; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class ConsumerDataOperationRegistry { + private final MergeClassifiersOperation mergeClassifiersOperation; + private final DeleteClassifiersOperation deleteClassifiersOperation; + private final MergeDecoratorsOperation mergeDecoratorsOperation; + private final DeleteDecoratorsOperation deleteDecoratorsOperation; + + /** + * Returns the concrete operation according to the parameter for classifiers. + * + * @param operation + * coming from the request + * @return classifiers operation for execution + */ + public ClassifiersOperation getClassifiersOperation(final OranTeivClassifier.OperationEnum operation) { + return switch (operation) { + case MERGE -> mergeClassifiersOperation; + case DELETE -> deleteClassifiersOperation; + }; + } + + /** + * Returns the concrete operation according to the parameter for decorators. + * + * @param operation + * coming from the request + * @return decorators operation for execution + */ + public DecoratorsOperation getDecoratorsOperation(final OranTeivDecorator.OperationEnum operation) { + return switch (operation) { + case MERGE -> mergeDecoratorsOperation; + case DELETE -> deleteDecoratorsOperation; + }; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinement.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepository.java similarity index 57% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinement.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepository.java index c1411fd..0c782c7 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/TiesPathQueryRefinement.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepository.java @@ -18,27 +18,37 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.exposure.tiespath.refiner; +package org.oran.smo.teiv.exposure.consumerdata; -import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; -import org.oran.smo.teiv.utils.path.TiesPathQuery; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.NotImplementedException; +import org.oran.smo.teiv.schema.YangDataTypes; -@UtilityClass -@Slf4j -public class TiesPathQueryRefinement { +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface ConsumerDataRepository { + + /** + * Load classifiers set. + * + * @return the classifiers + */ + Set loadClassifiers(); /** - * Parses tiesPathQuery to innerLanguageDTO. + * Load decorators map. * - * @param tiesPathQuery - * the ties path query - * @return the inner language dto + * @return the decorators + */ + Map loadDecorators(); + + /** + * Store classifier in the ties_model.classifiers + */ + void storeClassifiers(final List elements, final String moduleName); + + /** + * Store decorators in the ties_model.decorators */ - public static FilterCriteria parseTiesPathQuery(TiesPathQuery tiesPathQuery) { - log.trace(tiesPathQuery.toString()); - throw new NotImplementedException(); - } + void storeDecorators(final Map elements, final String moduleName); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepositoryImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepositoryImpl.java new file mode 100644 index 0000000..b6ebafb --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataRepositoryImpl.java @@ -0,0 +1,134 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; +import static org.oran.smo.teiv.utils.TiesConstants.DECORATORS; +import static org.oran.smo.teiv.utils.TiesConstants.MODULE_REFERENCE; +import static org.oran.smo.teiv.utils.TiesConstants.MODULE_REFERENCE_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.NAME; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; +import static org.oran.smo.teiv.utils.TiesConstants.SEMICOLON_SEPARATION; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Supplier; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.InsertValuesStepN; +import org.jooq.Record; +import org.jooq.Record1; +import org.jooq.Record2; +import org.jooq.SelectConditionStep; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.schema.YangDataTypes; +import org.oran.smo.teiv.utils.TiesConstants; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ConsumerDataRepositoryImpl implements ConsumerDataRepository { + private final DSLContext readDataDslContext; + private final DSLContext writeDataDslContext; + + @Override + public Set loadClassifiers() { + final Field classifierName = field("classifiers.name").as("classifierName"); + SelectConditionStep> availableClassifiers = runMethodSafe(() -> readDataDslContext.select( + classifierName).from(String.format(TIES_CONSUMER_DATA, CLASSIFIERS)).join(String.format(TIES_CONSUMER_DATA, + MODULE_REFERENCE)).on(field("\"moduleReferenceName\"").eq(field(String.format(TIES_CONSUMER_DATA, + MODULE_REFERENCE) + ".name"))).where(field("status").like(TiesConstants.IN_USAGE))); + Set result = new HashSet<>(); + for (Record record : availableClassifiers) { + result.add((String) record.get("classifierName")); + } + return result; + } + + @Override + public Map loadDecorators() { + final Field decoratorName = field("decorators.name").as("decoratorName"); + final Field dataType = field("decorators.\"dataType\"").as("dataType"); + SelectConditionStep> availableDecorators = runMethodSafe(() -> readDataDslContext.select( + decoratorName, dataType).from(String.format(TIES_CONSUMER_DATA, DECORATORS)).join(String.format( + TIES_CONSUMER_DATA, MODULE_REFERENCE)).on(field("\"moduleReferenceName\"").eq(field(String.format( + TIES_CONSUMER_DATA, MODULE_REFERENCE) + ".name"))).where(field("status").like( + TiesConstants.IN_USAGE))); + Map result = new HashMap<>(); + for (Record record : availableDecorators) { + result.put((String) record.get("decoratorName"), YangDataTypes.fromYangDataType("" + record.get("dataType"))); + } + return result; + } + + @Override + public void storeClassifiers(final List elements, final String moduleName) { + insertValues(CLASSIFIERS, List.of(NAME, String.format(QUOTED_STRING, MODULE_REFERENCE_NAME)), executable -> { + for (String element : elements) { + executable = executable.values(String.format(SEMICOLON_SEPARATION, moduleName, element), moduleName); + } + }); + } + + @Override + public void storeDecorators(final Map elements, final String moduleName) { + insertValues(DECORATORS, List.of(NAME, String.format(QUOTED_STRING, "dataType"), String.format(QUOTED_STRING, + MODULE_REFERENCE_NAME)), executable -> { + for (Map.Entry element : elements.entrySet()) { + executable = executable.values(String.format(SEMICOLON_SEPARATION, moduleName, element.getKey()), + element.getValue(), moduleName); + } + }); + } + + private void insertValues(final String tableName, final List columns, + final Consumer> consumer) { + InsertValuesStepN executable = writeDataDslContext.insertInto(table(String.format(TIES_CONSUMER_DATA, + tableName))).columns(columns.stream().map(column -> field(column, String.class)).toList()); + + consumer.accept(executable); + + runMethodSafe(executable::execute); + } + + protected T runMethodSafe(Supplier supp) { + try { + return supp.get(); + } catch (TiesException ex) { + throw ex; + } catch (Exception ex) { + log.error("Sql exception during query execution", ex); + throw TiesException.serverSQLException(); + } + } + +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataValidator.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataValidator.java new file mode 100644 index 0000000..5d58247 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/ConsumerDataValidator.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.consumerdata.model.Classifiers; +import org.oran.smo.teiv.exposure.consumerdata.model.Decorators; +import org.oran.smo.teiv.schema.ConsumerDataCache; +import org.oran.smo.teiv.schema.YangDataTypes; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ConsumerDataValidator { + + private final ConsumerDataCache consumerDataCache; + + public void validate(final Classifiers classifiers) { + log.debug(String.format("Validating %s", classifiers)); + + final List problems = checkAvailability(classifiers); + + if (!problems.isEmpty()) { + throw TiesException.invalidClassifiersException(problems); + } + } + + private List checkAvailability(final Classifiers classifiers) { + final List invalidClassifiers = new ArrayList<>(classifiers.data()); + + classifiers.data().stream().filter(classifier -> !consumerDataCache.getValidClassifiers(classifier).isEmpty()) + .forEach(invalidClassifiers::remove); + + return invalidClassifiers; + } + + public void validate(final Decorators decorators) { + log.debug(String.format("Validating %s", decorators)); + + final Map problems = checkAvailability(decorators); + + if (!problems.isEmpty()) { + throw TiesException.invalidDecoratorsException(problems); + } + } + + private Map checkAvailability(final Decorators decorators) { + final Map invalidKeys = new HashMap<>(); + + for (String key : decorators.data().keySet()) { + invalidKeys.put(key, "is_not_available"); + } + + decorators.data().forEach((key, value) -> { + + if (consumerDataCache.getDecorators().containsKey(key)) { + + final boolean isCompatible = checkCompatibility(key, value); + + if (isCompatible) { + invalidKeys.remove(key); + } else { + invalidKeys.put(key, "is_not_compatible"); + } + } + }); + + return invalidKeys; + } + + private boolean checkCompatibility(final String key, final Object value) { + return consumerDataCache.getDecorators().get(key).equals(YangDataTypes.fromRequestDataType(value.getClass())); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/StoredSchema.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Classifiers.java similarity index 74% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/StoredSchema.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Classifiers.java index 3d57139..28a2a12 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/StoredSchema.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Classifiers.java @@ -18,20 +18,13 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.exposure.spi.impl; - -import lombok.Data; +package org.oran.smo.teiv.exposure.consumerdata.model; import java.util.List; -@Data -public class StoredSchema { - private String name; - private String namespace; - private String domain; - private String revision; - private List includedModules; - private String content; - private String ownerAppId; - private String status; +import lombok.Builder; + +@Builder +public record Classifiers(List data, List entityIds, List relationshipIds) implements + ConsumerData> { } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/ConsumerData.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/ConsumerData.java new file mode 100644 index 0000000..23ec8b0 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/ConsumerData.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.model; + +import java.util.List; + +public interface ConsumerData { + /** + * Returns the actual consumer data. + * + * @return data + */ + T data(); + + /** + * Returns the entity ids. + * + * @return list of entity ids + */ + List entityIds(); + + /** + * Returns the relationship ids. + * + * @return list of relationship ids + */ + List relationshipIds(); +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Decorators.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Decorators.java new file mode 100644 index 0000000..cb56202 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/Decorators.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.model; + +import lombok.Builder; + +import java.util.List; +import java.util.Map; + +@Builder +public record Decorators(Map data, List entityIds, List relationshipIds) implements + ConsumerData> { +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/PersistableIdMap.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/PersistableIdMap.java new file mode 100644 index 0000000..dee0062 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/model/PersistableIdMap.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.model; + +import lombok.Builder; +import org.oran.smo.teiv.schema.Persistable; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Builder +public record PersistableIdMap(Set idsNotFound, Map> persistableWithIds) { +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ClassifiersOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ClassifiersOperation.java new file mode 100644 index 0000000..9e23820 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ClassifiersOperation.java @@ -0,0 +1,60 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import org.jooq.DSLContext; + +import lombok.extern.slf4j.Slf4j; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +import org.jooq.Result; +import org.jooq.Record; +import org.jooq.JSONB; +import org.oran.smo.teiv.schema.Persistable; +import org.oran.smo.teiv.service.models.OperationResult; +import org.oran.smo.teiv.utils.JooqTypeConverter; + +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Slf4j +public abstract class ClassifiersOperation extends ConsumerDataOperation> { + + protected ClassifiersOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + protected Map createOperationResults(final Persistable persistable, + final Result results) { + final Map opResults = new HashMap<>(); + for (Record record : results) { + String id = (String) record.get(persistable.getIdColumnNameWithTableName()); + List classifierListAfterUpdate = JooqTypeConverter.jsonbToList(record.get(String.format(QUOTED_STRING, + persistable.getClassifiersColumnName()), JSONB.class)); + OperationResult operationResult = OperationResult.createClassifierOperationResult(id, persistable.getName(), + persistable.getCategory(), classifierListAfterUpdate); + + opResults.put(id, operationResult); + } + return opResults; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ConsumerDataOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ConsumerDataOperation.java new file mode 100644 index 0000000..dc329e4 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/ConsumerDataOperation.java @@ -0,0 +1,160 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jooq.Configuration; +import org.jooq.DSLContext; +import org.jooq.Record1; +import org.jooq.Result; +import org.jooq.SelectConditionStep; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; + +import org.jooq.exception.DataAccessException; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.consumerdata.model.ConsumerData; +import org.oran.smo.teiv.exposure.consumerdata.model.PersistableIdMap; +import org.oran.smo.teiv.schema.Persistable; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.service.models.OperationResult; + +@Slf4j +@RequiredArgsConstructor +public abstract class ConsumerDataOperation { + + private final DSLContext readDataDslContext; + protected final DSLContext writeDataDslContext; + + protected abstract List performOperation(final PersistableIdMap map, final C consumerData, + final DSLContext writeDataDslContext); + + /** + * Executes the operation for the given consumer data. + * + * @param consumerData + * which holds the information for classifiers/decorators, entity ids and relationship ids + * @return Map of Operation Results. Key is the ID of the Entity/Relationship. + */ + public List execute(final ConsumerData consumerData) { + return runMethodSafe(() -> { + final Pair maps = checkIfIdsExist(consumerData); + final PersistableIdMap entityIdMap = maps.getKey(); + final PersistableIdMap relationshipIdMap = maps.getValue(); + + final List results = new ArrayList<>(); + + writeDataDslContext.transaction((Configuration config) -> { + if (!consumerData.entityIds().isEmpty()) { + final List entityResults = performOperation(entityIdMap, consumerData.data(), config + .dsl()); + results.addAll(entityResults); + } + + if (!consumerData.relationshipIds().isEmpty()) { + final List relshipResults = performOperation(relationshipIdMap, consumerData.data(), + config.dsl()); + results.addAll(relshipResults); + } + }); + + return results; + }); + } + + protected Pair checkIfIdsExist(final ConsumerData consumerData) { + log.debug("Checking entity and relationship ids"); + + final List entityNames = SchemaRegistry.getEntityNames(); + final List relationNames = SchemaRegistry.getRelationNames(); + + final PersistableIdMap entityCheckResult = performCheck(consumerData.entityIds(), entityNames, + SchemaRegistry::getEntityTypeByName); + final PersistableIdMap relationshipCheckResult = performCheck(consumerData.relationshipIds(), relationNames, + SchemaRegistry::getRelationTypeByName); + + if (!entityCheckResult.idsNotFound().isEmpty() || !relationshipCheckResult.idsNotFound().isEmpty()) { + + throw TiesException.resourceNotFoundException(entityCheckResult.idsNotFound(), relationshipCheckResult + .idsNotFound()); + } + + return new ImmutablePair<>(entityCheckResult, relationshipCheckResult); + } + + private PersistableIdMap performCheck(final List ids, final List names, + final Function supp) { + final Map> persistableWithIds = new HashMap<>(); + final Set idsNotFound = new HashSet<>(ids); + + for (String name : names) { + if (!idsNotFound.isEmpty()) { + + final Persistable persistable = supp.apply(name); + final SelectConditionStep> select = readDataDslContext.select(field(persistable + .getIdColumnNameWithTableName())).from(table(persistable.getTableName())).where(field(persistable + .getIdColumnNameWithTableName()).in(idsNotFound)); + final Result> result = select.fetch(); + + for (Record1 record : result) { + + if (!persistableWithIds.containsKey(persistable)) { + + List list = new ArrayList<>(); + list.add(record.get(0, String.class)); + + persistableWithIds.put(persistable, list); + } else { + persistableWithIds.get(persistable).add(record.get(0, String.class)); + } + + idsNotFound.remove(record.get(0, String.class)); + } + } else { + break; + } + } + return PersistableIdMap.builder().persistableWithIds(persistableWithIds).idsNotFound(idsNotFound).build(); + } + + protected T runMethodSafe(final Supplier supplier) { + try { + return supplier.get(); + } catch (DataAccessException ex) { + log.error("Sql exception during query execution", ex); + throw TiesException.serverSQLException(); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DecoratorsOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DecoratorsOperation.java new file mode 100644 index 0000000..1981cd6 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DecoratorsOperation.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import java.util.Map; + +import org.jooq.DSLContext; +import org.jooq.JSONB; +import org.jooq.Result; +import org.jooq.Record; + +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.schema.Persistable; +import org.oran.smo.teiv.service.models.OperationResult; +import org.oran.smo.teiv.utils.JooqTypeConverter; + +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Slf4j +public abstract class DecoratorsOperation extends ConsumerDataOperation> { + + protected DecoratorsOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + protected void saveResults(final Persistable persistable, final Result newResults, + final Map results) { + for (Record record : newResults) { + String id = (String) record.get(persistable.getIdColumnNameWithTableName()); + Map decoratorsAfterUpdate = JooqTypeConverter.jsonbToMap(record.get(String.format(QUOTED_STRING, + persistable.getDecoratorsColumnName()), JSONB.class)); + OperationResult operationResult = OperationResult.createDecoratorOperationResult(id, persistable.getName(), + persistable.getCategory(), decoratorsAfterUpdate); + + results.put(id, operationResult); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteClassifiersOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteClassifiersOperation.java new file mode 100644 index 0000000..f031072 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteClassifiersOperation.java @@ -0,0 +1,125 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import org.jooq.Configuration; +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.Record; +import org.jooq.Result; +import org.jooq.UpdateResultStep; +import org.oran.smo.teiv.exposure.consumerdata.model.ConsumerData; +import org.oran.smo.teiv.exposure.consumerdata.model.PersistableIdMap; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Component; + +import static org.jooq.impl.DSL.exists; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.select; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Component +public class DeleteClassifiersOperation extends ClassifiersOperation { + + public DeleteClassifiersOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + @Override + protected List performOperation(final PersistableIdMap map, final List consumerData, + final DSLContext writeDataDslContext) { + + final Map allResults = new HashMap<>(); + + map.persistableWithIds().forEach((persistable, ids) -> { + + for (String data : consumerData) { + final String classifiersColumnName = String.format(QUOTED_STRING, persistable.getClassifiersColumnName()); + final Field targetField = field(classifiersColumnName, JSONB.class); + final Field concatField = field(String.format("%s - '%s'", classifiersColumnName, data), + JSONB.class); + + final UpdateResultStep update = writeDataDslContext.update(table(persistable.getTableName())).set( + targetField, concatField).where(existsCondition(classifiersColumnName, data)).and(field(persistable + .getIdColumnNameWithTableName()).in(ids)).returning(field(persistable + .getIdColumnNameWithTableName()), field(String.format(QUOTED_STRING, persistable + .getClassifiersColumnName()), JSONB.class)); + + final Result newResults = update.fetch(); + final Map newOpResults = createOperationResults(persistable, newResults); + allResults.putAll(newOpResults); + } + }); + + return new ArrayList<>(allResults.values()); + } + + private Condition existsCondition(final String classifiersColumnName, final String data) { + return exists(select(field("1")).from(table("jsonb_array_elements_text(" + classifiersColumnName + ")").as( + "element")).where(field("element").eq(data))); + } + + /** + * Executes the operation for the given consumer data for specific entity type. + * + * @param consumerData + * which holds the information for classifiers/decorators, entity ids and relationship ids + * @param entityType + * entity type + */ + public List delete(final ConsumerData> consumerData, EntityType entityType) { + PersistableIdMap persistableIdMap = PersistableIdMap.builder().persistableWithIds(Map.of(entityType, consumerData + .entityIds())).build(); + + final List results = new ArrayList<>(); + writeDataDslContext.transaction((Configuration config) -> results.addAll(performOperation(persistableIdMap, + consumerData.data(), config.dsl()))); + return results; + } + + /** + * Executes the operation for the given consumer data for specific relation type. + * + * @param consumerData + * which holds the information for classifiers/decorators, entity ids and relationship ids + * @param relationType + * relation type + */ + public List delete(final ConsumerData> consumerData, RelationType relationType) { + PersistableIdMap persistableIdMap = PersistableIdMap.builder().persistableWithIds(Map.of(relationType, consumerData + .relationshipIds())).build(); + + final List results = new ArrayList<>(); + writeDataDslContext.transaction((Configuration config) -> results.addAll(performOperation(persistableIdMap, + consumerData.data(), config.dsl()))); + return results; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteDecoratorsOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteDecoratorsOperation.java new file mode 100644 index 0000000..68e4cf8 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/DeleteDecoratorsOperation.java @@ -0,0 +1,119 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import org.jooq.Condition; +import org.jooq.Configuration; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.Record; +import org.oran.smo.teiv.exposure.consumerdata.model.ConsumerData; +import org.oran.smo.teiv.exposure.consumerdata.model.PersistableIdMap; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Component; + +import org.jooq.Result; +import org.jooq.UpdateResultStep; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.jooq.impl.DSL.condition; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Component +public class DeleteDecoratorsOperation extends DecoratorsOperation { + + public DeleteDecoratorsOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + @Override + protected List performOperation(final PersistableIdMap map, final Map consumerData, + final DSLContext writeDataDslContext) { + + final Map allResults = new HashMap<>(); + + map.persistableWithIds().forEach((persistable, ids) -> consumerData.forEach((key, value) -> { + + final String decoratorsColumnName = String.format(QUOTED_STRING, persistable.getDecoratorsColumnName()); + final Field targetField = field(decoratorsColumnName, JSONB.class); + final Field concatField = field(String.format("%s - '%s'", decoratorsColumnName, key), JSONB.class); + + final UpdateResultStep update = writeDataDslContext.update(table(persistable.getTableName())).set( + targetField, concatField).where(keyExistsCondition(decoratorsColumnName, key).and(field(persistable + .getIdColumnNameWithTableName()).in(ids))).returning(field(persistable + .getIdColumnNameWithTableName()), field(String.format(QUOTED_STRING, persistable + .getDecoratorsColumnName()), JSONB.class)); + + final Result newResults = update.fetch(); + saveResults(persistable, newResults, allResults); + })); + + return new ArrayList<>(allResults.values()); + } + + private Condition keyExistsCondition(final String decoratorsColumnName, final String key) { + return condition(String.format("jsonb_exists(%s, '%s')", decoratorsColumnName, key)); + } + + /** + * Executes the operation for the given consumer data for specific entity type. + * + * @param consumerData + * which holds the information for classifiers/decorators, entity ids and relationship ids + * @param entityType + * entity type + */ + public List delete(final ConsumerData> consumerData, final EntityType entityType) { + PersistableIdMap persistableIdMap = PersistableIdMap.builder().persistableWithIds(Map.of(entityType, consumerData + .entityIds())).build(); + final List results = new ArrayList<>(); + writeDataDslContext.transaction((Configuration config) -> results.addAll(performOperation(persistableIdMap, + consumerData.data(), config.dsl()))); + return results; + } + + /** + * Executes the operation for the given consumer data for specific relation type. + * + * @param consumerData + * which holds the information for classifiers/decorators, entity ids and relationship ids + * @param relationType + * relation type + */ + public List delete(final ConsumerData> consumerData, + final RelationType relationType) { + PersistableIdMap persistableIdMap = PersistableIdMap.builder().persistableWithIds(Map.of(relationType, consumerData + .relationshipIds())).build(); + final List results = new ArrayList<>(); + writeDataDslContext.transaction((Configuration config) -> results.addAll(performOperation(persistableIdMap, + consumerData.data(), config.dsl()))); + return results; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeClassifiersOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeClassifiersOperation.java new file mode 100644 index 0000000..e251eb7 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeClassifiersOperation.java @@ -0,0 +1,93 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.jooq.DSLContext; +import org.jooq.Condition; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.Record; +import org.jooq.Result; +import org.jooq.UpdateResultStep; +import org.oran.smo.teiv.exposure.consumerdata.model.PersistableIdMap; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Component; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.notExists; +import static org.jooq.impl.DSL.select; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Component +@Slf4j +public class MergeClassifiersOperation extends ClassifiersOperation { + + public MergeClassifiersOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + @Override + protected List performOperation(final PersistableIdMap map, final List consumerData, + final DSLContext writeDataDslContext) { + + // Newer operations on the same entity/relationship makes old OperationResults obsolete, + // since we only care about the end result for given entity/relationship. + // We use a map with entity/relship ID as key, + // so we can automatically discard intermediary results. + final Map allResults = new HashMap<>(); + + map.persistableWithIds().forEach((persistable, ids) -> { + + for (String data : consumerData) { + final String classifiersColumnName = String.format(QUOTED_STRING, persistable.getClassifiersColumnName()); + final String concat = classifiersColumnName + " || '" + String.format(QUOTED_STRING, data) + "'"; + + final Field targetField = field(classifiersColumnName, JSONB.class); + final Field concatField = field(concat, JSONB.class); + + final UpdateResultStep update = writeDataDslContext.update(table(persistable.getTableName())).set( + targetField, concatField).where(notExistsCondition(classifiersColumnName, data)).and(field( + persistable.getIdColumnNameWithTableName()).in(ids)).returning(field(persistable + .getIdColumnNameWithTableName()), field(String.format(QUOTED_STRING, persistable + .getClassifiersColumnName()), JSONB.class)); + + final Result newResults = update.fetch(); + final Map newOpResults = createOperationResults(persistable, newResults); + allResults.putAll(newOpResults); + } + }); + + // Simplifying return type, as we need it to be a List anyway. + return new ArrayList<>(allResults.values()); + } + + private Condition notExistsCondition(final String classifiersColumnName, final String data) { + return notExists(select(field("1")).from(table("jsonb_array_elements_text(" + classifiersColumnName + ")").as( + "element")).where(field("element").eq(data))); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeDecoratorsOperation.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeDecoratorsOperation.java new file mode 100644 index 0000000..3493bb9 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/consumerdata/operation/MergeDecoratorsOperation.java @@ -0,0 +1,97 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.consumerdata.operation; + +import lombok.extern.slf4j.Slf4j; +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.Record; +import org.jooq.Result; +import org.jooq.UpdateResultStep; +import org.oran.smo.teiv.exposure.consumerdata.model.PersistableIdMap; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import static org.jooq.impl.DSL.condition; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.not; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Slf4j +@Component +public class MergeDecoratorsOperation extends DecoratorsOperation { + + public MergeDecoratorsOperation(DSLContext readDataDslContext, DSLContext writeDataDslContext) { + super(readDataDslContext, writeDataDslContext); + } + + @Override + protected List performOperation(final PersistableIdMap map, final Map consumerData, + final DSLContext writeDataDslContext) { + + final Map allResults = new HashMap<>(); + + map.persistableWithIds().forEach((persistable, ids) -> consumerData.forEach((key, value) -> { + + final String decoratorsColumnName = String.format(QUOTED_STRING, persistable.getDecoratorsColumnName()); + final String concat = String.format("%s || '{%s: %s}'", decoratorsColumnName, transformKey(key), transformValue( + value)); + + final Field targetField = field(decoratorsColumnName, JSONB.class); + final Field concatField = field(concat, JSONB.class); + + final UpdateResultStep update = writeDataDslContext.update(table(persistable.getTableName())).set( + targetField, concatField).where(not(keyValuePairExistsCondition(decoratorsColumnName, key, value)).or( + not(keyExistsCondition(decoratorsColumnName, key))).and(field(persistable + .getIdColumnNameWithTableName()).in(ids))).returning(field(persistable + .getIdColumnNameWithTableName()), field(String.format(QUOTED_STRING, persistable + .getDecoratorsColumnName()), JSONB.class)); + + final Result newResults = update.fetch(); + saveResults(persistable, newResults, allResults); + })); + return new ArrayList<>(allResults.values()); + } + + private String transformKey(final String key) { + return String.format("\"%s\"", key); + } + + private String transformValue(final Object value) { + return value instanceof String ? String.format("\"%s\"", value) : value.toString(); + } + + private Condition keyValuePairExistsCondition(final String decoratorsColumnName, final String key, final Object value) { + return condition(String.format("%s -> '%s' = '%s'", decoratorsColumnName, key, transformValue(value))); + } + + private Condition keyExistsCondition(final String decoratorsColumnName, final String key) { + return condition(String.format("jsonb_exists(%s, '%s')", decoratorsColumnName, key)); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/DataService.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/DataService.java index 85d5c48..99e10be 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/DataService.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/DataService.java @@ -25,45 +25,43 @@ import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; import org.oran.smo.teiv.api.model.OranTeivEntityTypes; import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; - -import java.util.Map; +import org.oran.smo.teiv.exposure.utils.RequestDetails; public interface DataService { /** * Get all the available topology domain types. * - * @param paginationDTO - * pagination data + * @param requestDetails + * - request details * * @return a collection of domain types */ - OranTeivDomains getDomainTypes(final PaginationDTO paginationDTO); + OranTeivDomains getDomainTypes(final RequestDetails requestDetails); /** * Get all entity types in a topology domain types. * * @param domain * domain name - * @param paginationDTO - * pagination data + * @param requestDetails + * - request details * * @return a collection of domain types */ - OranTeivEntityTypes getTopologyEntityTypes(final String domain, final PaginationDTO paginationDTO); + OranTeivEntityTypes getTopologyEntityTypes(final String domain, final RequestDetails requestDetails); /** * Get all relationship types in a topology domain types. * * @param domain * domain name - * @param paginationDTO - * pagination data + ** @param requestDetails + * - request details * * @return a collection of relationship types */ - OranTeivRelationshipTypes getTopologyRelationshipTypes(final String domain, final PaginationDTO paginationDTO); + OranTeivRelationshipTypes getTopologyRelationshipTypes(final String domain, final RequestDetails requestDetails); /** * Get topology for entity type with specified id. @@ -75,7 +73,7 @@ public interface DataService { * * @return a topology entity */ - Map getTopologyById(final String entityType, final String id); + Object getEntityById(final String entityType, final String id); /** * Get topology entities that match target, scope and relationships filters. @@ -86,13 +84,13 @@ public interface DataService { * specifies the entity type and attributes to be returned to the REST response * @param scopeFilter * specifies the attributes to match on - * @param paginationDTO - * pagination data + * @param requestDetails + * - request details * * @return a collection of entity data and attributes */ - OranTeivEntitiesResponseMessage getTopologyByType(final String entityType, final String targetFilter, - final String scopeFilter, final PaginationDTO paginationDTO); + OranTeivEntitiesResponseMessage getTopologyByType(final String domain, final String entityType, + final String targetFilter, final String scopeFilter, final RequestDetails requestDetails); /** * @@ -102,26 +100,34 @@ public interface DataService { * specifies the entity type and attributes to be returned to the REST response * @param scopeFilter * specifies the attributes to match on - * @param paginationDTO - * pagination data + * @param requestDetails + * - request details * * @return a collection of entity data and attributes */ OranTeivEntitiesResponseMessage getEntitiesByDomain(final String domain, final String targetFilter, - final String scopeFilter, final PaginationDTO paginationDTO); + final String scopeFilter, final RequestDetails requestDetails); /** * Get all relationships for entityType with specified id * + * @param domain + * domain name * @param entityType * type of entity, e.g. NRCellDU * @param id * unique identifier of entity + * @param targetFilter + * specifies the entity type and attributes to be returned to the REST response + * @param scopeFilter + * specifies the attributes to match on + * @param requestDetails + * - request details * * @return a collection of relationships for entity type */ - OranTeivRelationshipsResponseMessage getAllRelationshipsForObjectId(final String entityType, final String id, - final PaginationDTO paginationDTO); + OranTeivRelationshipsResponseMessage getAllRelationshipsForObjectId(final String domain, final String entityType, + final String targetFilter, final String scopeFilter, final String id, final RequestDetails requestDetails); /** * Get relationship with specified id @@ -133,7 +139,7 @@ public interface DataService { * * @return a topology relationship */ - Map getRelationshipById(final String relationshipType, final String id); + Object getRelationshipById(final String relationshipType, final String id); /** * @@ -141,11 +147,11 @@ public interface DataService { * type of relationship * @param scopeFilter * specifies the attributes to match on - * @param paginationDTO - * pagination data + * @param requestDetails + * - request details * * @return relationships by relationship type */ - OranTeivRelationshipsResponseMessage getRelationshipsByType(final String relationshipType, final String scopeFilter, - final PaginationDTO paginationDTO); + OranTeivRelationshipsResponseMessage getRelationshipsByType(final String domain, final String relationshipType, + final String targetFilter, final String scopeFilter, final RequestDetails requestDetails); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImpl.java index 1c6f220..323586a 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImpl.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImpl.java @@ -22,8 +22,22 @@ package org.oran.smo.teiv.exposure.data.api.impl; import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.Set; +import org.oran.smo.teiv.exposure.tiespath.resolver.ScopeResolver; +import org.jooq.Record; +import org.jooq.Result; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.DataRepository; +import org.oran.smo.teiv.exposure.spi.mapper.EntityMapper; +import org.oran.smo.teiv.exposure.spi.mapper.RelationshipMapper; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.InnerFilterCriteria; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.refiner.BasePathRefinement; +import org.oran.smo.teiv.exposure.tiespath.resolver.TargetResolver; +import org.oran.smo.teiv.exposure.utils.RequestDetails; import org.springframework.stereotype.Service; import org.oran.smo.teiv.api.model.OranTeivDomains; @@ -36,224 +50,218 @@ import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; import org.oran.smo.teiv.api.model.OranTeivRelationshipTypesItemsInner; import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; import org.oran.smo.teiv.exposure.data.api.DataService; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.mapper.MapperUtility; -import org.oran.smo.teiv.exposure.spi.mapper.PageMetaData; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; import org.oran.smo.teiv.schema.EntityType; import org.oran.smo.teiv.schema.RelationType; import org.oran.smo.teiv.schema.SchemaRegistry; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.firstHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.getViableLimit; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.lastHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.nextHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.prevHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.selfHref; + @Service @RequiredArgsConstructor public class DataServiceImpl implements DataService { - private final DataPersistanceService dataPersistanceService; - private final MapperUtility mapperUtility; + private final DataRepository dataRepository; + private final ScopeResolver scopeResolver; + private final TargetResolver targetResolver; + private final EntityMapper entityMapper; + private final RelationshipMapper relationshipMapper; + private final BasePathRefinement basePathRefinement; @Override - public OranTeivDomains getDomainTypes(final PaginationDTO paginationDTO) { - final Map result = mapperUtility.wrapList(new ArrayList<>(SchemaRegistry.getDomains()), - paginationDTO); - final List items = new ArrayList<>(); - final List itemsList = (List) result.get("items"); - itemsList.forEach(domain -> items.add(OranTeivDomainsItemsInner.builder().name(domain.toString()).entityTypes( - OranTeivHref.builder().href(paginationDTO.getBasePath() + "/" + domain + "/entity-types").build()) - .relationshipTypes(OranTeivHref.builder().href(paginationDTO - .getBasePath() + "/" + domain + "/relationship-types").build()).build())); - return getDomainsResponseMessage(result, items, paginationDTO.getLimit(), paginationDTO.getOffset()); + public OranTeivDomains getDomainTypes(final RequestDetails requestDetails) { + final Set domains = SchemaRegistry.getDomains(); + final int totalCount = domains.size(); + + final List items = domains.stream().skip(requestDetails.getOffset()).limit( + getViableLimit(requestDetails.getOffset(), requestDetails.getLimit(), totalCount)).map( + domain -> OranTeivDomainsItemsInner.builder().name(domain).entityTypes(OranTeivHref.builder().href( + requestDetails.getBasePath() + "/" + domain + "/entity-types").build()).relationshipTypes( + OranTeivHref.builder().href(requestDetails + .getBasePath() + "/" + domain + "/relationship-types").build()).build()) + .toList(); + + return OranTeivDomains.builder().items(items).first(firstHref(requestDetails)).prev(prevHref(requestDetails, + totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, totalCount)).last(lastHref( + requestDetails, totalCount)).totalCount(totalCount).build(); } @Override - public OranTeivEntityTypes getTopologyEntityTypes(final String domain, final PaginationDTO paginationDTO) { - final Map result = mapperUtility.wrapList(new ArrayList<>(SchemaRegistry.getEntityNamesByDomain( - domain)), paginationDTO); - final List items = new ArrayList<>(); - final List entities = SchemaRegistry.getEntityNamesByDomain(domain); - entities.stream().forEach(entity -> { - OranTeivEntityTypesItemsInner inner = new OranTeivEntityTypesItemsInner(); - OranTeivHref entitiesHref = new OranTeivHref(); - entitiesHref.setHref(paginationDTO.getBasePath() + "/" + entity + "/entities"); - inner.setName(entity); - inner.setEntities(entitiesHref); - items.add(inner); - }); - return getEntityTypesResponseMessage(result, items, paginationDTO.getLimit(), paginationDTO.getOffset()); + public OranTeivEntityTypes getTopologyEntityTypes(final String domain, final RequestDetails requestDetails) { + final List entityTypeNames = SchemaRegistry.getEntityNamesByDomain(domain); + final int totalCount = entityTypeNames.size(); + + final List items = entityTypeNames.stream().skip(requestDetails.getOffset()).limit( + getViableLimit(requestDetails.getOffset(), requestDetails.getLimit(), totalCount)).map( + entityTypeName -> OranTeivEntityTypesItemsInner.builder().name(entityTypeName).entities(OranTeivHref + .builder().href(requestDetails.getBasePath() + "/" + entityTypeName + "/entities").build()) + .build()).toList(); + + return OranTeivEntityTypes.builder().items(items).first(firstHref(requestDetails)).prev(prevHref(requestDetails, + totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, totalCount)).last(lastHref( + requestDetails, totalCount)).totalCount(totalCount).build(); } @Override - public OranTeivRelationshipTypes getTopologyRelationshipTypes(final String domain, final PaginationDTO paginationDTO) { - final Map result = mapperUtility.wrapList(new ArrayList<>(SchemaRegistry.getRelationNamesByDomain( - domain)), paginationDTO); - final List items = new ArrayList<>(); - final List relationships = SchemaRegistry.getRelationNamesByDomain(domain); - relationships.stream().forEach(relationship -> { - OranTeivRelationshipTypesItemsInner inner = new OranTeivRelationshipTypesItemsInner(); - OranTeivHref relationshipsHref = new OranTeivHref(); - relationshipsHref.setHref(paginationDTO.getBasePath() + "/" + relationship + "/relationships"); - inner.setName(relationship); - inner.setRelationships(relationshipsHref); - items.add(inner); - }); - return getRelationshipTypesResponseMessage(result, items, paginationDTO.getLimit(), paginationDTO.getOffset()); + public OranTeivRelationshipTypes getTopologyRelationshipTypes(final String domain, + final RequestDetails requestDetails) { + final List relationNames = SchemaRegistry.getRelationNamesByDomain(domain); + final int totalCount = relationNames.size(); + + final List items = relationNames.stream().skip(requestDetails.getOffset()) + .limit(getViableLimit(requestDetails.getOffset(), requestDetails.getLimit(), totalCount)).map( + relationName -> OranTeivRelationshipTypesItemsInner.builder().name(relationName).relationships( + OranTeivHref.builder().href(requestDetails + .getBasePath() + "/" + relationName + "/relationships").build()).build()).toList(); + + return OranTeivRelationshipTypes.builder().items(items).first(firstHref(requestDetails)).prev(prevHref( + requestDetails, totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, totalCount)).last( + lastHref(requestDetails, totalCount)).totalCount(totalCount).build(); } @Override - public Map getTopologyById(final String entityName, final String id) { + public Object getEntityById(final String entityName, final String id) { final EntityType entityType = SchemaRegistry.getEntityTypeByName(entityName); - return dataPersistanceService.getTopology(entityType, id); + final Result result = dataRepository.getEntityById(entityType, id); + if (result.isEmpty()) { + throw TiesException.resourceNotFoundException(); + } + + return entityMapper.getItemsWithTotalCount(result).getLeft().get(0); } @Override - public OranTeivEntitiesResponseMessage getTopologyByType(final String entityName, final String target, - final String scope, final PaginationDTO paginationDTO) { - final Map response = dataPersistanceService.getTopologyByType(entityName, target, scope, - paginationDTO); - return getEntitiesResponseMessage(response); + public OranTeivEntitiesResponseMessage getTopologyByType(final String domain, final String entityName, + final String target, final String scope, final RequestDetails requestDetails) { + final FilterCriteria filterCriteria = FilterCriteria.builder(domain).filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(targetResolver.resolve(entityName, target)).scope(scopeResolver.resolve(entityName, + scope)).build())).resolvingTopologyObjectType(FilterCriteria.ResolvingTopologyObjectType.ENTITY) + .build(); + final Result result = dataRepository.getTopologyByFilterCriteria(filterCriteria, requestDetails.getLimit(), + requestDetails.getOffset()); + return entityMapper.mapEntities(result, requestDetails); } @Override public OranTeivEntitiesResponseMessage getEntitiesByDomain(final String domain, final String fields, - final String filters, final PaginationDTO paginationDTO) { - final Map response = dataPersistanceService.getEntitiesByDomain(domain, fields, filters, - paginationDTO); - return getEntitiesResponseMessage(response); + final String filters, final RequestDetails requestDetails) { + final FilterCriteria filterCriteria = FilterCriteria.builder(domain).filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(targetResolver.resolve(null, fields)).scope(scopeResolver.resolve(null, filters)) + .build())).resolvingTopologyObjectType(FilterCriteria.ResolvingTopologyObjectType.ENTITY).build(); + final Result result = dataRepository.getTopologyByFilterCriteria(filterCriteria, requestDetails.getLimit(), + requestDetails.getOffset()); + return entityMapper.mapEntities(result, requestDetails); } @Override - public OranTeivRelationshipsResponseMessage getAllRelationshipsForObjectId(final String entityName, final String id, - final PaginationDTO paginationDTO) { - final EntityType entityType = SchemaRegistry.getEntityTypeByName(entityName); - final List relationTypes = SchemaRegistry.getRelationTypesByEntityName(entityName); - final Map response = dataPersistanceService.getAllRelationships(entityType, relationTypes, id, - paginationDTO); - return getRelationshipsResponseMessage(response); - } + public OranTeivRelationshipsResponseMessage getAllRelationshipsForObjectId(final String domain, final String entityName, + final String id, final String target, final String scope, final RequestDetails requestDetails) { - @Override - public Map getRelationshipById(final String relationName, final String id) { - return dataPersistanceService.getRelationshipWithSpecifiedId(id, SchemaRegistry.getRelationTypeByName( - relationName)); + final List relationNamesForEntityByDomain = SchemaRegistry.getRelationNamesForEntityByDomain( + entityName, domain); + final OranTeivRelationshipsResponseMessage response; + if (!relationNamesForEntityByDomain.isEmpty()) { + final FilterCriteria filterCriteria = FilterCriteria.builder(domain).filterCriteriaList(List.of( + InnerFilterCriteria.builder().targets(targetResolver.resolve(null, target)).scope(scopeResolver.resolve( + null, scope)).build())).resolvingTopologyObjectType( + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP).build(); + + basePathRefinement.refine(filterCriteria); + + List resolvedCriteriaList = new ArrayList<>(); + + relationNamesForEntityByDomain.forEach(relationType -> filterCriteria.getFilterCriteriaList().forEach( + innerFilterCriteria -> { + final String relationship = innerFilterCriteria.getTargets().get(0).getTopologyObject(); + if (relationship.equals(relationType.getName())) { + if (relationType.isConnectsSameEntity()) { + addLogicalBlockForLoopBackRelations(innerFilterCriteria, relationType.getASideAssociation() + .getName(), relationType.getBSideAssociation().getName(), id, resolvedCriteriaList); + } else if (relationType.getASide().getName().equals(entityName)) { + addAndLogicalBlockToFilter(innerFilterCriteria, relationType.getBSideAssociation() + .getName(), id, resolvedCriteriaList); + } else if (relationType.getBSide().getName().equals(entityName)) { + addAndLogicalBlockToFilter(innerFilterCriteria, relationType.getASideAssociation() + .getName(), id, resolvedCriteriaList); + } + } + })); + + final FilterCriteria build = FilterCriteria.builder(domain).resolvingTopologyObjectType( + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP).filterCriteriaList(resolvedCriteriaList) + .build(); + + final Result result = dataRepository.getTopologyByFilterCriteria(build, requestDetails.getLimit(), + requestDetails.getOffset()); + response = relationshipMapper.mapRelationships(result, requestDetails); + } else { + final int totalCount = 0; + response = OranTeivRelationshipsResponseMessage.builder().items(List.of()).first(firstHref(requestDetails)) + .prev(prevHref(requestDetails, totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, + totalCount)).last(lastHref(requestDetails, totalCount)).totalCount(totalCount).build(); + } + + if (response.getItems().isEmpty()) { + getEntityById(entityName, id); + } + return response; } @Override - public OranTeivRelationshipsResponseMessage getRelationshipsByType(final String relationName, final String scopeFilter, - final PaginationDTO paginationDTO) { - final Map response = dataPersistanceService.getRelationshipsByType(SchemaRegistry - .getRelationTypeByName(relationName), scopeFilter, paginationDTO); - return getRelationshipsResponseMessage(response); - } + public Object getRelationshipById(final String relationName, final String id) { + final RelationType relationType = SchemaRegistry.getRelationTypeByName(relationName); + final Result result = dataRepository.getRelationshipById(id, relationType); + if (result.isEmpty()) { + throw TiesException.resourceNotFoundException(); + } - private OranTeivEntitiesResponseMessage getEntitiesResponseMessage(Map response) { - OranTeivEntitiesResponseMessage result = new OranTeivEntitiesResponseMessage(); - List items = (List) response.get("items"); - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - Integer totalCount = (Integer) response.get("totalCount"); - - result.setItems(items); - - OranTeivHref selfHref = new OranTeivHref(); - OranTeivHref firstHref = new OranTeivHref(); - OranTeivHref prevHref = new OranTeivHref(); - OranTeivHref nextHref = new OranTeivHref(); - OranTeivHref lastHref = new OranTeivHref(); - - selfHref.setHref(self.getHref()); - firstHref.setHref(first.getHref()); - prevHref.setHref(prev.getHref()); - nextHref.setHref(next.getHref()); - lastHref.setHref(last.getHref()); - - result.setSelf(selfHref); - result.setFirst(firstHref); - result.setPrev(prevHref); - result.setNext(nextHref); - result.setLast(lastHref); - result.setTotalCount(totalCount); - return result; + return relationshipMapper.getItemsWithTotalCount(result).getLeft().get(0); } - private OranTeivRelationshipsResponseMessage getRelationshipsResponseMessage(Map response) { - OranTeivRelationshipsResponseMessage result = new OranTeivRelationshipsResponseMessage(); - List items = (List) response.get("items"); - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - Integer totalCount = (Integer) response.get("totalCount"); - - result.setItems(items); - - OranTeivHref selfHref = new OranTeivHref(); - OranTeivHref firstHref = new OranTeivHref(); - OranTeivHref prevHref = new OranTeivHref(); - OranTeivHref nextHref = new OranTeivHref(); - OranTeivHref lastHref = new OranTeivHref(); - - selfHref.setHref(self.getHref()); - firstHref.setHref(first.getHref()); - prevHref.setHref(prev.getHref()); - nextHref.setHref(next.getHref()); - lastHref.setHref(last.getHref()); - - result.setSelf(selfHref); - result.setFirst(firstHref); - result.setPrev(prevHref); - result.setNext(nextHref); - result.setLast(lastHref); - result.setTotalCount(totalCount); - return result; + @Override + public OranTeivRelationshipsResponseMessage getRelationshipsByType(final String domain, final String relationshipType, + final String targetFilter, final String scopeFilter, final RequestDetails requestDetails) { + final FilterCriteria filterCriteria = FilterCriteria.builder(domain).filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(targetResolver.resolve(relationshipType, targetFilter)).scope(scopeResolver.resolve( + relationshipType, scopeFilter)).build())).resolvingTopologyObjectType( + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP).build(); + final Result result = dataRepository.getTopologyByFilterCriteria(filterCriteria, requestDetails.getLimit(), + requestDetails.getOffset()); + return relationshipMapper.mapRelationships(result, requestDetails); } - private OranTeivDomains getDomainsResponseMessage(Map response, List items, - final Integer limit, final Integer offset) { - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - - return OranTeivDomains.builder().items(items.subList(offset, Math.min(offset + limit, items.size()))).first( - OranTeivHref.builder().href(first.getHref()).build()).prev(OranTeivHref.builder().href(prev.getHref()) - .build()).self(OranTeivHref.builder().href(self.getHref()).build()).next(OranTeivHref.builder() - .href(next.getHref()).build()).last(OranTeivHref.builder().href(last.getHref()).build()) - .totalCount(items.size()).build(); + // Helper method for adding AndLogicalBlock to FilterCriteria + private void addAndLogicalBlockToFilter(final InnerFilterCriteria innerFilterCriteria, final String associationName, + final String id, final List resolvedCriteriaList) { + AndLogicalBlock andLogicalBlock = createAndLogicalBlock(innerFilterCriteria, associationName, id); + innerFilterCriteria.setScope(andLogicalBlock); + resolvedCriteriaList.add(innerFilterCriteria); } - private OranTeivEntityTypes getEntityTypesResponseMessage(Map response, - List items, final Integer limit, final Integer offset) { - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - - return OranTeivEntityTypes.builder().items(items.subList(offset, Math.min(offset + limit, items.size()))).first( - OranTeivHref.builder().href(first.getHref()).build()).prev(OranTeivHref.builder().href(prev.getHref()) - .build()).self(OranTeivHref.builder().href(self.getHref()).build()).next(OranTeivHref.builder() - .href(next.getHref()).build()).last(OranTeivHref.builder().href(last.getHref()).build()) - .totalCount(items.size()).build(); + // Helper method used to add LogicalBlock for Rel connecting same entity to FilterCriteria + private void addLogicalBlockForLoopBackRelations(final InnerFilterCriteria innerFilterCriteria, + final String aSideAssociationName, final String bSideAssociationName, final String id, + final List resolvedCriteriaList) { + OrLogicalBlock orLogicalBlock = new OrLogicalBlock(); + orLogicalBlock.addChild(scopeResolver.resolve(null, "/" + aSideAssociationName + "[@id='" + id + "']")); + orLogicalBlock.addChild(scopeResolver.resolve(null, "/" + bSideAssociationName + "[@id='" + id + "']")); + AndLogicalBlock andLogicalBlock = new AndLogicalBlock(); + andLogicalBlock.addChild(innerFilterCriteria.getScope()); + andLogicalBlock.addChild(orLogicalBlock); + innerFilterCriteria.setScope(andLogicalBlock); + resolvedCriteriaList.add(innerFilterCriteria); } - private OranTeivRelationshipTypes getRelationshipTypesResponseMessage(Map response, - List items, final Integer limit, final Integer offset) { - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - - return OranTeivRelationshipTypes.builder().items(items.subList(offset, Math.min(offset + limit, items.size()))) - .first(OranTeivHref.builder().href(first.getHref()).build()).prev(OranTeivHref.builder().href(prev - .getHref()).build()).self(OranTeivHref.builder().href(self.getHref()).build()).next(OranTeivHref - .builder().href(next.getHref()).build()).last(OranTeivHref.builder().href(last.getHref()) - .build()).totalCount(items.size()).build(); + // Helper method to create AndLogicalBlock + private AndLogicalBlock createAndLogicalBlock(final InnerFilterCriteria innerFilterCriteria, + final String associationName, final String id) { + AndLogicalBlock andLogicalBlock = new AndLogicalBlock(); + andLogicalBlock.addChild(innerFilterCriteria.getScope()); + andLogicalBlock.addChild(scopeResolver.resolve(null, "/" + associationName + "[@id='" + id + "']")); + return andLogicalBlock; } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestController.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataController.java similarity index 79% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestController.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataController.java index f5f1705..bd151cc 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestController.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/data/rest/controller/DataController.java @@ -20,6 +20,8 @@ */ package org.oran.smo.teiv.exposure.data.rest.controller; +import java.util.function.Supplier; + import org.oran.smo.teiv.CustomMetrics; import org.oran.smo.teiv.api.EntitiesAndRelationshipsApi; import org.oran.smo.teiv.api.model.OranTeivDomains; @@ -28,30 +30,29 @@ import org.oran.smo.teiv.api.model.OranTeivEntityTypes; import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; import org.oran.smo.teiv.exposure.data.api.DataService; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; +import org.oran.smo.teiv.exposure.utils.RequestDetails; import org.oran.smo.teiv.exposure.utils.RequestValidator; import org.oran.smo.teiv.utils.TiesConstants; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import io.micrometer.core.annotation.Timed; import jakarta.validation.Valid; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.function.Supplier; @Slf4j @RestController @RequestMapping(TiesConstants.REQUEST_MAPPING) @RequiredArgsConstructor -public class DataRestController implements EntitiesAndRelationshipsApi { +public class DataController implements EntitiesAndRelationshipsApi { + public static final String SCOPE_FILTER = "scopeFilter"; + public static final String TARGET_FILTER = "targetFilter"; private final RequestValidator requestValidator; private final DataService dataService; @@ -61,37 +62,19 @@ public class DataRestController implements EntitiesAndRelationshipsApi { @Timed("ties_exposure_http_get_domain_types_seconds") public ResponseEntity getAllDomains(@NotNull String accept, @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { - return runWithFailCheck(() -> new ResponseEntity<>(dataService.getDomainTypes(PaginationDTO.builder().offset(offset) - .limit(limit).basePath("/domains").build()), HttpStatus.OK), + return runWithFailCheck(() -> new ResponseEntity<>(dataService.getDomainTypes(RequestDetails.builder().offset( + offset).limit(limit).basePath("/domains").build()), HttpStatus.OK), customMetrics::incrementNumUnsuccessfullyExposedDomainTypes); } - @Override - @Timed("ties_exposure_http_get_relationships_by_type_seconds") - public ResponseEntity getRelationshipsByType(@NotNull String accept, - String domain, String relationshipType, @Valid String targetFilter, @Valid String scopeFilter, - @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { - return runWithFailCheck(() -> { - requestValidator.validateDomain(domain); - requestValidator.validateRelationshipType(relationshipType); - requestValidator.validateRelationshipTypeInDomain(relationshipType, domain); - requestValidator.validateFiltersForRelationships(targetFilter, scopeFilter); - return ResponseEntity.ok(dataService.getRelationshipsByType(relationshipType, scopeFilter, PaginationDTO - .builder().offset(offset).limit(limit).addPathParameters("relationshipType", relationshipType).basePath( - String.format("/domains/%s/relationship-types/%s/relationships", domain, relationshipType)) - .addPathParameters("domain", domain).addQueryParameters("scopeFilter", scopeFilter).build())); - }, customMetrics::incrementNumUnsuccessfullyExposedRelationshipsByType); - } - @Override @Timed("ties_exposure_http_get_entity_types_seconds") public ResponseEntity getTopologyEntityTypes(@NotNull String accept, String domain, @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { return runWithFailCheck(() -> { requestValidator.validateDomain(domain); - return new ResponseEntity<>(dataService.getTopologyEntityTypes(domain, PaginationDTO.builder().offset(offset) - .limit(limit).basePath(String.format("/domains/%s/entity-types", domain)).addPathParameters("domain", - domain).build()), HttpStatus.OK); + return new ResponseEntity<>(dataService.getTopologyEntityTypes(domain, RequestDetails.builder().offset(offset) + .limit(limit).basePath(String.format("/domains/%s/entity-types", domain)).build()), HttpStatus.OK); }, customMetrics::incrementNumUnsuccessfullyExposedEntityTypes); } @@ -101,12 +84,28 @@ public class DataRestController implements EntitiesAndRelationshipsApi { @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { return runWithFailCheck(() -> { requestValidator.validateDomain(domain); - return new ResponseEntity<>(dataService.getTopologyRelationshipTypes(domain, PaginationDTO.builder().offset( - offset).limit(limit).basePath(String.format("/domains/%s/relationship-types", domain)) - .addPathParameters("domain", domain).build()), HttpStatus.OK); + return new ResponseEntity<>(dataService.getTopologyRelationshipTypes(domain, RequestDetails.builder().offset( + offset).limit(limit).basePath(String.format("/domains/%s/relationship-types", domain)).build()), + HttpStatus.OK); }, customMetrics::incrementNumUnsuccessfullyExposedRelationshipTypes); } + @Override + @Timed("ties_exposure_http_get_relationships_by_type_seconds") + public ResponseEntity getRelationshipsByType(@NotNull String accept, + String domain, String relationshipType, @Valid String targetFilter, @Valid String scopeFilter, + @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { + return runWithFailCheck(() -> { + requestValidator.validateDomain(domain); + requestValidator.validateRelationshipType(relationshipType); + requestValidator.validateRelationshipTypeInDomain(relationshipType, domain); + return ResponseEntity.ok(dataService.getRelationshipsByType(domain, relationshipType, targetFilter, scopeFilter, + RequestDetails.builder().offset(offset).limit(limit).basePath(String.format( + "/domains/%s/relationship-types/%s/relationships", domain, relationshipType)).queryParam( + SCOPE_FILTER, scopeFilter).queryParam(TARGET_FILTER, targetFilter).build())); + }, customMetrics::incrementNumUnsuccessfullyExposedRelationshipsByType); + } + @Override @Timed("ties_exposure_http_get_entity_by_id_seconds") public ResponseEntity getTopologyById(@NotNull final String accept, final String domain, @@ -115,7 +114,7 @@ public class DataRestController implements EntitiesAndRelationshipsApi { requestValidator.validateDomain(domain); requestValidator.validateEntityType(entityType); requestValidator.validateEntityTypeInDomain(entityType, domain); - return new ResponseEntity<>(dataService.getTopologyById(entityType, id), HttpStatus.OK); + return new ResponseEntity<>(dataService.getEntityById(entityType, id), HttpStatus.OK); }, customMetrics::incrementNumUnsuccessfullyExposedEntityById); } @@ -128,10 +127,10 @@ public class DataRestController implements EntitiesAndRelationshipsApi { requestValidator.validateDomain(domain); requestValidator.validateEntityType(entityType); requestValidator.validateEntityTypeInDomain(entityType, domain); - return ResponseEntity.ok(dataService.getTopologyByType(entityType, targetFilter, scopeFilter, PaginationDTO - .builder().offset(offset).limit(limit).basePath(String.format("/domains/%s/entity-types/%s/entities", - domain, entityType)).addPathParameters("domain", domain).addQueryParameters("targetFilter", - targetFilter).addQueryParameters("scopeFilter", scopeFilter).build())); + return ResponseEntity.ok(dataService.getTopologyByType(domain, entityType, targetFilter, scopeFilter, + RequestDetails.builder().offset(offset).limit(limit).basePath(String.format( + "/domains/%s/entity-types/%s/entities", domain, entityType)).queryParam(TARGET_FILTER, + targetFilter).queryParam(SCOPE_FILTER, scopeFilter).build())); }, customMetrics::incrementNumUnsuccessfullyExposedEntitiesByType); } @@ -142,10 +141,9 @@ public class DataRestController implements EntitiesAndRelationshipsApi { @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { return runWithFailCheck(() -> { requestValidator.validateDomain(domain); - return ResponseEntity.ok(dataService.getEntitiesByDomain(domain, targetFilter, scopeFilter, PaginationDTO - .builder().offset(offset).limit(limit).basePath("/domains/" + domain + "/entities").addPathParameters( - "domain", domain).addQueryParameters("targetFilter", targetFilter).addQueryParameters( - "scopeFilter", scopeFilter).build())); + return ResponseEntity.ok(dataService.getEntitiesByDomain(domain, targetFilter, scopeFilter, RequestDetails + .builder().offset(offset).limit(limit).basePath("/domains/" + domain + "/entities").queryParam( + TARGET_FILTER, targetFilter).queryParam(SCOPE_FILTER, scopeFilter).build())); }, customMetrics::incrementNumUnsuccessfullyExposedEntitiesByDomain); } @@ -159,11 +157,10 @@ public class DataRestController implements EntitiesAndRelationshipsApi { requestValidator.validateDomain(domain); requestValidator.validateEntityType(entityType); requestValidator.validateEntityTypeInDomain(entityType, domain); - return ResponseEntity.ok(dataService.getAllRelationshipsForObjectId(entityType, id, PaginationDTO.builder() - .offset(offset).limit(limit).basePath(String.format( - "/domains/%s/entity-types/%s/entities/%s/relationships", domain, entityType, id)) - .addPathParameters("domain", domain).addPathParameters("entityType", entityType).addPathParameters("id", - id).build())); + return ResponseEntity.ok(dataService.getAllRelationshipsForObjectId(domain, entityType, id, targetFilter, + scopeFilter, RequestDetails.builder().offset(offset).limit(limit).basePath(String.format( + "/domains/%s/entity-types/%s/entities/%s/relationships", domain, entityType, id)).queryParam( + TARGET_FILTER, targetFilter).queryParam(SCOPE_FILTER, scopeFilter).build())); }, customMetrics::incrementNumUnsuccessfullyExposedAllRelationshipsByEntityId); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/DecoratorsService.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/DecoratorsService.java new file mode 100644 index 0000000..f7347e5 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/DecoratorsService.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.decorators.api; + +import org.oran.smo.teiv.api.model.OranTeivDecorator; + +public interface DecoratorsService { + /** + * Updates the decorators of the specified entities and/or relationships + * + * @param oranTeivDecorator + * holds information for updating classifiers + */ + void update(OranTeivDecorator oranTeivDecorator); +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/impl/DecoratorsServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/impl/DecoratorsServiceImpl.java new file mode 100644 index 0000000..7f166c5 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/api/impl/DecoratorsServiceImpl.java @@ -0,0 +1,142 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.decorators.api.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataOperationRegistry; +import org.oran.smo.teiv.exposure.consumerdata.model.Decorators; +import org.oran.smo.teiv.exposure.consumerdata.operation.DecoratorsOperation; +import org.oran.smo.teiv.exposure.decorators.api.DecoratorsService; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.schema.ConsumerDataCache; +import org.oran.smo.teiv.schema.YangDataTypes; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.function.Consumer; + +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; + +@Slf4j +@Service +@RequiredArgsConstructor +public class DecoratorsServiceImpl implements DecoratorsService { + + private final ModelRepository modelRepository; + private final ConsumerDataCache consumerDataCache; + private final ConsumerDataOperationRegistry consumerDataOperationRegistry; + + @Override + public void update(final OranTeivDecorator oranTeivDecorator) { + + log.debug(String.format("Executing %s on decorators", oranTeivDecorator.getOperation())); + + List entityIds = oranTeivDecorator.getEntityIds(); + if (entityIds == null) { + entityIds = Collections.emptyList(); + } + + List relationshipIds = oranTeivDecorator.getRelationshipIds(); + if (relationshipIds == null) { + relationshipIds = Collections.emptyList(); + } + + final Map decoratorNames = oranTeivDecorator.getDecorators(); + Decorators decorators = Decorators.builder().data(decoratorNames).entityIds(entityIds).relationshipIds( + relationshipIds).build(); + + if (oranTeivDecorator.getOperation().equals(OranTeivDecorator.OperationEnum.MERGE)) { + runMethodSafe(this::validateMerge, decorators); + } else { + runMethodSafe(this::validateDelete, decorators); + } + + final DecoratorsOperation operation = consumerDataOperationRegistry.getDecoratorsOperation(oranTeivDecorator + .getOperation()); + + List results = operation.execute(decorators); + } + + public void validateMerge(final Decorators decorators) { + log.debug(String.format("Validating merging %s", decorators)); + + final Map problems = checkAvailability(decorators); + + if (!problems.isEmpty()) { + throw TiesException.invalidDecoratorsException(problems); + } + } + + public void validateDelete(final Decorators decorators) { + log.debug(String.format("Validating deleting %s", decorators)); + + for (String decorator : decorators.data().keySet()) { + final String schemaName = decorator.split(":")[0]; + if (!modelRepository.doesModuleExists(TIES_CONSUMER_DATA, schemaName)) { + throw TiesException.invalidSchema(schemaName); + } + } + } + + private Map checkAvailability(final Decorators decorators) { + final Map invalidKeys = new HashMap<>(); + + for (String key : decorators.data().keySet()) { + invalidKeys.put(key, "is_not_available"); + } + + decorators.data().forEach((key, value) -> { + + if (consumerDataCache.getDecorators().containsKey(key)) { + + final boolean isCompatible = checkCompatibility(key, value); + + if (isCompatible) { + invalidKeys.remove(key); + } else { + invalidKeys.put(key, "is_not_compatible"); + } + } + }); + + return invalidKeys; + } + + private boolean checkCompatibility(final String key, final Object value) { + return consumerDataCache.getDecorators().get(key).equals(YangDataTypes.fromRequestDataType(value.getClass())); + } + + private void runMethodSafe(Consumer consumer, Decorators classifiers) { + try { + consumer.accept(classifiers); + } catch (TiesException ex) { + log.error("Exception during validation", ex); + throw ex; + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/rest/controller/DecoratorsRestController.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/rest/controller/DecoratorsRestController.java index df158f5..3f49902 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/rest/controller/DecoratorsRestController.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/decorators/rest/controller/DecoratorsRestController.java @@ -20,14 +20,79 @@ */ package org.oran.smo.teiv.exposure.decorators.rest.controller; +import java.util.Collections; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Supplier; +import jakarta.servlet.http.HttpServletRequest; + +import io.micrometer.core.annotation.Timed; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.oran.smo.teiv.CustomMetrics; import org.oran.smo.teiv.api.DecoratorsApi; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.audit.AuditMapper; +import org.oran.smo.teiv.exposure.audit.LoggerHandler; +import org.oran.smo.teiv.exposure.decorators.api.DecoratorsService; import org.oran.smo.teiv.utils.TiesConstants; - +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Slf4j @RestController @RequestMapping(TiesConstants.REQUEST_MAPPING) +@RequiredArgsConstructor public class DecoratorsRestController implements DecoratorsApi { + private final DecoratorsService decoratorsService; + private final CustomMetrics customMetrics; + private final LoggerHandler loggerHandler; + private final HttpServletRequest context; + + @Value("${consumer-data.batch-size}") + private int limit; + + @Override + @Timed("ties_exposure_http_update_decorators_seconds") + public ResponseEntity updateDecorator(final String accept, final String contentType, + final OranTeivDecorator oranTeivDecorator) { + return runWithFailCheck(() -> { + if (Optional.ofNullable(oranTeivDecorator.getEntityIds()).orElseGet(Collections::emptyList).size() + Optional + .ofNullable(oranTeivDecorator.getRelationshipIds()).orElseGet(Collections::emptyList).size() > limit) { + throw TiesException.clientException("Limit exceeded", + "Number of entities and relationships exceeded the limit"); + } + runSafeMethod(() -> decoratorsService.update(oranTeivDecorator), status -> loggerHandler.logAudit(log, + AuditMapper.fromDecoratorsRequest(oranTeivDecorator, status).toString(), context)); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + }, customMetrics::incrementNumUnsuccessfullyUpdatedDecorators); + } + + private T runWithFailCheck(final Supplier supp, final Runnable runnable) { + try { + return supp.get(); + } catch (Exception ex) { + log.error("Exception during service call", ex); + runnable.run(); + throw ex; + } + } + + protected void runSafeMethod(final Runnable runnable, final Consumer logAudit) { + try { + runnable.run(); + logAudit.accept(HttpStatus.NO_CONTENT); + } catch (TiesException ex) { + logAudit.accept(ex.getStatus()); + log.error("Exception during service call", ex); + throw ex; + } + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelSchemaService.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelService.java similarity index 65% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelSchemaService.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelService.java index 416d19b..c46b488 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelSchemaService.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/ModelService.java @@ -20,57 +20,45 @@ */ package org.oran.smo.teiv.exposure.model.api; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; import org.oran.smo.teiv.api.model.OranTeivSchemaList; +import org.oran.smo.teiv.exposure.utils.RequestDetails; import org.springframework.web.multipart.MultipartFile; -public interface ModelSchemaService { +public interface ModelService { /** - * Create schema. + * Creates module from the yang file. * * @param yangFile * the yang content */ - void createSchema(final MultipartFile yangFile); + void createModule(final MultipartFile yangFile); /** - * Get all schemas extracted from yang models - * - * @param paginationDTO - * pagination data - * - * @return a map of all schemas - */ - OranTeivSchemaList getSchemas(final PaginationDTO paginationDTO); - - /** - * Get all schemas in a domain + * Gets all modules in a domain * * @param domain * domain name * @param paginationDTO * pagination data - * * @return a map of all schemas in a domain */ - OranTeivSchemaList getSchemasInDomain(final String domain, final PaginationDTO paginationDTO); + OranTeivSchemaList getModulesByDomain(final String domain, final RequestDetails paginationDTO); /** - * Get a yang schema name + * Gets module content * - * @param schema - * schema name - * - * @return a schema in a string format + * @param name + * name name + * @return the content */ - String getSchemaByName(final String schema); + String getModuleContentByName(final String name); /** - * Delete schema. + * Deletes module. * * @param name * the schema name */ - void deleteSchema(final String name); + void deleteConsumerModule(final String name); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelSchemaServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelSchemaServiceImpl.java deleted file mode 100644 index b43a85f..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelSchemaServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.model.api.impl; - -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.api.model.OranTeivSchema; -import org.oran.smo.teiv.api.model.OranTeivSchemaList; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.impl.StoredSchema; -import org.oran.smo.teiv.exposure.spi.mapper.PageMetaData; -import org.oran.smo.teiv.exposure.model.api.ModelSchemaService; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.util.*; - -import static org.oran.smo.teiv.utils.TiesConstants.IN_USAGE; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ModelSchemaServiceImpl implements ModelSchemaService { - - private final DataPersistanceService dataPersistanceService; - - @Override - public void createSchema(MultipartFile yangFile) { - log.trace("yang file: {}", yangFile); - } - - @Override - public OranTeivSchemaList getSchemas(final PaginationDTO paginationDTO) { - return getSchemaListResponseMessage(dataPersistanceService.getSchemas(paginationDTO)); - } - - @Override - public OranTeivSchemaList getSchemasInDomain(final String domainName, final PaginationDTO paginationDTO) { - return getSchemaListResponseMessage(dataPersistanceService.getSchemas(domainName, paginationDTO)); - } - - @Override - public String getSchemaByName(final String schemaName) { - final StoredSchema schema = dataPersistanceService.getSchema(schemaName); - if (schema == null || !schema.getStatus().equals(IN_USAGE)) { - throw TiesException.invalidSchema(schemaName); - } - return schema.getContent(); - } - - @Override - public void deleteSchema(String name) { - final StoredSchema schema = dataPersistanceService.getSchema(name); - if (schema == null) { - throw TiesException.invalidSchema(name); - } - if (schema.getOwnerAppId().equals("BUILT_IN_MODULE")) { - throw TiesException.schemaNotOwned(name); - } - dataPersistanceService.setSchemaToDeleting(name); - } - - private OranTeivSchemaList getSchemaListResponseMessage(Map response) { - OranTeivSchemaList result = new OranTeivSchemaList(); - List items = (List) response.get("items"); - PageMetaData self = (PageMetaData) response.get("self"); - PageMetaData first = (PageMetaData) response.get("first"); - PageMetaData prev = (PageMetaData) response.get("prev"); - PageMetaData next = (PageMetaData) response.get("next"); - PageMetaData last = (PageMetaData) response.get("last"); - Integer totalCount = (Integer) response.get("totalCount"); - - result.setItems(items); - - OranTeivHref selfHref = new OranTeivHref(); - OranTeivHref firstHref = new OranTeivHref(); - OranTeivHref prevHref = new OranTeivHref(); - OranTeivHref nextHref = new OranTeivHref(); - OranTeivHref lastHref = new OranTeivHref(); - - selfHref.setHref(self.getHref()); - firstHref.setHref(first.getHref()); - prevHref.setHref(prev.getHref()); - nextHref.setHref(next.getHref()); - lastHref.setHref(last.getHref()); - - result.setSelf(selfHref); - result.setFirst(firstHref); - result.setPrev(prevHref); - result.setNext(nextHref); - result.setLast(lastHref); - result.setTotalCount(totalCount); - return result; - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelServiceImpl.java new file mode 100644 index 0000000..2deee52 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/api/impl/ModelServiceImpl.java @@ -0,0 +1,157 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.model.api.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.api.model.OranTeivHref; +import org.oran.smo.teiv.api.model.OranTeivSchema; +import org.oran.smo.teiv.api.model.OranTeivSchemaList; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exception.YangModelException; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataRepository; +import org.oran.smo.teiv.exposure.model.api.ModelService; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.exposure.spi.Module; +import org.oran.smo.teiv.exposure.spi.ModuleStatus; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.oran.smo.teiv.schema.ConsumerDataCache; +import org.oran.smo.teiv.service.SchemaCleanUpService; +import org.oran.smo.teiv.utils.YangParser; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.firstHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.getViableLimit; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.lastHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.nextHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.prevHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.selfHref; +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; +import static org.oran.smo.teiv.utils.TiesConstants.DECORATORS; +import static org.oran.smo.teiv.utils.TiesConstants.INVALID_SCHEMA; +import static org.oran.smo.teiv.utils.TiesConstants.SCHEMA_ALREADY_EXISTS; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_MODEL; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModelServiceImpl implements ModelService { + private static final String CONTENT_HREF = "%s/%s/content"; + + private final ModelRepository modelRepository; + private final YangParser yangParser; + private final ConsumerDataRepository consumerDataRepository; + private final ConsumerDataCache consumerDataCaches; + private final SchemaCleanUpService schemaCleanUpService; + + @Override + public void createModule(final MultipartFile yangFile) { + log.debug("Create module with file: {}", yangFile); + final Map result; + final String content; + + try { + result = yangParser.validateSchemasYang(yangFile); + content = Base64.getEncoder().encodeToString(yangFile.getBytes()); + } catch (IOException | YangModelException e) { + log.warn(INVALID_SCHEMA, e); + throw TiesException.invalidFileInput(INVALID_SCHEMA); + } + + String moduleName = (String) result.get("moduleName"); + String revision = (String) result.get("revision"); + List classifiers = (List) result.get(CLASSIFIERS); + Map decorators = (Map) result.get(DECORATORS); + + if (modelRepository.doesModuleExists(TIES_MODEL, moduleName) || modelRepository.doesModuleExists(TIES_CONSUMER_DATA, + moduleName)) { + throw TiesException.invalidFileInput(SCHEMA_ALREADY_EXISTS); + } + + if (classifiers.isEmpty() && decorators.isEmpty()) { + throw TiesException.invalidFileInput(INVALID_SCHEMA); + } + + modelRepository.createModule(Module.builder().name(moduleName).content(content).revision(revision).ownerAppId("APP") + .status(ModuleStatus.IN_USAGE).build()); + + if (!classifiers.isEmpty()) { + consumerDataRepository.storeClassifiers(classifiers, moduleName); + } + + if (!decorators.isEmpty()) { + consumerDataRepository.storeDecorators(decorators, moduleName); + } + + consumerDataCaches.emptyConsumerDataCaches(); + + } + + @Override + public OranTeivSchemaList getModulesByDomain(final String domain, final RequestDetails requestDetails) { + log.debug("Get modules with domain : {}", domain); + final List modulesByDomain = modelRepository.getModules().stream().filter(s -> (domain == null) || (s + .getDomain() != null && s.getDomain().matches(domain))).toList(); + int totalCount = modulesByDomain.size(); + + final List items = modulesByDomain.stream().skip(requestDetails.getOffset()).limit(getViableLimit( + requestDetails.getOffset(), requestDetails.getLimit(), totalCount)).map(module -> OranTeivSchema.builder() + .name(module.getName()).domain(module.getDomain() == null ? "" : module.getDomain()).revision(module + .getRevision()).content(OranTeivHref.builder().href(String.format(CONTENT_HREF, + requestDetails.getBasePath(), module.getName())).build()).build()).toList(); + + return OranTeivSchemaList.builder().items(items).first(firstHref(requestDetails)).prev(prevHref(requestDetails, + totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, totalCount)).last(lastHref( + requestDetails, totalCount)).totalCount(totalCount).build(); + } + + @Override + public String getModuleContentByName(final String name) { + log.debug("Get {} module content", name); + return Optional.ofNullable(modelRepository.getModuleContentByName(name)).map(content -> new String(Base64 + .getDecoder().decode(content), StandardCharsets.UTF_8)).orElseGet(() -> { + log.warn("No schema found with name: {}", name); + throw TiesException.invalidSchema(name); + }); + } + + @Override + public void deleteConsumerModule(final String name) { + log.debug("Delete module: {}", name); + modelRepository.getConsumerModuleByName(name).ifPresentOrElse(module -> { + modelRepository.updateModuleStatus(name, ModuleStatus.DELETING); + schemaCleanUpService.cleanUpModule(name); + }, () -> { + log.warn("No module found with name: {}", name); + throw TiesException.invalidSchema(name); + }); + } + +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelSchemaRestController.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelController.java similarity index 54% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelSchemaRestController.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelController.java index ffd2e9e..e3422fe 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelSchemaRestController.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/model/rest/controller/ModelController.java @@ -20,66 +20,89 @@ */ package org.oran.smo.teiv.exposure.model.rest.controller; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; import org.oran.smo.teiv.api.SchemasApi; import org.oran.smo.teiv.api.model.OranTeivSchemaList; -import org.oran.smo.teiv.exposure.model.api.ModelSchemaService; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.audit.LoggerHandler; +import org.oran.smo.teiv.exposure.model.api.ModelService; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.oran.smo.teiv.exposure.utils.RequestValidator; import org.oran.smo.teiv.utils.TiesConstants; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.NotNull; -import java.util.Objects; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; + +@Slf4j @RestController @RequestMapping(TiesConstants.REQUEST_MAPPING) @RequiredArgsConstructor -public class ModelSchemaRestController implements SchemasApi { +public class ModelController implements SchemasApi { - private final ModelSchemaService modelSchemaService; + private final ModelService modelService; + private final RequestValidator requestValidator; + private final Logger logger = LoggerFactory.getLogger(ModelController.class); + private final LoggerHandler loggerHandler; + private final HttpServletRequest context; @Override public ResponseEntity createSchema(String accept, String contentType, MultipartFile file) { - modelSchemaService.createSchema(file); - return new ResponseEntity<>(HttpStatus.OK); + requestValidator.validateYangFile(file); + runSafeMethod(() -> modelService.createModule(file), "create"); + return new ResponseEntity<>(HttpStatus.CREATED); } - /** - * Return a list of all schemas/schemas filtered by domain extracted from yang models - */ @Override public ResponseEntity getSchemas(@NotNull final String accept, @Valid final String domain, @Min(0) @Valid final Integer offset, @Min(1) @Max(500) @Valid final Integer limit) { - final PaginationDTO.PaginationDTOBuilder builder = PaginationDTO.builder().offset(offset).limit(limit); - if (Objects.isNull(domain)) { - return new ResponseEntity<>(modelSchemaService.getSchemas(builder.basePath("/schemas").build()), HttpStatus.OK); - } else { - return new ResponseEntity<>(modelSchemaService.getSchemasInDomain(domain, builder.basePath("/schemas") - .addPathParameters("domain", domain).build()), HttpStatus.OK); + final RequestDetails.RequestDetailsBuilder builder = RequestDetails.builder().basePath("/schemas").offset(offset) + .limit(limit); + if (!Objects.isNull(domain)) { + builder.queryParam("domain", domain); } + + return new ResponseEntity<>(modelService.getModulesByDomain(domain, builder.build()), HttpStatus.OK); } - /** - * Return a schema by schema name - */ @Override @SneakyThrows public ResponseEntity getSchemaByName(@NotNull final String accept, final String schemaName) { - final String module = modelSchemaService.getSchemaByName(schemaName); + final String module = modelService.getModuleContentByName(schemaName); return new ResponseEntity<>(module, HttpStatus.OK); } @Override public ResponseEntity deleteSchema(String accept, String schemaName) { - modelSchemaService.deleteSchema(schemaName); - return new ResponseEntity<>(HttpStatus.OK); + runSafeMethod(() -> modelService.deleteConsumerModule(schemaName), "delete"); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + protected void runSafeMethod(final Runnable runnable, String operation) { + try { + runnable.run(); + loggerHandler.logAudit(logger, String.format("%s schema (successful)", StringUtils.capitalize(operation)), + context); + } catch (TiesException ex) { + loggerHandler.logAudit(logger, String.format("%s schema (failed)", StringUtils.capitalize(operation)), context); + log.error("Exception during service call", ex); + throw ex; + } + } + } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataPersistanceService.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataPersistanceService.java deleted file mode 100644 index df347dd..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataPersistanceService.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.oran.smo.teiv.exposure.spi.impl.StoredSchema; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.DataType; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.RelationType; - -public interface DataPersistanceService { - /** - * Gets topology. - * - * @param entityType - * the entityType - * @param id - * the id - * - * @return the topology - */ - Map getTopology(EntityType entityType, String id); - - /** - * Gets topology by type. - * - * @param entityName - * type of entity, e.g. NrCellDU - * @param targetFilter - * specifies the entity type and attributes to be returned in the REST response - * @param scopeFilter - * specifies the attributes to match on - * @param relationshipsFilter - * specifies the relationships to match on - * @param paginationDTO - * pagination data - * - * @return the all entities of type that match the filter criteria - */ - Map getTopologyByType(final String entityName, final String targetFilter, final String scopeFilter, - final PaginationDTO paginationDTO); - - /** - * Gets all relationships for objectType with specified id. - * - * @param entityType - * the entity type - * @param relationTypes - * the relation type - * @param id - * the id - * @param paginationDTO - * pagination data - * - * @return the all relationships - */ - Map getAllRelationships(final EntityType entityType, final List relationTypes, - final String id, final PaginationDTO paginationDTO); - - /** - * Gets relationship by id - * - * @param id - * the relationType id - * @param relationType - * the relationType - * - * @return relationship - */ - Map getRelationshipWithSpecifiedId(final String id, final RelationType relationType); - - /** - * Gets relationships for given edge. - * - * @param relationType - * represents the actual relationship type - * @param scopeFilter - * for filtering - * @param paginationDTO - * pagination data - * - * @return filtered relationships by given relationship type - */ - Map getRelationshipsByType(final RelationType relationType, final String scopeFilter, - final PaginationDTO paginationDTO); - - /** - * Get topology entities by domain, using specified targetFilter as mandatory query parameter - * - * @param domain - * specifies the domain - * @param targetFilter - * specifies the entity type and attributes to be returned in the REST response - * @param scopeFilter - * specifies the attributes to match on - * @param paginationDTO - * pagination data - * - * @return the all entities of type that match the filter criteria - */ - Map getEntitiesByDomain(final String domain, final String targetFilter, final String scopeFilter, - final PaginationDTO paginationDTO); - - /** - * Load classifiers set. - * - * @return the classifiers - */ - Set loadClassifiers(); - - /** - * Load decorators map. - * - * @return the decorators - */ - Map loadDecorators(); - - /** - * Gets schemas. - * - * @param paginationDTO - * the pagination dto - * @return the schemas - */ - Map getSchemas(final PaginationDTO paginationDTO); - - /** - * Gets schemas. - * - * @param domain - * the domain - * @param paginationDTO - * the pagination dto - * @return the schemas - */ - Map getSchemas(final String domain, final PaginationDTO paginationDTO); - - /** - * Gets schema. - * - * @param name - * the name - * @return the schema - */ - StoredSchema getSchema(final String name); - - /** - * Post schema. - * - * @param name - * the name - * @param namespace - * the namespace - * @param domain - * the domain - * @param includedModules - * the included modules - * @param content - * the content - * @param ownerAppId - * the owner App id - */ - void postSchema(final String name, final String namespace, final String domain, final List includedModules, - final String content, final String ownerAppId); - - /** - * Sets schema to deleting. - */ - void setSchemaToDeleting(final String name); - - /** - * Delete schema. - */ - void deleteSchema(final String name); -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataRepository.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataRepository.java new file mode 100644 index 0000000..ab15d24 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/DataRepository.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi; + +import java.util.List; +import java.util.Set; + +import org.jooq.Record; +import org.jooq.Result; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; + +public interface DataRepository { + /** + * Gets topology. + * + * @param entityType + * the entityType + * @param id + * the id + * @return the topology + */ + Result getEntityById(final EntityType entityType, final String id); + + /** + * Gets relationship by id + * + * @param id + * the relationType id + * @param relationType + * the relationType + * @return relationship + */ + Result getRelationshipById(final String id, final RelationType relationType); + + /** + * Get topology objects by a filter criteria + * + * @param filterCriteria + * the filter criteria + * @param limit + * the limit + * @param offset + * the offset + * + * @return the all topology objects of type that match the filter criteria + */ + Result getTopologyByFilterCriteria(final FilterCriteria filterCriteria, final int limit, final int offset); + + /** + * Gets classifiers for schema. + * + * @param schemaName + * the schema name + * @return the classifiers for schema + */ + Set getClassifiersForSchema(final String schemaName); + + /** + * Gets decorators for schema. + * + * @param schemaName + * the schema name + * @return the decorators for schema + */ + Set getDecoratorsForSchema(final String schemaName); + + /** + * Gets relationship ids for decorator deletion. + * + * @param relationType + * the relation type + * @param decorators + * the decorators + * @return the relationship ids for decorator deletion + */ + List getRelationshipIdsForDecoratorDeletion(final RelationType relationType, final Set decorators); + + /** + * Gets relationship ids for classifier deletion. + * + * @param relationType + * the relation type + * @param classifiers + * the classifiers + * @return the relationship ids for classifier deletion + */ + List getRelationshipIdsForClassifierDeletion(final RelationType relationType, final Set classifiers); + + /** + * Gets entity ids for decorator deletion. + * + * @param entityType + * the entity type + * @param decorators + * the decorators + * @return the entity ids for decorator deletion + */ + List getEntityIdsForDecoratorDeletion(final EntityType entityType, final Set decorators); + + /** + * Gets entity ids for classifier deletion. + * + * @param entityType + * the entity type + * @param classifiers + * the classifiers + * @return the entity ids for classifier deletion + */ + List getEntityIdsForClassifierDeletion(final EntityType entityType, final Set classifiers); +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModelRepository.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModelRepository.java new file mode 100644 index 0000000..320f29e --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModelRepository.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi; + +import java.util.List; +import java.util.Optional; + +/** + * Handles database operations for {@link Module} + */ +public interface ModelRepository { + + /** + * Checks whether the given module exists in the given schema. + * + * @param schemaName + * - schemaName name + * @param name + * - module name + * @return true if module exists + */ + + boolean doesModuleExists(final String schemaName, final String name); + + /** + * Gets module by name. + * + * @param name + * - the name + * @return the module + */ + Optional getConsumerModuleByName(final String name); + + /** + * Gets modules. + * + * @return the modules + */ + List getModules(); + + /** + * Gets module that were in the process of being deleted prior to pod restart. + * + * @return the module + */ + List getDeletingModulesOnStartup(); + + /** + * Gets module content by name. + * + * @param name + * the name + * @return the schema + */ + String getModuleContentByName(final String name); + + /** + * Creates module. + * + * @param module + * - module to create + */ + void createModule(Module module); + + /** + * Updates module status. + * + * @param name + * - name of the module + * @param status + * - status to update + */ + void updateModuleStatus(final String name, final ModuleStatus status); + + /** + * Deletes a module. + * + * @param name + * - name of the module + */ + void deleteModuleByName(final String name); + +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/Module.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/Module.java similarity index 81% rename from teiv/src/main/java/org/oran/smo/teiv/schema/Module.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/spi/Module.java index 76066e8..53136cb 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/Module.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/Module.java @@ -18,23 +18,24 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.schema; +package org.oran.smo.teiv.exposure.spi; import java.util.List; import lombok.Builder; -import lombok.Getter; import lombok.Singular; -import lombok.ToString; +import lombok.Value; -@Getter +@Value @Builder -@ToString public class Module { - private final String name; - private final String namespace; - private final String domain; - + String name; + String namespace; + String domain; @Singular - private final List includedModuleNames; + List includedModuleNames; + String revision; + String content; + String ownerAppId; + ModuleStatus status; } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModuleStatus.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModuleStatus.java new file mode 100644 index 0000000..c9d6d10 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/ModuleStatus.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi; + +/** + * Status of the {@link Module} + */ +public enum ModuleStatus { + IN_USAGE, + DELETING +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistanceServiceImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistanceServiceImpl.java deleted file mode 100644 index 1ee5811..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistanceServiceImpl.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.impl; - -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; -import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; -import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_MODEL; -import static org.jooq.impl.DSL.exists; -import static org.jooq.impl.DSL.field; -import static org.jooq.impl.DSL.select; -import static org.jooq.impl.DSL.table; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Supplier; - -import org.oran.smo.teiv.schema.DataType; -import org.oran.smo.teiv.utils.TiesConstants; -import org.jooq.DSLContext; -import org.jooq.JSONB; -import org.jooq.Record; -import org.jooq.Record1; -import org.jooq.Result; -import org.jooq.ResultQuery; -import org.jooq.tools.json.JSONArray; -import org.jooq.SelectConditionStep; -import org.springframework.stereotype.Service; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.RelationMappedRecordsDTO; -import org.oran.smo.teiv.exposure.spi.mapper.MapperUtility; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.utils.query.QueryMonad; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; - -@Slf4j -@Service -@RequiredArgsConstructor -public class DataPersistanceServiceImpl implements DataPersistanceService { - - private final DSLContext readDataDslContext; - private final DSLContext writeDataDslContext; - private final MapperUtility mapperUtility; - - @Override - public Map getTopology(final EntityType entityType, final String eiId) { - return runMethodSafe(() -> { - final Result result = readDataDslContext.select(entityType.getAllFieldsWithId()).from(entityType - .getTableName()).where(field(ID_COLUMN_NAME).eq(eiId)).fetch(); - if (result.isEmpty()) { - throw TiesException.resourceNotFoundException(); - } - return mapperUtility.mapEntity(entityType, result); - }); - } - - @Override - public Map getTopologyByType(final String entityType, final String target, final String scope, - final PaginationDTO paginationDTO) { - final QueryMonad queryMonad = QueryMonad.builder().managedObject(entityType).targets(target).scope(scope).build(); - final ResultQuery> queryCount = queryMonad.countWithSchema().apply(readDataDslContext); - paginationDTO.setTotalSize(runMethodSafe(() -> (int) queryCount.fetch().get(0).getValue(0))); - final ResultQuery query = queryMonad.withSchema(paginationDTO).apply(readDataDslContext); - log.trace("SQL :: " + query.getSQL()); - return runMethodSafe(() -> mapperUtility.mapComplexQuery(query.fetch(), paginationDTO)); - } - - @Override - public Map getAllRelationships(final EntityType entityType, final List relationTypes, - final String id, final PaginationDTO paginationDTO) { - List relationMappedRecordsDTOS = new ArrayList<>(); - int resultSize = 0; - - for (RelationType relationType : relationTypes) { - String columnNameToFindBy; - String columnNameToCheckIfNull; - - if (relationType.getASide().equals(entityType)) { - columnNameToFindBy = relationType.aSideColumnName(); - columnNameToCheckIfNull = relationType.bSideColumnName(); - } else { - columnNameToFindBy = relationType.bSideColumnName(); - columnNameToCheckIfNull = relationType.aSideColumnName(); - } - - Result result = runMethodSafe(() -> readDataDslContext.select(relationType.getBaseFieldsWithId()).from( - table(relationType.getTableName())).where(field(String.format(QUOTED_STRING, columnNameToFindBy)).eq(id) - .and(field(String.format(QUOTED_STRING, columnNameToCheckIfNull)).isNotNull())).fetch()); - - if (result.isNotEmpty()) { - result.forEach(record -> relationMappedRecordsDTOS.add(RelationMappedRecordsDTO.builder().relationType( - relationType).record(record).build())); - resultSize += result.size(); - } else if (!checkIfEntityWithIdExists(entityType, id)) { - throw TiesException.resourceNotFoundException(); - - } - - } - - paginationDTO.setTotalSize(resultSize); - return mapperUtility.wrapRelationships(relationMappedRecordsDTOS, relationTypes, readDataDslContext, paginationDTO); - } - - @Override - public Map getRelationshipWithSpecifiedId(final String id, final RelationType relationType) { - return runMethodSafe(() -> { - final Result result = readDataDslContext.select(relationType.getAllFieldsWithId()).from(table( - relationType.getTableName())).where(field(String.format(QUOTED_STRING, relationType.getIdColumnName())) - .eq(id)).fetch(); - if (result.isEmpty()) { - throw TiesException.resourceNotFoundException(); - } - return mapperUtility.mapRelationship(result, relationType); - }); - } - - @Override - public Map getRelationshipsByType(final RelationType relationType, final String scopeFilter, - final PaginationDTO paginationDTO) { - return runMethodSafe(() -> { - String attribute1; - String attribute2; - if (!relationType.getRelationshipStorageLocation().equals(RELATION)) { - attribute1 = relationType.getIdColumnName(); - attribute2 = relationType.aSideColumnName().equals("id") ? - relationType.bSideColumnName() : - relationType.aSideColumnName(); - } else { - attribute1 = relationType.aSideColumnName(); - attribute2 = relationType.bSideColumnName(); - } - final QueryMonad queryMonad = QueryMonad.builder().managedObject(relationType.getTableNameWithoutSchema()) - .targets(String.format("/id;/attributes(%s,%s)", getModelledName(attribute1), getModelledName( - attribute2))).scope(scopeFilter).relationships(relationType.getName()).build(); - final ResultQuery> queryCount = queryMonad.countWithSchema().apply(readDataDslContext); - paginationDTO.setTotalSize(runMethodSafe(() -> (int) queryCount.fetch().get(0).getValue(0))); - final ResultQuery query = queryMonad.withSchema(paginationDTO).apply(readDataDslContext); - log.trace("SQL :: " + query.getSQL()); - return mapperUtility.wrapMapObject(mapperUtility.mapRelationships(query.fetch(), relationType), paginationDTO); - }); - } - - @Override - public Map getEntitiesByDomain(final String domain, final String targetFilter, final String scopeFilter, - final PaginationDTO paginationDTO) { - final QueryMonad queryMonad = QueryMonad.builder().managedObject(null).targets(targetFilter).scope(scopeFilter) - .domain(domain).build(); - final ResultQuery query = queryMonad.withSchema(paginationDTO).apply(readDataDslContext); - final ResultQuery> queryCount = queryMonad.countWithSchema().apply(readDataDslContext); - paginationDTO.setTotalSize(runMethodSafe(() -> (int) queryCount.fetch().get(0).getValue(0))); - log.trace("SQL :: " + query.getSQL()); - return runMethodSafe(() -> mapperUtility.mapComplexQuery(query.fetch(), paginationDTO)); - } - - @Override - public Set loadClassifiers() { - SelectConditionStep availableClassifiers = runMethodSafe(() -> readDataDslContext.select().from(String - .format(TIES_MODEL, "classifiers")).join(String.format(TIES_MODEL, "module_reference")).on(field( - "\"moduleReferenceName\"").eq(field(String.format(TIES_MODEL, "module_reference") + ".name"))) - .where(field("status").like(TiesConstants.IN_USAGE))); - Set result = new HashSet<>(); - for (Record record : availableClassifiers) { - result.add((String) record.get("name")); - } - return result; - } - - @Override - public Map loadDecorators() { - SelectConditionStep availableDecorators = runMethodSafe(() -> readDataDslContext.select().from(String - .format(TIES_MODEL, "decorators")).join(String.format(TIES_MODEL, "module_reference")).on(field( - "\"moduleReferenceName\"").eq(field(String.format(TIES_MODEL, "module_reference") + ".name"))) - .where(field("status").like(TiesConstants.IN_USAGE))); - Map result = new HashMap<>(); - for (Record record : availableDecorators) { - result.put((String) record.get("name"), DataType.fromDbDataType("" + record.get("dataType"))); - } - return result; - } - - @Override - public Map getSchemas(PaginationDTO paginationDTO) { - final List schemas = runMethodSafe(() -> readDataDslContext.select().from(table(String.format( - TIES_MODEL, "module_reference"))).where(field("status").eq(TiesConstants.IN_USAGE)).fetchInto( - StoredSchema.class)); - - return mapperUtility.wrapSchema(new ArrayList<>(schemas), paginationDTO); - } - - @Override - public Map getSchemas(String domain, PaginationDTO paginationDTO) { - final List schemas = runMethodSafe(() -> readDataDslContext.select().from(table(String.format( - TIES_MODEL, "module_reference"))).where(field("status").eq(TiesConstants.IN_USAGE)).fetchInto( - StoredSchema.class)); - - return mapperUtility.wrapSchema(schemas.stream().filter(s -> s.getDomain() != null && s.getDomain().matches(domain)) - .toList(), paginationDTO); - } - - @Override - public StoredSchema getSchema(String name) { - List schemas = readDataDslContext.select().from(table(String.format(TIES_MODEL, "module_reference"))) - .where(field("name").eq(name)).fetchInto(StoredSchema.class); - if (schemas.isEmpty()) { - return null; - } - - schemas.get(0).setContent(new String(Base64.getDecoder().decode(schemas.get(0).getContent()), - StandardCharsets.UTF_8)); - - return schemas.get(0); - } - - @Override - public void postSchema(String name, String namespace, String domain, List includedModules, String content, - String ownerAppId) { - writeDataDslContext.insertInto(table(String.format(TIES_MODEL, "module_reference"))).set(field("name"), name).set( - field("namespace"), namespace).set(field("domain"), domain).set(field("\"includedModules\""), JSONB.valueOf( - JSONArray.toJSONString(includedModules))).set(field("content"), new String(Base64.getEncoder() - .encode(content.replaceAll("\\r\\n?", "\n").getBytes(StandardCharsets.UTF_8)), - StandardCharsets.UTF_8)).set(field("\"ownerAppId\""), ownerAppId).set(field("status"), - TiesConstants.IN_USAGE).execute(); - } - - @Override - public void setSchemaToDeleting(String name) { - writeDataDslContext.update(table(String.format(TIES_MODEL, "module_reference"))).set(field("status"), "DELETING") - .where(field("name").eq(name)).execute(); - } - - @Override - public void deleteSchema(String name) { - writeDataDslContext.deleteFrom(table(String.format(TIES_MODEL, "module_reference"))).where(field("name").eq(name)) - .execute(); - } - - private boolean checkIfEntityWithIdExists(final EntityType entityType, final String id) { - return readDataDslContext.select(exists(select(field("1")).from(table(entityType.getTableName())).where(field( - ID_COLUMN_NAME).eq(id)))).fetch().get(0).value1(); - } - - protected T runMethodSafe(Supplier supp) { - try { - return supp.get(); - } catch (TiesException ex) { - throw ex; - } catch (TiesPathException ex) { - log.error("Exception during query construction", ex); - throw ex; - } catch (Exception ex) { - log.error("Sql exception during query execution", ex); - throw TiesException.serverSQLException(); - } - } - -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImpl.java new file mode 100644 index 0000000..f21039f --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImpl.java @@ -0,0 +1,191 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi.impl; + +import static org.jooq.impl.DSL.falseCondition; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.jooq.impl.DSL.val; +import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.jooq.JSONB; +import org.jooq.Record; +import org.jooq.Result; +import org.jooq.SelectConditionStep; +import org.jooq.SelectOrderByStep; +import org.jooq.impl.DSL; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.DataRepository; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; +import org.oran.smo.teiv.exposure.tiespath.refiner.BasePathRefinement; +import org.oran.smo.teiv.exposure.tiespath.refiner.PathToJooqRefinement; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +@Slf4j +@Service +@RequiredArgsConstructor +public class DataRepositoryImpl implements DataRepository { + private final BasePathRefinement basePathRefinement; + + private final DSLContext readDataDslContext; + + @Value("${consumer-data.batch-size:100}") + private int batchSize = 100; + + @Override + public Result getEntityById(final EntityType entityType, final String id) { + return runMethodSafe(() -> readDataDslContext.select(entityType.getAllFieldsWithId()).from(entityType + .getTableName()).where(field(ID_COLUMN_NAME).eq(id)).fetch()); + } + + @Override + public Result getRelationshipById(final String id, final RelationType relationType) { + return runMethodSafe(() -> readDataDslContext.select(relationType.getAllFieldsWithId()).from(table(relationType + .getTableName())).where(field(String.format(QUOTED_STRING, relationType.getIdColumnName())).eq(id)) + .fetch()); + } + + @Override + public Result getTopologyByFilterCriteria(final FilterCriteria filterCriteria, final int limit, + final int offset) { + basePathRefinement.refine(filterCriteria); + SelectOrderByStep query = PathToJooqRefinement.toJooq(filterCriteria, offset, limit); + log.debug("SQL: {}", query); + + return runMethodSafe(() -> readDataDslContext.fetch(query)); + } + + @Override + public Set getClassifiersForSchema(final String schemaName) { + SelectConditionStep availableClassifiers = runMethodSafe(() -> readDataDslContext.select().from(String + .format(TIES_CONSUMER_DATA, "classifiers")).where(field("\"moduleReferenceName\"").eq(schemaName))); + Set result = new HashSet<>(); + for (Record record : availableClassifiers) { + result.add((String) record.get("name")); + } + return result; + } + + @Override + public Set getDecoratorsForSchema(final String schemaName) { + SelectConditionStep availableDecorators = runMethodSafe(() -> readDataDslContext.select().from(String + .format(TIES_CONSUMER_DATA, "decorators")).where(field("\"moduleReferenceName\"").like(schemaName))); + Set result = new HashSet<>(); + for (Record record : availableDecorators) { + result.add((String) record.get("name")); + } + return result; + } + + @Override + public List getRelationshipIdsForDecoratorDeletion(final RelationType relationType, + final Set decorators) { + Condition condition = falseCondition(); + for (String decorator : decorators) { + condition = condition.or(DSL.condition("{0}->>{1} IS NOT NULL", field(String.format(QUOTED_STRING, relationType + .getDecoratorsColumnName()), JSONB.class), val(decorator))); + } + + final Condition finalCondition = condition; + return runMethodSafe(() -> readDataDslContext.select(field(relationType.getTableName() + "." + String.format( + QUOTED_STRING, relationType.getIdColumnName()))).from(table(relationType.getTableName())).where(field( + relationType.getTableName() + "." + String.format(QUOTED_STRING, relationType.getIdColumnName())) + .isNotNull().and(finalCondition)).orderBy(field(String.format(QUOTED_STRING, "id"))).limit( + batchSize).fetchInto(String.class)); + } + + @Override + public List getRelationshipIdsForClassifierDeletion(final RelationType relationType, + final Set classifiers) { + Condition condition = falseCondition(); + for (String classifier : classifiers) { + condition = condition.or(field(String.format(QUOTED_STRING, relationType.getClassifiersColumnName()), + JSONB.class).contains(JSONB.valueOf("[\"" + classifier + "\"]"))); + } + + final Condition finalCondition = condition; + return runMethodSafe(() -> readDataDslContext.select(field(relationType.getTableName() + "." + String.format( + QUOTED_STRING, relationType.getIdColumnName()))).from(table(relationType.getTableName())).where(field( + relationType.getTableName() + "." + String.format(QUOTED_STRING, relationType.getIdColumnName())) + .isNotNull().and(finalCondition)).orderBy(field(String.format(QUOTED_STRING, "id"))).limit( + batchSize).fetchInto(String.class)); + } + + @Override + public List getEntityIdsForDecoratorDeletion(final EntityType entityType, final Set decorators) { + Condition condition = falseCondition(); + for (String decorator : decorators) { + condition = condition.or(DSL.condition("{0}->>{1} IS NOT NULL", field(String.format(QUOTED_STRING, entityType + .getDecoratorsColumnName()), JSONB.class), val(decorator))); + } + + final Condition finalCondition = condition; + return runMethodSafe(() -> readDataDslContext.select(field(entityType.getIdColumnName())).from(table(entityType + .getTableName())).where(finalCondition).orderBy(field(String.format(QUOTED_STRING, "id"))).limit(batchSize) + .fetchInto(String.class)); + } + + @Override + public List getEntityIdsForClassifierDeletion(final EntityType entityType, final Set classifiers) { + Condition condition = falseCondition(); + for (String classifier : classifiers) { + condition = condition.or(field(String.format(QUOTED_STRING, entityType.getClassifiersColumnName()), JSONB.class) + .contains(JSONB.valueOf("[\"" + classifier + "\"]"))); + } + + final Condition finalCondition = condition; + return runMethodSafe(() -> readDataDslContext.select(field(entityType.getIdColumnName())).from(table(entityType + .getTableName())).where(finalCondition).orderBy(field(String.format(QUOTED_STRING, "id"))).limit(batchSize) + .fetchInto(String.class)); + } + + protected T runMethodSafe(Supplier supp) { + try { + return supp.get(); + } catch (TiesException ex) { + throw ex; + } catch (TiesPathException ex) { + log.error("Exception during query construction", ex); + throw ex; + } catch (Exception ex) { + log.error("Sql exception during query execution", ex); + throw TiesException.serverSQLException(); + } + } + +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/ModelRepositoryImpl.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/ModelRepositoryImpl.java new file mode 100644 index 0000000..1e40eea --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/impl/ModelRepositoryImpl.java @@ -0,0 +1,170 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi.impl; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.name; +import static org.jooq.impl.DSL.noCondition; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.IN_USAGE; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_MODEL; +import static org.oran.smo.teiv.utils.TiesConstants.MODULE_REFERENCE; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jooq.DSLContext; +import org.jooq.Record; +import org.jooq.Record1; +import org.jooq.Select; +import org.jooq.SelectConditionStep; +import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.exposure.spi.Module; +import org.oran.smo.teiv.exposure.spi.ModuleStatus; + +@Slf4j +@Component +@RequiredArgsConstructor +public class ModelRepositoryImpl implements ModelRepository { + public static final String STATUS = "status"; + public static final String REVISION = "revision"; + public static final String NAME = "name"; + + private final DSLContext readDataDslContext; + private final DSLContext readWriteDataDslContext; + private final DSLContext writeDataDslContext; + + @Override + public boolean doesModuleExists(final String schemaName, final String name) { + final SelectConditionStep> query = readDataDslContext.selectOne().from(String.format(schemaName, + MODULE_REFERENCE)).where(field(name(NAME)).eq(name)); + return query.fetchAny() != null; + } + + @Override + public Optional getConsumerModuleByName(final String name) { + final Record moduleRecord = runMethodSafe(() -> readDataDslContext.select().from(table(String.format( + TIES_CONSUMER_DATA, MODULE_REFERENCE))).where(field("name").eq(name)).and(field(STATUS).eq( + ModuleStatus.IN_USAGE.name())).fetchAny()); + return Optional.ofNullable(moduleRecord).map(module -> Module.builder().name((String) module.get(NAME)).namespace( + (String) module.get("namespace")).revision((String) module.get(REVISION)).ownerAppId((String) module.get( + "ownerAppId")).status(ModuleStatus.valueOf((String) module.get(STATUS))).build()); + } + + @Override + public List getModules() { + return runMethodSafe(() -> { + final List modules = new ArrayList<>(); + final List modulesFromModelSchema = getModulesBySchema(TIES_MODEL); + final List modulesFromConsumerDataSchema = getModulesBySchema(TIES_CONSUMER_DATA); + modules.addAll(modulesFromModelSchema); + modules.addAll(modulesFromConsumerDataSchema); + return modules; + }); + } + + @Override + public List getDeletingModulesOnStartup() { + return runMethodSafe(() -> readWriteDataDslContext.select().from(table(String.format(TIES_CONSUMER_DATA, + MODULE_REFERENCE))).where(field(STATUS).eq(ModuleStatus.DELETING.name())).fetchInto(Module.class)); + } + + @Override + public String getModuleContentByName(final String name) { + return runMethodSafe(() -> { + String content = getModuleContentByNameFromSchema(TIES_MODEL, name); + if (content == null || content.equals("")) { + content = getModuleContentByNameFromSchema(TIES_CONSUMER_DATA, name); + } + return content; + }); + } + + @Override + public void createModule(Module module) { + runMethodSafe(() -> writeDataDslContext.insertInto(table(String.format(TIES_CONSUMER_DATA, MODULE_REFERENCE))).set( + field(NAME), module.getName()).set(field("content"), module.getContent()).set(field("\"ownerAppId\""), + module.getOwnerAppId()).set(field(STATUS), module.getStatus().name()).set(field(REVISION), module + .getRevision()).execute()); + } + + @Override + public void updateModuleStatus(String name, ModuleStatus status) { + runMethodSafe(() -> writeDataDslContext.update(table(String.format(TIES_CONSUMER_DATA, MODULE_REFERENCE))).set( + field(STATUS), status.name()).where(field("name").eq(name)).execute()); + } + + @Override + public void deleteModuleByName(String name) { + runMethodSafe(() -> writeDataDslContext.deleteFrom(table(String.format(TIES_CONSUMER_DATA, MODULE_REFERENCE))) + .where(field("name").eq(name)).execute()); + } + + private List getModulesBySchema(final String schemaName) { + Select moduleRecords = readDataDslContext.select().from(table(String.format(schemaName, MODULE_REFERENCE))) + .where(noCondition()); + Function buildModuleFunction; + + if (schemaName.equals(TIES_CONSUMER_DATA)) { + moduleRecords = moduleRecords.$where((field(STATUS).eq(IN_USAGE))); + buildModuleFunction = buildConsumerModules(); + } else { + buildModuleFunction = buildBuiltInModule(); + } + + return moduleRecords.stream().map(buildModuleFunction).toList(); + } + + private Function buildBuiltInModule() { + return moduleRecord -> Module.builder().name((String) moduleRecord.get(NAME)).namespace((String) moduleRecord.get( + "namespace")).domain((String) moduleRecord.get("domain")).revision((String) moduleRecord.get(REVISION)) + .build(); + } + + private Function buildConsumerModules() { + return moduleRecord -> Module.builder().name((String) moduleRecord.get(NAME)).namespace((String) moduleRecord.get( + "namespace")).revision((String) moduleRecord.get(REVISION)).ownerAppId((String) moduleRecord.get( + "ownerAppId")).status(ModuleStatus.valueOf((String) moduleRecord.get(STATUS))).build(); + } + + private String getModuleContentByNameFromSchema(final String schemaName, final String name) { + return readDataDslContext.select(field("content")).from(table(String.format(schemaName, MODULE_REFERENCE))).where( + field("name").eq(name)).limit(1).fetchAnyInto(String.class); + } + + private T runMethodSafe(Supplier supp) { + try { + return supp.get(); + } catch (Exception ex) { + log.warn("Exception occurred during query execution.", ex); + throw TiesException.serverSQLException(); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapper.java deleted file mode 100644 index b4dac6d..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapper.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import org.jooq.Field; -import org.jooq.Record; -import org.jooq.Result; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import org.oran.smo.teiv.schema.SchemaRegistry; - -@RequiredArgsConstructor -@Slf4j -public class ComplexMapper extends ResponseMapper { - - /** - * Maps the results of the queries created by the QueryModal to a REST response - * - * @param results - * results of the query - * @return a map of the results - */ - @Override - public Map map(Result results) { - final Map>> response = new HashMap<>(); - results.forEach(result -> { - Map record = new HashMap<>(); - Map mappedRecords = new HashMap<>(); - String currentObject = ""; - String objectName = ""; - for (Field field : result.fields()) { - String[] nameTokens = field.getName().split("\\."); - objectName = nameTokens[1].substring(1, nameTokens[1].length() - 1); - - if (!currentObject.isEmpty() && !objectName.equals(currentObject)) { - fillResult(currentObject, response, mappedRecords, record); - mappedRecords.clear(); - record.clear(); - } - fillRecord(nameTokens[2], record, mappedRecords, result, field); - currentObject = objectName; - } - fillResult(currentObject, response, mappedRecords, record); - }); - return Collections.unmodifiableMap(response); - } - - private void fillRecord(String nameToken, Map record, Map mappedRecords, Record result, - Field field) { - if (nameToken.replace("\"", "").equals(ID_COLUMN_NAME)) { - record.put(nameToken.replace("\"", ""), result.getValue(field)); - } else { - mappedRecords.put(getModelledName(nameToken.replace("\"", "")), mapField(result, field)); - } - } - - private void fillResult(String currentObject, Map>> response, - Map mappedRecords, Map record) { - if (!mappedRecords.values().stream().allMatch(Objects::isNull) || !record.values().stream().allMatch( - Objects::isNull)) { - String qualifiedName = SchemaRegistry.getEntityTypeByName(getModelledName(currentObject)) - .getFullyQualifiedName(); - response.putIfAbsent(qualifiedName, new ArrayList<>()); - if (!mappedRecords.values().stream().allMatch(Objects::isNull)) { - record.put(ATTRIBUTES, new HashMap<>(mappedRecords)); - } - response.get(qualifiedName).add(new HashMap<>(record)); - } - } - -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapper.java index 4e303db..fdacaa8 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapper.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapper.java @@ -20,51 +20,34 @@ */ package org.oran.smo.teiv.exposure.spi.mapper; -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.CONSUMER_DATA_PREFIX; -import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.firstHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.lastHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.nextHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.prevHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.selfHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.validateOffset; -import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Record; import org.jooq.Result; -import lombok.RequiredArgsConstructor; +import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.springframework.stereotype.Component; -import org.oran.smo.teiv.schema.EntityType; - -@RequiredArgsConstructor +@Slf4j +@Component public class EntityMapper extends ResponseMapper { - - final EntityType entityType; - - /** - * Maps the query results to an api response - * - * @param result - * result of the query - * @return response - */ - @Override - public Map map(final Result result) { - final Map responseData = new HashMap<>(); - final Map mappedRecords = new HashMap<>(); - result.forEach(record -> Arrays.stream(record.fields()).forEach(field -> { - if (getModelledName(field.getName()).equals(ID_COLUMN_NAME)) { - responseData.put(getModelledName(field.getName()), record.getValue(field)); - } else if (getModelledName(field.getName()).startsWith(CONSUMER_DATA_PREFIX)) { - responseData.put(getModelledName(field.getName()).substring(CONSUMER_DATA_PREFIX.length()), mapField(record, - field)); - } else { - mappedRecords.put(getModelledName(field.getName()), mapField(record, field)); - } - })); - responseData.put(ATTRIBUTES, mappedRecords); - return Map.of(entityType.getFullyQualifiedName(), List.of(responseData)); + public OranTeivEntitiesResponseMessage mapEntities(final Result results, final RequestDetails requestDetails) { + //Pair + final Pair, Integer> pair = getItemsWithTotalCount(results); + int totalCount = pair.getRight(); + validateOffset(requestDetails.getOffset(), totalCount); + return OranTeivEntitiesResponseMessage.builder().items(pair.getLeft()).first(firstHref(requestDetails)).prev( + prevHref(requestDetails, totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, + totalCount)).last(lastHref(requestDetails, totalCount)).totalCount(totalCount).build(); } - } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtility.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtility.java deleted file mode 100644 index b044516..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtility.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.spi.impl.StoredSchema; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; - -import java.util.Collections; -import java.util.stream.Collectors; -import org.jooq.DSLContext; -import org.jooq.Record; -import org.jooq.Result; -import org.springframework.stereotype.Service; - -import org.oran.smo.teiv.exposure.spi.RelationMappedRecordsDTO; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.RelationType; -import lombok.extern.slf4j.Slf4j; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Service -@Slf4j -public class MapperUtility { - - /** - * Maps the query results to an api response - * - * @param entityType - * entityType - * @param result - * result of the query - * - * @return response - */ - public Map mapEntity(final EntityType entityType, final Result result) { - return new EntityMapper(entityType).map(result); - } - - /** - * Maps all relationships - * - * @param result - * @param relationType - * @return all relationships - */ - public Map mapRelationships(final Result result, final RelationType relationType) { - return new RelationshipsMapper(relationType).map(result); - } - - /** - * Maps one relationship - * - * @param result - * @param relationType - * @return one relationship - */ - public Map mapRelationship(final Result result, final RelationType relationType) { - return new RelationshipMapper(relationType).map(result); - } - - /** - * Maps the results of the queries created by the QueryModal to a REST response - * - * @param results - * results of the query - * @param paginationDTO - * pagination data - * - * @return a map of the results - */ - public Map mapComplexQuery(final Result results, final PaginationDTO paginationDTO) { - return wrapResponse(results, new ComplexMapper(), paginationDTO); - } - - public Map wrapMapObject(final Map results, final PaginationDTO paginationDTO) { - - validateOffset(paginationDTO); - - Map response = new HashMap<>(); - response.put("items", List.of(results)); - - PaginationMetaData paginationMetaData = new PaginationMetaData(); - response.putAll(paginationMetaData.getObjectList(paginationDTO)); - - response.put("query", queryPart(paginationDTO)); - return response; - } - - public Map wrapList(final List objectsList, final PaginationDTO paginationDTO) { - Map response = new HashMap<>(); - paginationDTO.setTotalSize(objectsList.size()); - - if (objectsList.size() <= paginationDTO.getOffset() && !objectsList.isEmpty()) { - throw TiesException.invalidValueException("Offset", objectsList.size() - 1, true); - } else { - response.put("items", objectsList.subList(paginationDTO.getOffset(), Math.min(paginationDTO - .getOffset() + paginationDTO.getLimit(), objectsList.size()))); - } - - PaginationMetaData paginationMetaData = new PaginationMetaData(); - response.putAll(paginationMetaData.getObjectList(paginationDTO)); - - return response; - } - - public Map wrapSchema(final List schemaList, final PaginationDTO paginationDTO) { - List> response = new ArrayList<>(); - - for (StoredSchema schema : schemaList) { - Map innerResponse = new HashMap<>(); - innerResponse.put("name", schema.getName()); - innerResponse.put("domain", schema.getDomain() == null ? - Collections.emptyList() : - Collections.singletonList(schema.getDomain())); - innerResponse.put("revision", schema.getRevision()); - innerResponse.put("content", Collections.singletonMap("href", "/schemas/" + schema.getName() + "/content")); - response.add(innerResponse); - } - - return wrapList(new ArrayList<>(response), paginationDTO); - } - - private Map wrapResponse(final Result results, final ResponseMapper responseMapper, - final PaginationDTO paginationDTO) { - validateOffset(paginationDTO); - - Map response = new HashMap<>(); - response.put("items", List.of(responseMapper.map(results))); - - PaginationMetaData paginationMetaData = new PaginationMetaData(); - response.putAll(paginationMetaData.getObjectList(paginationDTO)); - - response.put("query", queryPart(paginationDTO)); - return response; - } - - private Map queryPart(final PaginationDTO paginationDTO) { - Map response = new HashMap<>(); - response.putAll(paginationDTO.getPathParameters()); - Map notNullQueryParameters = paginationDTO.getQueryParameters().entrySet().stream().filter( - entry -> entry.getValue() != null).collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry - .getValue())); - response.putAll(notNullQueryParameters); - - return response; - } - - public Map wrapRelationships(List records, List relationTypes, - DSLContext readDataDslContext, final PaginationDTO paginationDTO) { - Map response = new HashMap<>(); - - if (paginationDTO.getTotalSize() <= paginationDTO.getOffset() && !records.isEmpty()) { - throw TiesException.invalidValueException("Offset", records.size() - 1, true); - } else { - //TODO: Refactor the logic since RelationMappedRecordsDTO already contains the relation type - List pagedRecords = records.subList(paginationDTO.getOffset(), Math.min(paginationDTO - .getOffset() + paginationDTO.getLimit(), records.size())); - Map> batch = new HashMap<>(); - for (RelationMappedRecordsDTO record : pagedRecords) { - RelationType relTypeForCurrentRecord = record.getRelationType(); - if (!batch.containsKey(relTypeForCurrentRecord.getFullyQualifiedName())) { - batch.put(relTypeForCurrentRecord.getFullyQualifiedName(), readDataDslContext.newResult()); - } - batch.get(relTypeForCurrentRecord.getFullyQualifiedName()).add(record.getRecord()); - } - List> mappedResults = new ArrayList<>(); - for (Map.Entry> entry : batch.entrySet()) { - mappedResults.add(mapRelationships(entry.getValue(), relationTypes.stream().filter(relType -> relType - .getFullyQualifiedName().equals(entry.getKey())).findFirst().orElseThrow())); - } - response.put("items", mappedResults); - - } - - PaginationMetaData paginationMetaData = new PaginationMetaData(); - response.putAll(paginationMetaData.getObjectList(paginationDTO)); - - return response; - } - - private void validateOffset(PaginationDTO paginationDTO) { - if (paginationDTO.getTotalSize() < paginationDTO.getOffset()) { - throw TiesException.invalidValueException("Offset", paginationDTO.getTotalSize() - 1, true); - } - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PageMetaData.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PageMetaData.java deleted file mode 100644 index b0d6ca5..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PageMetaData.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import lombok.Getter; - -import java.util.Map; - -@Getter -public class PageMetaData { - - private final String href; - - public PageMetaData(final PaginationDTO paginationDTO) { - this(paginationDTO.getOffset(), paginationDTO.getLimit(), paginationDTO); - } - - public PageMetaData(final int offset, final PaginationDTO paginationDTO) { - this(offset, paginationDTO.getLimit(), paginationDTO); - } - - public PageMetaData(final int offset, final int limit, final PaginationDTO paginationDTO) { - StringBuilder stringBuilder = new StringBuilder(paginationDTO.getBasePath() + String.format("?offset=%s&limit=%s", - offset, limit)); - for (Map.Entry entry : paginationDTO.getQueryParameters().entrySet()) { - if (entry.getValue() != null) { - stringBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue()); - } - } - this.href = stringBuilder.toString(); - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaData.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaData.java deleted file mode 100644 index 3a44586..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaData.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; - -import java.util.HashMap; -import java.util.Map; - -public class PaginationMetaData { - - public Map getObjectList(final PaginationDTO paginationDTO) { - Map innerResponse = new HashMap<>(); - PageMetaData self = new PageMetaData(paginationDTO); - innerResponse.put("self", self); - - innerResponse.put("next", hasNextPage(paginationDTO) ? - new PageMetaData(Math.min(paginationDTO.getOffset() + paginationDTO.getLimit(), paginationDTO - .getTotalSize()), paginationDTO) : - self); - - innerResponse.put("last", hasNextPage(paginationDTO) ? - new PageMetaData(calculateLastPageOffset(paginationDTO), paginationDTO) : - self); - - innerResponse.put("first", new PageMetaData(0, paginationDTO)); - - innerResponse.put("prev", hasPrevPage(paginationDTO) ? - new PageMetaData(Math.max(paginationDTO.getOffset() - paginationDTO.getLimit(), 0), paginationDTO) : - self); - - innerResponse.put("totalCount", paginationDTO.getTotalSize()); - - return innerResponse; - } - - private boolean hasNextPage(final PaginationDTO paginationDTO) { - return (paginationDTO.getOffset() + paginationDTO.getLimit()) < paginationDTO.getTotalSize() && paginationDTO - .getTotalSize() > 0; - } - - private boolean hasPrevPage(final PaginationDTO paginationDTO) { - return paginationDTO.getOffset() > 0 && paginationDTO.getTotalSize() > 0; - } - - private int calculateLastPageOffset(final PaginationDTO paginationDTO) { - int diff = paginationDTO.getTotalSize() - paginationDTO.getOffset(); - - if (diff % paginationDTO.getLimit() == 0) { - return (diff / paginationDTO.getLimit() - 1) * paginationDTO.getLimit() + paginationDTO.getOffset(); - } - - return (diff / paginationDTO.getLimit()) * paginationDTO.getLimit() + paginationDTO.getOffset(); - - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/QueryMetaData.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/QueryMetaData.java deleted file mode 100644 index 92287a1..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/QueryMetaData.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import java.util.HashMap; -import java.util.Map; - -import lombok.AllArgsConstructor; - -import static org.oran.smo.teiv.utils.TiesConstants.QUERY; -import static org.oran.smo.teiv.utils.TiesConstants.SCOPE_FILTER; -import static org.oran.smo.teiv.utils.TiesConstants.TARGET_FILTER; - -@AllArgsConstructor -public class QueryMetaData { - - private String targetFilter; - private String scopeFilter; - - public Map getObjectList() { - Map response = new HashMap<>(); - Map innerResponse = new HashMap<>(); - - boolean hasResponse = false; - - if (!targetFilter.isEmpty()) { - innerResponse.put(TARGET_FILTER, targetFilter); - hasResponse = true; - - } - if (!scopeFilter.isEmpty()) { - innerResponse.put(SCOPE_FILTER, scopeFilter); - hasResponse = true; - } - if (hasResponse) { - response.put(QUERY, innerResponse); - } - return response; - } - -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapper.java index bfbe520..a4900e9 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapper.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapper.java @@ -20,25 +20,33 @@ */ package org.oran.smo.teiv.exposure.spi.mapper; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Record; import org.jooq.Result; -import org.oran.smo.teiv.schema.RelationType; -import lombok.RequiredArgsConstructor; +import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.springframework.stereotype.Component; -@RequiredArgsConstructor -public class RelationshipMapper extends ResponseMapper { - final RelationType relationType; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.firstHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.lastHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.nextHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.prevHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.selfHref; +import static org.oran.smo.teiv.exposure.utils.PaginationUtil.validateOffset; - @Override - public Map map(final Result record) { - final Map> relationshipMap = new HashMap<>(); - relationshipMap.put(relationType.getFullyQualifiedName(), List.of(createProperties(record.get(0), relationType))); - return Collections.unmodifiableMap(relationshipMap); +@Component +public class RelationshipMapper extends ResponseMapper { + public OranTeivRelationshipsResponseMessage mapRelationships(final Result results, + final RequestDetails requestDetails) { + //Pair + final Pair, Integer> pair = getItemsWithTotalCount(results); + int totalCount = pair.getRight(); + validateOffset(requestDetails.getOffset(), totalCount); + return OranTeivRelationshipsResponseMessage.builder().items(pair.getLeft()).first(firstHref(requestDetails)).prev( + prevHref(requestDetails, totalCount)).self(selfHref(requestDetails)).next(nextHref(requestDetails, + totalCount)).last(lastHref(requestDetails, totalCount)).totalCount(totalCount).build(); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapper.java deleted file mode 100644 index 9a6baf1..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapper.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.jooq.Record; -import org.jooq.Result; - -import org.oran.smo.teiv.schema.RelationType; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class RelationshipsMapper extends ResponseMapper { - - final RelationType relationType; - - @Override - public Map map(final Result result) { - final Map> relationshipsMap = new HashMap<>(); - final List relationships = new ArrayList<>(); - result.stream().filter(record -> Arrays.stream(record.valuesRow().fields()).noneMatch(field -> field.getName() - .equals("null"))).forEach(record -> relationships.add(createProperties(record, relationType))); - relationshipsMap.put(relationType.getFullyQualifiedName(), relationships); - return Collections.unmodifiableMap(relationshipsMap); - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ResponseMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ResponseMapper.java index 0316f8d..e5a8d68 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ResponseMapper.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/spi/mapper/ResponseMapper.java @@ -20,16 +20,19 @@ */ package org.oran.smo.teiv.exposure.spi.mapper; +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.getOriginalAlias; import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_A_SIDE; import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_B_SIDE; import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; import static org.oran.smo.teiv.utils.TiesConstants.SOURCE_IDS; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Field; import org.jooq.JSONB; import org.jooq.Record; @@ -38,12 +41,13 @@ import org.jooq.exception.DataTypeException; import org.oran.smo.teiv.schema.RelationType; import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.utils.TiesConstants; @Slf4j public abstract class ResponseMapper { - public abstract Map map(final Result result); + private static final String COUNT_FIELD = "count"; - protected Map createProperties(final Record record, RelationType relationType) { + protected Map createProperties(final Record record, final RelationType relationType) { final Map dataMap = new HashMap<>(); dataMap.put(ID_COLUMN_NAME, String.valueOf(record.get(relationType.getTableName() + "." + String.format( QUOTED_STRING, relationType.getIdColumnName())))); @@ -61,7 +65,7 @@ public abstract class ResponseMapper { return dataMap; } - protected Object mapField(Record record, org.jooq.Field field) { + protected Object mapField(final Record record, org.jooq.Field field) { try { return !field.getType().equals(JSONB.class) ? record.getValue(field) : record.get(field, Map.class); } catch (DataTypeException e) { @@ -69,4 +73,62 @@ public abstract class ResponseMapper { return record.get(field, List.class); } } + + public Pair, Integer> getItemsWithTotalCount(final Result results) { + List items = new ArrayList<>(); + int totalCount = 0; + for (Record result : results) { + String managedObject = null; + for (Field field : result.fields()) { + final String alias = getOriginalAlias(field.getName()); + String[] nameTokens = alias.split("\\."); + if (isCountField(nameTokens)) { + final Object count = result.get(COUNT_FIELD); + if (null != count) { + totalCount = (int) count; + } + break; + } + + if (isIdFieldNotNull(result, field, nameTokens)) { + managedObject = nameTokens[0]; + } + } + + if (managedObject != null) { + items.add(getItem(result, managedObject)); + } + } + return Pair.of(items, totalCount); + } + + private boolean isIdFieldNotNull(final Record result, final Field field, final String[] nameTokens) { + return nameTokens[1].equals(ID_COLUMN_NAME) && result.get(field) != null; + } + + private boolean isCountField(final String[] nameTokens) { + return nameTokens.length < 2 && nameTokens[0].equals(COUNT_FIELD); + } + + private Map getItem(final Record result, final String managedObject) { + Map item = new HashMap<>(); + Map data = new HashMap<>(); + Map attributes = new HashMap<>(); + for (Field field : result.fields()) { + final String alias = getOriginalAlias(field.getName()); + String[] nameTokens = alias.split("\\."); + if (nameTokens[0].equals(managedObject)) { + if (nameTokens[1].equals("attr")) { + attributes.put(nameTokens[2], mapField(result, field)); + } else { + data.put(nameTokens[1], mapField(result, field)); + } + } + } + if (!attributes.isEmpty()) { + data.put(TiesConstants.ATTRIBUTES, attributes); + } + item.put(managedObject, List.of(data)); + return item; + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/AndOrLogicalBlock.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/AndOrLogicalBlock.java index c68279c..9f1bb95 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/AndOrLogicalBlock.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/AndOrLogicalBlock.java @@ -22,7 +22,9 @@ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; import lombok.Data; import lombok.EqualsAndHashCode; -import org.jooq.util.xml.jaxb.Table; +import org.apache.commons.lang3.tuple.Pair; +import org.jooq.Field; +import org.jooq.Table; import java.util.ArrayList; import java.util.HashSet; @@ -40,4 +42,16 @@ public abstract class AndOrLogicalBlock extends LogicalBlock { tables.addAll(children.get(1).getTables()); return tables; } + + @Override + public Set> getJoinCondition() { + Set> tables = new HashSet<>(); + tables.addAll(children.get(0).getJoinCondition()); + tables.addAll(children.get(1).getJoinCondition()); + return tables; + } + + public void addChild(LogicalBlock logicalBlock) { + children.add(logicalBlock); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ConditionFactory.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ConditionFactory.java new file mode 100644 index 0000000..54faceb --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ConditionFactory.java @@ -0,0 +1,495 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.innerlanguage; + +import static org.jooq.impl.DSL.condition; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.name; +import static org.oran.smo.teiv.exposure.tiespath.innerlanguage.QueryFunction.EQ; +import static org.oran.smo.teiv.utils.PersistableUtil.getTableNameWithColumnName; +import static org.oran.smo.teiv.utils.TiesConstants.ITEM; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.List; +import java.util.Objects; + +import org.jooq.Condition; +import org.jooq.Field; +import org.jooq.JSONB; + +import lombok.experimental.UtilityClass; +import org.oran.smo.teiv.schema.DataType; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.Persistable; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.RelationshipDataLocation; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +@UtilityClass +public class ConditionFactory { + private static final String INVALID_TOPOLOGY_OBJECT_TYPE = "Invalid topology object type"; + private static final String INVALID_QUERY_FUNCTION = "Invalid query function"; + + public static AnyCondition create(final ScopeObject scopeObject) { + + return switch (scopeObject.getContainer()) { + case ATTRIBUTES -> new AttributesCondition(); + case RELATION -> new RelationCondition(); + case ID -> new IdCondition(); + case ASSOCIATION -> new AssociationCondition(); + case CLASSIFIERS, SOURCE_IDS -> new ConsumerDataListCondition(); + case DECORATORS -> new ConsumerDataMapCondition(); + }; + } + + abstract static class AnyCondition { + + public abstract Condition getCondition(final ScopeObject scopeObject); + + protected static Object convert(final ScopeObject scopeObject) { + + switch (scopeObject.getDataType()) { + case PRIMITIVE -> { + return String.valueOf(scopeObject.getParameter()); + } + case INTEGER -> { + return Integer.valueOf(scopeObject.getParameter()); + } + case BIGINT -> { + return new BigInteger(scopeObject.getParameter()); + } + case DECIMAL -> { + return new BigDecimal(scopeObject.getParameter()); + } + case CONTAINER -> { + return JSONB.valueOf(scopeObject.getParameter()); + } + case GEOGRAPHIC -> { + validateGeographicParameter(scopeObject.getParameter()); + return scopeObject.getParameter(); + } + default -> throw TiesPathException.invalidQueryCondition("Unexpected value: " + scopeObject.getDataType()); + } + } + + protected static Persistable getPersistable(final ScopeObject scopeObject) { + switch (scopeObject.getTopologyObjectType()) { + case ENTITY -> { + return SchemaRegistry.getEntityTypeByName(scopeObject.getTopologyObject()); + } + case RELATION -> { + return SchemaRegistry.getRelationTypeByName(scopeObject.getTopologyObject()); + } + default -> throw TiesPathException.invalidQueryCondition(INVALID_TOPOLOGY_OBJECT_TYPE); + } + } + + private static void validateGeographicParameter(final String parameter) { + if (!parameter.toLowerCase().startsWith("point(") || !parameter.endsWith(")")) { + throw TiesPathException.invalidQueryCondition("Invalid geographic format."); + } + + final String[] coordinates = parameter.substring(parameter.indexOf("(") + 1, parameter.indexOf(")")).split(" "); + if (coordinates.length != 2) { + throw TiesPathException.invalidQueryCondition( + "A point should have 2 coordinates (longitude and latitude)."); + } + + for (String coord : coordinates) { + try { + new BigDecimal(coord); + } catch (NumberFormatException ex) { + throw TiesPathException.invalidQueryCondition(String.format("Invalid coordinate: %s", coord)); + } + } + } + } + + static class AttributesCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + if (scopeObject.getInnerContainer().isEmpty()) { + return handleSimpleAttribute(scopeObject); + } + return handleComplexAttribute(scopeObject); + } + + private Condition handleSimpleAttribute(final ScopeObject scopeObject) { + switch (scopeObject.getQueryFunction()) { + case EQ -> { + if (scopeObject.getDataType().equals(DataType.GEOGRAPHIC)) { + return condition(String.format("%s = st_geomfromtext('%s')", handleSimpleLeaf(scopeObject), convert( + scopeObject))); + } + return field(handleSimpleLeaf(scopeObject)).eq(convert(scopeObject)); + } + case CONTAINS -> { + if (scopeObject.getDataType().equals(DataType.GEOGRAPHIC)) { + throw TiesPathException.invalidQueryCondition("Cannot have CONTAINS on geography type data"); + } + return field(handleSimpleLeaf(scopeObject)).contains(convert(scopeObject)); + } + default -> { + return field(handleSimpleLeaf(scopeObject)).isNotNull(); + } + } + } + + private Condition handleComplexAttribute(final ScopeObject scopeObject) { + switch (scopeObject.getQueryFunction()) { + case EQ -> { + if (scopeObject.getLeaf().equals(ITEM)) { + return condition(handleContainers(scopeObject) + String.format(" @> '%s'", handleEqComplexParameter( + scopeObject))); + } + return field(handleContainers(scopeObject) + String.format(" -> '%s'", scopeObject.getLeaf())).eq(field( + applyQuotes(handleEqComplexParameter(scopeObject)))); + } + case CONTAINS -> { + if (scopeObject.getLeaf().equals(ITEM)) { + return condition(handleContainersForArray(scopeObject) + String.format("::text like '%%%s%%'", + scopeObject.getParameter())); + } + return condition(field(handleContainers(scopeObject) + String.format(" ->> '%s'", scopeObject + .getLeaf())).like(handleLikeComplexParameter(scopeObject))); + } + default -> throw TiesPathException.invalidQueryCondition(INVALID_QUERY_FUNCTION); + } + } + + private String handleEqComplexParameter(final ScopeObject scopeObject) { + if (scopeObject.getDataType().equals(DataType.INTEGER)) { + return scopeObject.getParameter(); + } + return String.valueOf(name(scopeObject.getParameter())); + } + + private String handleLikeComplexParameter(final ScopeObject scopeObject) { + if (scopeObject.getDataType().equals(DataType.INTEGER)) { + return scopeObject.getParameter(); + } + return String.format("%%%s%%", scopeObject.getParameter()); + } + + private String handleSimpleLeaf(final ScopeObject scopeObject) { + return handleTopologyObjectType(scopeObject).getTableName() + "." + name(scopeObject.getLeaf()); + } + + private String handleContainers(final ScopeObject scopeObject) { + + if (scopeObject.getInnerContainer().size() > 1) { + StringBuilder sb = new StringBuilder(); + + for (String element : scopeObject.getInnerContainer().subList(1, scopeObject.getInnerContainer().size())) { + sb.append(" -> ").append(applyQuotes(element)); + } + return handleTopologyObjectType(scopeObject).getTableName() + "." + name(scopeObject.getInnerContainer() + .get(0)) + sb; + } + return handleTopologyObjectType(scopeObject).getTableName() + "." + name(scopeObject.getInnerContainer().get( + 0)); + } + + private String handleContainersForArray(final ScopeObject scopeObject) { + + if (scopeObject.getInnerContainer().size() > 1) { + StringBuilder sb = new StringBuilder(); + + for (String element : scopeObject.getInnerContainer().subList(1, scopeObject.getInnerContainer() + .size() - 1)) { + sb.append(" -> ").append(applyQuotes(element)); + } + sb.append(" ->> ").append(applyQuotes(scopeObject.getInnerContainer().get(scopeObject.getInnerContainer() + .size() - 1))); + return handleTopologyObjectType(scopeObject).getTableName() + "." + name(scopeObject.getInnerContainer() + .get(0)) + sb; + } + return handleTopologyObjectType(scopeObject).getTableName() + "." + name(scopeObject.getInnerContainer().get( + 0)); + } + + private Persistable handleTopologyObjectType(final ScopeObject scopeObject) { + Persistable persistable; + + switch (scopeObject.getTopologyObjectType()) { + case ENTITY -> persistable = SchemaRegistry.getEntityTypeByName(scopeObject.getTopologyObject()); + case RELATION -> persistable = SchemaRegistry.getRelationTypeByName(scopeObject.getTopologyObject()); + default -> throw TiesPathException.invalidQueryCondition(INVALID_TOPOLOGY_OBJECT_TYPE); + } + + return persistable; + } + + private static String applyQuotes(String element) { + return String.format("'%s'", element); + } + } + + static class RelationCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + + switch (scopeObject.getQueryFunction()) { + case EQ -> { + return equalsCondition(scopeObject); + } + case NOT_NULL -> { + return notNullCondition(scopeObject); + } + default -> throw TiesPathException.invalidQueryCondition(INVALID_QUERY_FUNCTION); + } + } + + private static Condition equalsCondition(final ScopeObject scopeObject) { + + return field(getColumnName(scopeObject)).eq(convert(scopeObject)); + } + + private static String getColumnName(final ScopeObject scopeObject) { + + if (Objects.requireNonNull(scopeObject.getTopologyObjectType()) == TopologyObjectType.ENTITY) { + + final List relationNames = SchemaRegistry.getRelationNamesByEntityName(scopeObject + .getTopologyObject()); + + final String relationName = relationNames.stream().filter(name -> name.equals(scopeObject + .getInnerContainer().get(0))).findFirst().orElseThrow(() -> TiesPathException.invalidQueryCondition( + "Relationship was not found for topology object")); + + final Persistable persistable = SchemaRegistry.getRelationTypeByName(relationName); + + return Objects.requireNonNull(persistable).getTableName() + "." + name(persistable.getIdColumnName()); + } else { + throw TiesPathException.invalidQueryCondition(INVALID_TOPOLOGY_OBJECT_TYPE); + } + } + + private static Condition notNullCondition(final ScopeObject scopeObject) { + + return field(getColumnName(scopeObject)).isNotNull(); + } + } + + static class AssociationCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + + RelationType relation; + + switch (scopeObject.getTopologyObjectType()) { + + case ENTITY -> { + final List relationTypes = SchemaRegistry.getAllRelationNamesByAssociationName(scopeObject + .getInnerContainer().get(0)); + relation = relationTypes.stream().filter(r -> r.getASide().getName().equals(scopeObject + .getTopologyObject()) || r.getBSide().getName().equals(scopeObject.getTopologyObject())) + .findFirst().orElseThrow(() -> TiesPathException.invalidQueryCondition( + "Relation was not found")); + } + case RELATION -> relation = SchemaRegistry.getRelationTypeByName(scopeObject.getTopologyObject()); + default -> throw TiesPathException.invalidQueryCondition(INVALID_TOPOLOGY_OBJECT_TYPE); + } + + switch (scopeObject.getQueryFunction()) { + case EQ, CONTAINS -> { + + EntityType entityType; + String sideColumnName; + + if (Objects.requireNonNull(relation).getRelationshipStorageLocation().equals( + RelationshipDataLocation.A_SIDE)) { + entityType = relation.getASide(); + sideColumnName = relation.bSideColumnName(); + } else if (relation.getRelationshipStorageLocation().equals(RelationshipDataLocation.B_SIDE)) { + entityType = relation.getBSide(); + sideColumnName = relation.aSideColumnName(); + } else { + if (relation.isConnectsSameEntity()) { + sideColumnName = checkSameEntityRelationship(relation, scopeObject); + } else { + sideColumnName = checkManyToMany(relation, scopeObject); + } + if (scopeObject.getQueryFunction().equals(EQ)) { + return condition(field(getTableNameWithColumnName(relation.getTableName(), sideColumnName)).eq( + scopeObject.getParameter())); + } + return condition(field(getTableNameWithColumnName(relation.getTableName(), sideColumnName)) + .contains(scopeObject.getParameter())); + + } + return ConditionFactory.getConditionContainsOrEquals(scopeObject, relation, entityType, sideColumnName); + } + case NOT_NULL -> { + return condition(field(SchemaRegistry.getReferenceColumnName(Objects.requireNonNull(relation))) + .isNotNull()); + } + default -> throw TiesPathException.invalidQueryCondition(INVALID_QUERY_FUNCTION); + } + } + + private static String checkManyToMany(RelationType relation, ScopeObject scopeObject) { + if (relation.getASide().getName().equals(scopeObject.getTopologyObject()) || SchemaRegistry + .getEntityTypeOnAssociationSide(relation, scopeObject.getInnerContainer().get(0)).getName().equals( + relation.getASide().getName())) { + return relation.bSideColumnName(); + } else { + return relation.aSideColumnName(); + } + } + + private static String checkSameEntityRelationship(RelationType relation, ScopeObject scopeObject) { + if (relation.getASideAssociation().getName().equals(scopeObject.getInnerContainer().get(0))) { + return relation.aSideColumnName(); + } else { + return relation.bSideColumnName(); + } + } + } + + private static Condition getConditionContainsOrEquals(ScopeObject scopeObject, RelationType relation, + EntityType entityType, String sideColumnName) { + if (scopeObject.getTopologyObject().equals(entityType.getName()) || SchemaRegistry.getEntityTypeOnAssociationSide( + relation, scopeObject.getInnerContainer().get(0)).getName().equals(entityType.getName())) { + Field field = field(getTableNameWithColumnName(Objects.requireNonNull(entityType).getTableName(), + sideColumnName)); + + if (scopeObject.getQueryFunction().equals(EQ)) { + return condition(field.eq(scopeObject.getParameter())); + } + return condition(field.contains(scopeObject.getParameter())); + + } else { + if (scopeObject.getQueryFunction().equals(EQ)) { + return condition(field(getTableNameWithColumnName(entityType.getTableName(), sideColumnName)).isNotNull()) + .and(condition(field(getTableNameWithColumnName(entityType.getTableName(), entityType + .getIdColumnName())).eq(scopeObject.getParameter()))); + } + return condition(field(getTableNameWithColumnName(entityType.getTableName(), sideColumnName)).isNotNull()).and( + condition(field(getTableNameWithColumnName(entityType.getTableName(), entityType.getIdColumnName())) + .contains(scopeObject.getParameter()))); + } + } + + static class ConsumerDataMapCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + if (scopeObject.getQueryFunction().equals(EQ)) { + + return equalsCondition(scopeObject); + } + + return containsCondition(scopeObject); + } + + private static String getColumnName(final ScopeObject scopeObject) { + + final Persistable persistable = getPersistable(scopeObject); + + return Objects.requireNonNull(persistable).getTableName() + "." + name(persistable.getDecoratorsColumnName()); + } + + private static Condition equalsCondition(final ScopeObject scopeObject) { + + String newValue = scopeObject.getParameter(); + + if (scopeObject.getDataType().equals(DataType.PRIMITIVE)) { + newValue = String.format("\"%s\"", convert(scopeObject)); + + } + + return field(getColumnName(scopeObject) + " -> '" + scopeObject.getLeaf() + "'").eq(field( + "'" + newValue + "'")); + } + + private static Condition containsCondition(final ScopeObject scopeObject) { + + return field(getColumnName(scopeObject) + " ->> '" + scopeObject.getLeaf() + "'").like("%" + scopeObject + .getParameter() + "%"); + } + } + + static class ConsumerDataListCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + if (scopeObject.getQueryFunction().equals(EQ)) { + + return equalsCondition(scopeObject); + } + + return containsCondition(scopeObject); + } + + private static String getColumnName(final ScopeObject scopeObject) { + + final Persistable persistable = getPersistable(scopeObject); + + if (scopeObject.getContainer().equals(ContainerType.CLASSIFIERS)) { + return Objects.requireNonNull(persistable).getTableName() + "." + name(persistable + .getClassifiersColumnName()); + } + + return Objects.requireNonNull(persistable).getTableName() + "." + name(persistable.getSourceIdsColumnName()); + } + + private static Condition equalsCondition(final ScopeObject scopeObject) { + + return condition(String.format("%s @> '\"%s\"'", getColumnName(scopeObject), scopeObject.getParameter())); + } + + private static Condition containsCondition(final ScopeObject scopeObject) { + + return condition(String.format("%s::text like '%%%s%%'", getColumnName(scopeObject), scopeObject + .getParameter())); + } + } + + static class IdCondition extends AnyCondition { + + @Override + public Condition getCondition(final ScopeObject scopeObject) { + + switch (scopeObject.getQueryFunction()) { + case EQ -> { + return field(getColumnName(scopeObject)).eq(convert(scopeObject)); + } + case CONTAINS -> { + return field(getColumnName(scopeObject)).contains(convert(scopeObject)); + } + case NOT_NULL -> { + return field(getColumnName(scopeObject)).isNotNull(); + } + default -> throw TiesPathException.invalidQueryCondition(INVALID_QUERY_FUNCTION); + } + } + + private static String getColumnName(final ScopeObject scopeObject) { + final Persistable persistable = getPersistable(scopeObject); + return persistable.getIdColumnNameWithTableName(); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ContainerType.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ContainerType.java index 46de5ff..3543c5d 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ContainerType.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ContainerType.java @@ -22,21 +22,23 @@ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; import jakarta.annotation.Nullable; import lombok.Getter; +import lombok.RequiredArgsConstructor; @Getter +@RequiredArgsConstructor public enum ContainerType { - ATTRIBUTES("attributes"), - DECORATORS("decorators"), - CLASSIFIERS("classifiers"), - ID("id"), - SOURCE_IDS("sourceIds"), - ASSOCIATION("association"); + ATTRIBUTES("attributes", true), + DECORATORS("decorators", false), + CLASSIFIERS("classifiers", false), + ID("id", false), + SOURCE_IDS("sourceIds", false), - private final String value; + //ToDo Resolver should not treat below two as containers but refinement do so this needs to be fixed + ASSOCIATION("association", false), + RELATION("relation", false); - ContainerType(String value) { - this.value = value; - } + private final String value; + private final boolean isParamAllowedInTargetFilter; @Nullable public static ContainerType fromValue(String value) { diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/EmptyLogicalBlock.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/EmptyLogicalBlock.java index 5ee9223..10e59c3 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/EmptyLogicalBlock.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/EmptyLogicalBlock.java @@ -22,8 +22,13 @@ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; import java.util.Collections; import java.util.Set; + +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Condition; -import org.jooq.util.xml.jaxb.Table; +import org.jooq.Field; +import org.jooq.Table; + +import static org.jooq.impl.DSL.noCondition; public class EmptyLogicalBlock extends LogicalBlock { private static EmptyLogicalBlock emptyLogicalBlock = null; @@ -40,11 +45,15 @@ public class EmptyLogicalBlock extends LogicalBlock { @Override public Condition getCondition() { - return null; + return noCondition(); } @Override public Set getTables() { return Collections.emptySet(); } + + public Set> getJoinCondition() { + return Collections.emptySet(); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteria.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteria.java index 56bb0ce..26b55e9 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteria.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteria.java @@ -20,57 +20,56 @@ */ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.Getter; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.jooq.Condition; import org.jooq.SelectField; -import org.jooq.util.xml.jaxb.Table; +import org.oran.smo.teiv.schema.DataType; -import java.util.ArrayList; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; @Data +@Builder(builderMethodName = "hiddenBuilder") @Slf4j public class FilterCriteria { + @NonNull private final String domain; - private List targets = new ArrayList<>(); - private LogicalBlock scope; + private final ResolvingTopologyObjectType resolvingTopologyObjectType; + private List filterCriteriaList; - public FilterCriteria(String domain) { - this.domain = domain; + public static FilterCriteriaBuilder builder(final String domain) { + return hiddenBuilder().domain(domain); } - public Condition getCondition() { - return scope.getCondition(); - } - - public Set
getTables() { - Set
tables = new HashSet<>(); - tables.addAll(scope.getTables()); + public Map> getSelects() { + Map> selectFields = new HashMap<>(); - targets.forEach(t -> tables.add(getTablesFromTarget(t))); - - return tables; - } - - public Set getSelects() { - Set selectFields = new HashSet<>(); - - targets.forEach(t -> selectFields.add(getSelectFromTarget(t))); + filterCriteriaList.forEach(t -> { + Map> selects = t.getSelects(); + for (Map.Entry> select : selects.entrySet()) { + if (!selectFields.containsKey(select.getKey())) { + selectFields.put(select.getKey(), new HashMap<>()); + } + selectFields.get(select.getKey()).putAll(select.getValue()); + } + }); return selectFields; } - private SelectField getSelectFromTarget(TargetObject t) { - log.trace(t.toString()); - return null; - } + @Getter + @AllArgsConstructor + public enum ResolvingTopologyObjectType { + RELATIONSHIP(true, false), + ENTITY(false, true), + ALL(true, true); - @SuppressWarnings("squid:S4144") - private Table getTablesFromTarget(TargetObject t) { - log.trace(t.toString()); - return null; + private final boolean resolveRelationships; + private final boolean resolveEntities; } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/InnerFilterCriteria.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/InnerFilterCriteria.java new file mode 100644 index 0000000..b44c7d0 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/InnerFilterCriteria.java @@ -0,0 +1,163 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.innerlanguage; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; +import static org.oran.smo.teiv.utils.PersistableUtil.getFullyQualifiedNameWithColumnName; +import static org.oran.smo.teiv.utils.PersistableUtil.getTableNameWithColumnName; +import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_A_SIDE; +import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_B_SIDE; +import static org.oran.smo.teiv.utils.TiesConstants.SOURCE_IDS; +import static org.oran.smo.teiv.utils.TiesConstants.DECORATORS; +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; + +import org.apache.commons.lang3.tuple.Pair; +import org.jooq.Condition; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.SelectField; +import org.jooq.Table; + +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.schema.DataType; +import org.oran.smo.teiv.schema.Persistable; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.SchemaRegistry; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Data +@Slf4j +@Builder +public class InnerFilterCriteria { + private List targets; + private LogicalBlock scope; + + public Condition getCondition() { + return scope.getCondition(); + } + + public Set
getTables() { + Set
tables = new HashSet<>(); + tables.addAll(scope.getTables()); + + targets.forEach(t -> tables.add(getTableFromTarget(t))); + + return tables; + } + + public Set> getJoinCondition() { + Set> joins = new HashSet<>(); + joins.addAll(scope.getJoinCondition()); + + return joins; + } + + public Map> getSelects() { + Map> selectFields = new HashMap<>(); + + targets.forEach(t -> { + Pair> select = getSelectFromTarget(t); + if (!selectFields.containsKey(select.getLeft())) { + selectFields.put(select.getLeft(), new HashMap<>()); + } + selectFields.get(select.getLeft()).putAll(select.getRight()); + }); + + return selectFields; + } + + @SuppressWarnings({ "java:S108", "java:S5738" }) + private Pair> getSelectFromTarget(TargetObject targetObject) { + Map select = new HashMap<>(); + + final Persistable persistable; + String idColumn; + switch (targetObject.getTopologyObjectType()) { + case ENTITY -> { + persistable = SchemaRegistry.getEntityTypeByName(targetObject.getTopologyObject()); + idColumn = getTableNameWithColumnName(persistable.getTableName(), ID_COLUMN_NAME); + } + case RELATION -> { + persistable = SchemaRegistry.getRelationTypeByName(targetObject.getTopologyObject()); + idColumn = getTableNameWithColumnName(persistable.getTableName(), persistable.getIdColumnName()); + + select.put(field(getTableNameWithColumnName(persistable.getTableName(), ((RelationType) persistable) + .aSideColumnName())).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable + .getFullyQualifiedName(), PROPERTY_A_SIDE))), DataType.PRIMITIVE); + select.put(field(getTableNameWithColumnName(persistable.getTableName(), ((RelationType) persistable) + .bSideColumnName())).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable + .getFullyQualifiedName(), PROPERTY_B_SIDE))), DataType.PRIMITIVE); + } + default -> throw TiesException.unParsedTopologyObjectType(targetObject.getTopologyObject()); + } + + select.put(field(idColumn).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable.getFullyQualifiedName(), + ID_COLUMN_NAME))), DataType.PRIMITIVE); + + switch (targetObject.getContainer()) { + case ATTRIBUTES -> { + if (targetObject.isAllParamQueried()) { + select.putAll(persistable.getSpecificAttributeColumns(List.of())); + } else { + select.putAll(persistable.getSpecificAttributeColumns(targetObject.getParams())); + } + } + case DECORATORS -> select.put(field(getTableNameWithColumnName(persistable.getTableName(), persistable + .getDecoratorsColumnName()), JSONB.class).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable + .getFullyQualifiedName(), DECORATORS))), DataType.CONTAINER); + case CLASSIFIERS -> select.put(field(getTableNameWithColumnName(persistable.getTableName(), persistable + .getClassifiersColumnName()), JSONB.class).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable + .getFullyQualifiedName(), CLASSIFIERS))), DataType.CONTAINER); + case ID -> { + } + case SOURCE_IDS -> select.put(field(getTableNameWithColumnName(persistable.getTableName(), persistable + .getSourceIdsColumnName()), JSONB.class).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable + .getFullyQualifiedName(), SOURCE_IDS))), DataType.CONTAINER); + default -> throw TiesException.invalidContainerType(targetObject.getContainer().getValue()); + } + + return Pair.of(field(idColumn).as(hashAlias(getFullyQualifiedNameWithColumnName(persistable.getFullyQualifiedName(), + ID_COLUMN_NAME))), select); + } + + public Table getTableFromTarget(TargetObject targetObject) { + switch (targetObject.getTopologyObjectType()) { + case ENTITY -> { + return table(SchemaRegistry.getEntityTypeByName(targetObject.getTopologyObject()).getTableName()); + } + case RELATION -> { + return table(SchemaRegistry.getRelationTypeByName(targetObject.getTopologyObject()).getTableName()); + } + default -> throw TiesException.unParsedTopologyObjectType(targetObject.getTopologyObject()); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/LogicalBlock.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/LogicalBlock.java index b5154f7..e44e101 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/LogicalBlock.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/LogicalBlock.java @@ -21,8 +21,10 @@ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; import lombok.Data; +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Condition; -import org.jooq.util.xml.jaxb.Table; +import org.jooq.Field; +import org.jooq.Table; import java.util.Set; @@ -33,4 +35,6 @@ public abstract class LogicalBlock { public abstract Condition getCondition(); public abstract Set
getTables(); + + public abstract Set> getJoinCondition(); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/QueryFunction.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/QueryFunction.java index fee1f36..a52fe57 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/QueryFunction.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/QueryFunction.java @@ -20,7 +20,27 @@ */ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; +import lombok.Getter; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +@Getter public enum QueryFunction { - EQ, - CONTAINS + EQ("="), + CONTAINS("contains"), + NOT_NULL("notNull"); + + private final String value; + + QueryFunction(String value) { + this.value = value; + } + + public static QueryFunction fromValue(String value) { + for (QueryFunction queryFunction : QueryFunction.values()) { + if (queryFunction.getValue().equals(value)) { + return queryFunction; + } + } + throw TiesPathException.grammarError("Unsupported operation: " + value); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlock.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlock.java index 373b858..ccd17db 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlock.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlock.java @@ -20,15 +20,32 @@ */ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; -import java.util.Collections; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jooq.Condition; -import org.jooq.util.xml.jaxb.Table; +import org.jooq.Field; +import org.jooq.Table; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.RelationshipDataLocation; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; import java.util.Set; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.PersistableUtil.getTableNameWithColumnName; +import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + @Data @EqualsAndHashCode(callSuper = true) @RequiredArgsConstructor @@ -37,11 +54,96 @@ public class ScopeLogicalBlock extends LogicalBlock { @Override public Condition getCondition() { - return null; + return ConditionFactory.create(scopeObject).getCondition(scopeObject); } @Override public Set
getTables() { - return Collections.emptySet(); + + Set
result = new HashSet<>(); + + if (scopeObject.getContainer().equals(ContainerType.ASSOCIATION)) { + result.add(addAssociationToTable()); + } else if (scopeObject.getTopologyObjectType() == TopologyObjectType.ENTITY) { + result.add(addEntityToTable()); + } else if (scopeObject.getTopologyObjectType() == TopologyObjectType.RELATION) { + result.add(addRelationToTable()); + } else if (scopeObject.getTopologyObjectType() == TopologyObjectType.UNDEFINED) { + throw TiesException.unknownTopologyObjectType(scopeObject.getTopologyObject()); + } + + return result; } + + public Set> getJoinCondition() { + HashSet> joinCondition = new HashSet<>(); + if (scopeObject.getContainer().equals(ContainerType.ASSOCIATION) && scopeObject.getTopologyObjectType().equals( + TopologyObjectType.ENTITY)) { + EntityType entityType = SchemaRegistry.getEntityTypeByName(scopeObject.getTopologyObject()); + String association = scopeObject.getInnerContainer().get(0); + List relationTypes = SchemaRegistry.getAllRelationNamesByAssociationName(association); + + RelationType relationType = relationTypes.stream().filter(relation -> relation.getASide().equals( + entityType) || relation.getBSide().equals(entityType)).findFirst().orElseThrow(() -> TiesPathException + .invalidAssociation(entityType.getName(), association)); + + if (relationType.getRelationshipStorageLocation().equals(RelationshipDataLocation.RELATION)) { + String columnName = ""; + if (relationType.getASide().equals(entityType)) { + columnName = relationType.aSideColumnName(); + } else { + columnName = relationType.bSideColumnName(); + } + String col1 = constructColumnNameForJoinCondition(relationType, columnName); + String col2 = getTableNameWithColumnName(entityType.getTableName(), ID_COLUMN_NAME); + + joinCondition.add(constructJoinConditionPair(relationType, col1, col2)); + } else if (!relationType.getStoringSideEntityType().equals(scopeObject.getTopologyObject())) { + String col1 = constructColumnNameForJoinCondition(relationType, relationType + .getNotStoringSideEntityIdColumnNameInStoringSideTable()); + String col2 = getTableNameWithColumnName(relationType.getNotStoringSideTableName(), ID_COLUMN_NAME); + + joinCondition.add(constructJoinConditionPair(relationType, col1, col2)); + } + } + return joinCondition; + } + + private static String constructColumnNameForJoinCondition(RelationType relationType, String columnName) { + return relationType.getTableName() + "." + String.format(QUOTED_STRING, columnName); + } + + private static Pair constructJoinConditionPair(RelationType relationType, String col1, String col2) { + Field equalsField = field(col1 + "=" + col2); + return new ImmutablePair<>(relationType.getTableName(), equalsField); + } + + private Table addEntityToTable() { + return table(SchemaRegistry.getEntityTypeByName(scopeObject.getTopologyObject()).getTableName()); + } + + private Table addRelationToTable() { + return table(SchemaRegistry.getRelationTypeByName(scopeObject.getTopologyObject()).getTableName()); + } + + private Table addAssociationToTable() { + List relationTypes = SchemaRegistry.getAllRelationNamesByAssociationName(scopeObject + .getInnerContainer().get(0)); + if (scopeObject.getTopologyObjectType().equals(TopologyObjectType.ENTITY)) { + for (RelationType relation : relationTypes) { + if (relation.getASide().getName().equals(scopeObject.getTopologyObject()) || relation.getBSide().getName() + .equals(scopeObject.getTopologyObject())) { + return table(relation.getTableName()); + } + } + } else { + Optional relation = relationTypes.stream().filter(relationType -> relationType.getName().equals( + scopeObject.getTopologyObject())).findFirst(); + if (relation.isPresent()) { + return table(relation.get().getTableName()); + } + } + throw TiesException.invalidAssociationType(scopeObject.getInnerContainer().get(0)); + } + } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeObject.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeObject.java index f2a51f7..52e0396 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeObject.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeObject.java @@ -20,35 +20,29 @@ */ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; +import lombok.Builder; +import org.oran.smo.teiv.exposure.tiespath.resolver.ResolverDataType; import org.oran.smo.teiv.schema.DataType; import lombok.Data; -import java.util.ArrayList; import java.util.List; @Data +@Builder(builderMethodName = "hiddenBuilder") public class ScopeObject { private String topologyObject; + @Builder.Default private TopologyObjectType topologyObjectType = TopologyObjectType.UNDEFINED; private ContainerType container; - private List innerContainer = new ArrayList<>(); // in first round it is not supported + @Builder.Default + private List innerContainer = List.of(); // in first round it is not supported private String leaf; private QueryFunction queryFunction; private String parameter; private DataType dataType; + private ResolverDataType resolverDataType; - public ScopeObject(String topologyObject, ContainerType container, QueryFunction queryFunction, String parameter, - DataType dataType) { - this(topologyObject, container, null, queryFunction, parameter, dataType); - } - - public ScopeObject(String topologyObject, ContainerType container, String leaf, QueryFunction queryFunction, - String parameter, DataType dataType) { - this.topologyObject = topologyObject; - this.container = container; - this.leaf = leaf; - this.queryFunction = queryFunction; - this.parameter = parameter; - this.dataType = dataType; + public static ScopeObjectBuilder builder(final String topologyObject) { + return hiddenBuilder().topologyObject(topologyObject); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/TargetObject.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/TargetObject.java index 815babb..d497592 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/TargetObject.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/TargetObject.java @@ -24,10 +24,12 @@ import java.util.List; import lombok.Builder; import lombok.Data; +import lombok.NonNull; @Data @Builder(builderMethodName = "hiddenBuilder") public class TargetObject { + @NonNull private String topologyObject; @Builder.Default private TopologyObjectType topologyObjectType = TopologyObjectType.UNDEFINED; @@ -36,7 +38,11 @@ public class TargetObject { @Builder.Default private List params = List.of(); - public static TargetObjectBuilder builder(String topologyObject) { + private boolean isAllParamQueried; + + private boolean isGenerated; + + public static TargetObjectBuilder builder(final String topologyObject) { return hiddenBuilder().topologyObject(topologyObject); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapper.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapper.java new file mode 100644 index 0000000..17196ee --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapper.java @@ -0,0 +1,86 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.refiner; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +import jakarta.xml.bind.DatatypeConverter; +import org.oran.smo.teiv.exception.TiesException; + +@Slf4j +@UtilityClass +public class AliasMapper { + private static final String SHA_1 = "SHA-1"; + private static final int POSTGRES_MAX_IDENTIFIER_LENGTH = 63; + private static final Map originalToHashed = new ConcurrentHashMap<>(); + private static final Map hashedToOriginal = new ConcurrentHashMap<>(); + + /** + * Hashes the original alias if it is more than 63 characters and stores in the originalToHashed & hashedToOriginal + * maps. + * + * @param originalAlias + * - original alias + * @return hashed alias if more than 63 characters otherwise original alias + */ + public static String hashAlias(final String originalAlias) { + if (originalAlias.length() <= POSTGRES_MAX_IDENTIFIER_LENGTH) { + return originalAlias; + } + if (originalToHashed.containsKey(originalAlias)) { + return originalToHashed.get(originalAlias); + } + final String hashedAlias = generateSha1Hash(originalAlias); + originalToHashed.put(originalAlias, hashedAlias); + hashedToOriginal.put(hashedAlias, originalAlias); + return hashedAlias; + } + + /** + * Gets the original alias from the hashed alias. + * + * @param hashedAlias + * - hashed alias + * @return original alias + */ + public static String getOriginalAlias(String hashedAlias) { + return hashedToOriginal.getOrDefault(hashedAlias, hashedAlias); + } + + private static String generateSha1Hash(final String stringToHash) { + try { + MessageDigest digest = MessageDigest.getInstance(SHA_1); + byte[] hashBytes = digest.digest(stringToHash.getBytes(StandardCharsets.UTF_8)); + return DatatypeConverter.printHexBinary(hashBytes).toUpperCase(Locale.US); + } catch (NoSuchAlgorithmException exception) { + log.warn("Not a valid algorithm", exception); + throw TiesException.serverException("Invalid Hashing algorithm", "Error while hashing alias", exception); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinement.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinement.java index 755aca2..37cd05f 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinement.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinement.java @@ -20,49 +20,397 @@ */ package org.oran.smo.teiv.exposure.tiespath.refiner; +import lombok.RequiredArgsConstructor; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataValidator; +import org.oran.smo.teiv.exposure.consumerdata.model.Classifiers; +import org.oran.smo.teiv.exposure.consumerdata.model.Decorators; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndOrLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.EmptyLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.QueryFunction; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.InnerFilterCriteria; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeObject; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TopologyObjectType; +import org.oran.smo.teiv.exposure.tiespath.resolver.ResolverDataType; +import org.oran.smo.teiv.schema.DataType; import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.Persistable; import org.oran.smo.teiv.schema.RelationType; import org.oran.smo.teiv.schema.SchemaRegistry; import org.oran.smo.teiv.utils.query.exception.TiesPathException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TargetObject; import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; +import java.util.function.Supplier; import java.util.stream.Collectors; -import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.NotImplementedException; +import org.springframework.stereotype.Component; -import static org.oran.smo.teiv.utils.TiesConstants.ITEMS; +import static org.oran.smo.teiv.schema.DataType.BIGINT; +import static org.oran.smo.teiv.schema.DataType.DECIMAL; +import static org.oran.smo.teiv.schema.DataType.INTEGER; +import static org.oran.smo.teiv.schema.DataType.PRIMITIVE; +import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.ITEM; -@UtilityClass +@Component @Slf4j +@RequiredArgsConstructor public class BasePathRefinement { + private final ConsumerDataValidator consumerDataValidator; - @SuppressWarnings("squid:S4144") - public static void resolveWildCardObjectsInScopeAndTarget(FilterCriteria filterCriteria) { - // change every * to the possible topology object - // get the intersection of all possibilities to resolve the * (base set come from domain) - // there are topology objects in TO or SO-s we only can work with them - // there is no matching entity for the * throw error! - // on multiple match connect with OR - log.trace(filterCriteria.toString()); - throw new NotImplementedException(filterCriteria.toString()); + /** + * Main method to orchestrate the refinement process + * + * @param filterCriteria + * the filter criteria + */ + public void refine(FilterCriteria filterCriteria) { + processTopologyObjectsWithContainerTypeNull(filterCriteria); + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> resolveWildCardObjectsInScopeAndTarget( + innerFilterCriteria, filterCriteria.getDomain(), filterCriteria.getResolvingTopologyObjectType())); + resolveUndefinedTopologyObjectTypes(filterCriteria); + validateContainers(filterCriteria); + validateScopeParametersDataType(filterCriteria); + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> checkIfTargetMatchesWithScope( + innerFilterCriteria, filterCriteria.getDomain())); + splitFilterCriteria(filterCriteria); + validateQuery(filterCriteria); + applyRelationshipCriteria(filterCriteria); + } + + /** + * Process topology objects with container type null. + * If scopeResolver can not differentiate ASSOCIATION from ENTITY and RELATION, + * this function does additional settings of ScopeObjects. + * + * @param filterCriteria + * the filter criteria + */ + public void processTopologyObjectsWithContainerTypeNull(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> runOnTree(innerFilterCriteria.getScope(), + filterCriteria.getDomain(), this::setContainerTypesAndTopologyObjects)); + } + + private void setContainerTypesAndTopologyObjects(ScopeLogicalBlock slb, String domain) { + if (slb.getScopeObject().getContainer() == null) { + if (slb.getScopeObject().getInnerContainer().isEmpty()) { + throw TiesPathException.grammarError("invalid scopeFilter"); + } + boolean isResolved = false; + if (SchemaRegistry.getEntityNames().stream().anyMatch(entityName -> SchemaRegistry + .getAssociationNamesByEntityName(entityName).contains(slb.getScopeObject().getInnerContainer().get( + 0))) || !SchemaRegistry.getAllRelationNamesByAssociationName(slb.getScopeObject() + .getInnerContainer().get(0)).isEmpty()) { + setContainerTypeForScopeLogicalBlocksScopeObject(slb, ContainerType.ASSOCIATION); + isResolved = true; + } + if (SchemaRegistry.getRelationNames().contains(slb.getScopeObject().getInnerContainer().get(0))) { + checkIfAlreadyResolved(slb.getScopeObject().getInnerContainer().get(0), isResolved); + setContainerTypeForScopeLogicalBlocksScopeObject(slb, ContainerType.RELATION); + isResolved = true; + } + isResolved = entityTopologyObjectSettings(slb, isResolved); + if (!isResolved) { + throw TiesPathException.invalidInnerContainer(slb.getScopeObject().getInnerContainer().get(0)); + } + } else if (slb.getScopeObject().getContainer().equals(ContainerType.ATTRIBUTES) && !slb.getScopeObject() + .getInnerContainer().isEmpty() && slb.getScopeObject().getTopologyObject() == null) { + slb.getScopeObject().setTopologyObject("*"); + } + } + + private void setContainerTypeForScopeLogicalBlocksScopeObject(ScopeLogicalBlock slb, ContainerType containerType) { + slb.getScopeObject().setContainer(containerType); + if (slb.getScopeObject().getTopologyObject() == null) { + slb.getScopeObject().setTopologyObject("*"); + } + } + + private boolean entityTopologyObjectSettings(ScopeLogicalBlock slb, boolean isResolved) { + if (SchemaRegistry.getEntityNames().contains(slb.getScopeObject().getInnerContainer().get(0))) { + checkIfAlreadyResolved(slb.getScopeObject().getInnerContainer().get(0), isResolved); + if (slb.getScopeObject().getLeaf().equals(ID_COLUMN_NAME)) { + slb.getScopeObject().setContainer(ContainerType.ID); + slb.getScopeObject().setLeaf(null); + } else { + throw TiesPathException.grammarError("invalid scopeFilter, missing containerType"); + } + if (slb.getScopeObject().getTopologyObject() == null) { + slb.getScopeObject().setTopologyObject(slb.getScopeObject().getInnerContainer().get(0)); + slb.getScopeObject().getInnerContainer().remove(0); + } else { + throw TiesPathException.grammarError("invalid ScopeFilter"); + } + isResolved = true; + } + return isResolved; + } + + private void checkIfAlreadyResolved(String innerContainer, boolean isResolved) { + if (isResolved) { + throw TiesPathException.ambiguousTopologyObject(innerContainer); + } + } + + /** + * Unifies duplicated targets by container type. + * e.g. TargetFilter: /NRCellDU/attributes(fdn); /NRCellDU/attributes(nCI) --> /NRCellDU/attributes(fdn,nCI) + * TargetFilter: /attributes; /attributes(fdn) --> /attributes(fdn) and isAllParamQueried = true (every attribute of + * TopologyObjects if they have attribute fdn) + */ + private void unifyDuplicatedTargetsByContainerType(List targetObjects, ContainerType containerType) { + Set uniqueTopologyObjects = new HashSet<>(); + targetObjects.stream().filter(targetObject -> targetObject.getContainer().equals(containerType)).forEach( + targetObject -> uniqueTopologyObjects.add(targetObject.getTopologyObject())); + + for (String topologyObject : uniqueTopologyObjects) { + final Set unifiedParams = new HashSet<>(); + boolean isAllParamQueried = containerType == ContainerType.ATTRIBUTES && targetObjects.stream().anyMatch( + targetObject -> targetObject.getTopologyObject().equals(topologyObject) && (targetObject.getParams() + .isEmpty() || targetObject.isAllParamQueried()) && targetObject.getContainer().equals( + containerType)); + + targetObjects.stream().filter(targetObject -> targetObject.getTopologyObject().equals( + topologyObject) && targetObject.getContainer().equals(containerType)).forEach( + targetObject -> unifiedParams.addAll(targetObject.getParams())); + + targetObjects.removeIf(targetObject -> targetObject.getTopologyObject().equals(topologyObject) && targetObject + .getContainer().equals(containerType)); + TargetObject unifiedTarget = TargetObject.builder(topologyObject).container(containerType).params(unifiedParams + .stream().toList()).isAllParamQueried(isAllParamQueried).build(); + + targetObjects.add(unifiedTarget); + } + } + + /** + * Resolve wildcard topologyObjects in scopeObjects and in targetObjects. + * + * @param filterCriteria + * the filter criteria + */ + public void resolveWildCardObjectsInScopeAndTarget(InnerFilterCriteria filterCriteria, String domain, + FilterCriteria.ResolvingTopologyObjectType resolvingTopologyObjectType) { + if (filterCriteria.getTargets() == null || filterCriteria.getTargets().isEmpty()) { + filterCriteria.setTargets(List.of(TargetObject.builder("*").container(ContainerType.ID).build())); + } + + // merge targets + Arrays.stream(ContainerType.values()).toList().forEach(containerType -> unifyDuplicatedTargetsByContainerType( + filterCriteria.getTargets(), containerType)); + + // calculate situation + final List wildCardsInScope = new ArrayList<>(); + final List nonWildCardsInScope = new ArrayList<>(); + runOnTree(filterCriteria.getScope(), domain, (lb, s) -> { + if (lb.getScopeObject().getTopologyObject().equals("*")) { + wildCardsInScope.add(lb); + } else { + nonWildCardsInScope.add(lb); + } + }); + + boolean wildCardInTarget = filterCriteria.getTargets().stream().anyMatch(t -> t.getTopologyObject().equals("*")); + boolean wildCardInScope = (filterCriteria.getScope() instanceof EmptyLogicalBlock) || !wildCardsInScope.isEmpty(); + boolean isAllParamRequired = filterCriteria.getTargets().stream().anyMatch(t -> t.getTopologyObject().equals( + "*") && t.getContainer().equals(ContainerType.ATTRIBUTES) && t.isAllParamQueried()); + + // skip when nothing to do + if ((!wildCardInScope || filterCriteria.getScope() instanceof EmptyLogicalBlock) && !wildCardInTarget) { + return; + } + + List possibleTypes = listPossibleTypes(filterCriteria, domain, nonWildCardsInScope, wildCardInTarget, + wildCardInScope, resolvingTopologyObjectType); + + filterPossibleTypesInTarget(filterCriteria, possibleTypes); + filterPossibleTypesInScope(wildCardsInScope, possibleTypes); + + // check + if (possibleTypes.isEmpty()) { + throw TiesPathException.notMatchingScopeAndTargetFilter(); + } + + resolveTargets(filterCriteria, isAllParamRequired, possibleTypes); + + // merge targets + Arrays.stream(ContainerType.values()).toList().forEach(containerType -> unifyDuplicatedTargetsByContainerType( + filterCriteria.getTargets(), containerType)); + + //resolve scope + List resolvedTrees = new ArrayList<>(); + if (!(filterCriteria.getScope() instanceof EmptyLogicalBlock) && wildCardInScope) { + possibleTypes.forEach(t -> resolvedTrees.add(copyTree(filterCriteria.getScope(), t.getName()))); + } else { + return; + } + + rebuildBinaryTree(filterCriteria, resolvedTrees); + } + + private List listPossibleTypes(InnerFilterCriteria filterCriteria, String domain, + List nonWildCardsInScope, boolean wildCardInTarget, boolean wildCardInScope, + FilterCriteria.ResolvingTopologyObjectType resolvingTopologyObjectType) { + List result = new ArrayList<>(); + if (!wildCardInTarget) { + if (resolvingTopologyObjectType.isResolveEntities()) { + result.addAll(filterCriteria.getTargets().stream().map(TargetObject::getTopologyObject).map( + SchemaRegistry::getEntityTypeByName).filter(Objects::nonNull).toList()); + } + if (resolvingTopologyObjectType.isResolveRelationships()) { + result.addAll(filterCriteria.getTargets().stream().map(TargetObject::getTopologyObject).map( + SchemaRegistry::getRelationTypeByName).filter(Objects::nonNull).toList()); + } + } else if (!wildCardInScope) { + if (resolvingTopologyObjectType.isResolveEntities()) { + result.addAll(nonWildCardsInScope.stream().map(ScopeLogicalBlock::getScopeObject).map( + ScopeObject::getTopologyObject).map(SchemaRegistry::getEntityTypeByName).filter(Objects::nonNull) + .toList()); + } + if (resolvingTopologyObjectType.isResolveRelationships()) { + result.addAll(nonWildCardsInScope.stream().map(ScopeLogicalBlock::getScopeObject).map( + ScopeObject::getTopologyObject).map(SchemaRegistry::getRelationTypeByName).filter(Objects::nonNull) + .toList()); + } + } else { + if (resolvingTopologyObjectType.isResolveEntities()) { + result.addAll(SchemaRegistry.getEntityTypesByDomain(domain)); + } + if (resolvingTopologyObjectType.isResolveRelationships()) { + result.addAll(SchemaRegistry.getRelationTypesByDomain(domain)); + } + } + return result; + } + + private void filterPossibleTypesInTarget(InnerFilterCriteria filterCriteria, List possibleTypes) { + for (TargetObject targetObject : filterCriteria.getTargets().stream().filter(t -> t.getTopologyObject().equals("*")) + .toList()) { + if (targetObject.getContainer().equals(ContainerType.ATTRIBUTES)) { + for (String parameter : targetObject.getParams()) { + possibleTypes.removeIf(t -> !t.getAttributeNames().contains(parameter)); + } + } + } + } + + private void filterPossibleTypesInScope(List wildCardsInScope, List possibleTypes) { + for (ScopeObject scopeObject : wildCardsInScope.stream().map(ScopeLogicalBlock::getScopeObject).toList()) { + if (scopeObject.getContainer().equals(ContainerType.ATTRIBUTES)) { + if (!scopeObject.getInnerContainer().isEmpty()) { + possibleTypes.removeIf(t -> !t.getAttributeNames().contains(scopeObject.getInnerContainer().get(0))); + } else { + possibleTypes.removeIf(t -> !t.getAttributeNames().contains(scopeObject.getLeaf())); + } + } + if (scopeObject.getContainer().equals(ContainerType.ASSOCIATION)) { + filterPossibleTypesInScopeByAssociations(possibleTypes, scopeObject); + } + } + } + + private void filterPossibleTypesInScopeByAssociations(List possibleTypes, ScopeObject scopeObject) { + String innerContainer = scopeObject.getInnerContainer().get(0); + List entityTypesCopy = new ArrayList<>(possibleTypes); + for (Persistable t : entityTypesCopy) { + if ((t instanceof RelationType && !(SchemaRegistry.getRelationTypeByName(t.getName()).getASideAssociation() + .getName().equals(innerContainer) || SchemaRegistry.getRelationTypeByName(t.getName()) + .getBSideAssociation().getName().equals( + innerContainer))) || (t instanceof EntityType && !SchemaRegistry + .getAssociationNamesByEntityName(t.getName()).contains(innerContainer))) { + possibleTypes.remove(t); + } + } + } + + private void resolveTargets(InnerFilterCriteria filterCriteria, boolean isAllParamRequired, + List possibleTypes) { + List resolvedTargets = new ArrayList<>(); + for (TargetObject targetObject : filterCriteria.getTargets()) { + if (targetObject.getTopologyObject().equals("*")) { + possibleTypes.forEach(t -> resolvedTargets.add(TargetObject.builder(t.getName()).container(targetObject + .getContainer()).params(targetObject.getParams()).isAllParamQueried(isAllParamRequired).build())); + } else { + resolvedTargets.add(targetObject); + } + } + filterCriteria.setTargets(resolvedTargets); + } + + private LogicalBlock copyTree(LogicalBlock logicalBlock, String topologyObject) { + if (logicalBlock instanceof AndLogicalBlock andLogicalBlock) { + AndLogicalBlock lb = new AndLogicalBlock(); + lb.setValid(logicalBlock.isValid()); + lb.getChildren().addAll(andLogicalBlock.getChildren().stream().map(child -> copyTree(child, topologyObject)) + .toList()); + return lb; + } + if (logicalBlock instanceof OrLogicalBlock orLogicalBlock) { + OrLogicalBlock lb = new OrLogicalBlock(); + lb.setValid(logicalBlock.isValid()); + lb.getChildren().addAll(orLogicalBlock.getChildren().stream().map(child -> copyTree(child, topologyObject)) + .toList()); + return lb; + } + if (logicalBlock instanceof ScopeLogicalBlock scopeLogicalBlock) { + ScopeObject scopeObject = ScopeObject.builder((topologyObject == null || !scopeLogicalBlock.getScopeObject() + .getTopologyObject().equals("*")) ? + scopeLogicalBlock.getScopeObject().getTopologyObject() : + topologyObject).topologyObjectType((topologyObject == null || !scopeLogicalBlock + .getScopeObject().getTopologyObject().equals("*")) ? + scopeLogicalBlock.getScopeObject().getTopologyObjectType() : + TopologyObjectType.UNDEFINED).container(scopeLogicalBlock.getScopeObject() + .getContainer()).innerContainer(scopeLogicalBlock.getScopeObject() + .getInnerContainer()).leaf(scopeLogicalBlock.getScopeObject() + .getLeaf()).queryFunction(scopeLogicalBlock + .getScopeObject().getQueryFunction()).parameter( + scopeLogicalBlock.getScopeObject() + .getParameter()).dataType( + scopeLogicalBlock + .getScopeObject() + .getDataType()) + .resolverDataType(scopeLogicalBlock.getScopeObject().getResolverDataType()).build(); + + if (scopeObject.getLeaf() != null && scopeObject.getLeaf().equals(ID_COLUMN_NAME) && scopeObject.getContainer() + .equals(ContainerType.ID)) { + scopeObject.setLeaf(null); + } + + ScopeLogicalBlock lb = new ScopeLogicalBlock(scopeObject); + lb.setValid(logicalBlock.isValid()); + return lb; + } + return EmptyLogicalBlock.getInstance(); + } + + private void rebuildBinaryTree(InnerFilterCriteria filterCriteria, List resolvedTrees) { + LogicalBlock subTree = resolvedTrees.get(0); + for (int i = 1; i < resolvedTrees.size(); i++) { + OrLogicalBlock lb = new OrLogicalBlock(); + lb.getChildren().add(copyTree(subTree, null)); + lb.getChildren().add(resolvedTrees.get(i)); + subTree = lb; + } + + filterCriteria.setScope(subTree); } /** @@ -72,23 +420,23 @@ public class BasePathRefinement { * @param filterCriteria * the filter criteria */ - public static void resolveUndefinedTopologyObjectTypes(FilterCriteria filterCriteria) { + public void resolveUndefinedTopologyObjectTypes(FilterCriteria filterCriteria) { resolveUndefinedObjectTypesInTarget(filterCriteria); resolveUndefinedObjectTypesInScope(filterCriteria); } - private static void resolveUndefinedObjectTypesInScope(FilterCriteria filterCriteria) { - runOnTree(filterCriteria.getScope(), filterCriteria.getDomain(), - BasePathRefinement::defineTopologyObjectTypeInScope); + private void resolveUndefinedObjectTypesInScope(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> runOnTree(innerFilterCriteria.getScope(), + filterCriteria.getDomain(), this::defineTopologyObjectTypeInScope)); } - private static void resolveUndefinedObjectTypesInTarget(FilterCriteria filterCriteria) { - filterCriteria.getTargets().stream().filter(targetObject -> targetObject.getTopologyObjectType().equals( - TopologyObjectType.UNDEFINED)).forEach(targetObject -> defineTopologyObjectTypeForTarget(targetObject, - filterCriteria.getDomain())); + private void resolveUndefinedObjectTypesInTarget(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> innerFilterCriteria.getTargets().stream() + .filter(targetObject -> targetObject.getTopologyObjectType().equals(TopologyObjectType.UNDEFINED)).forEach( + targetObject -> defineTopologyObjectTypeForTarget(targetObject, filterCriteria.getDomain()))); } - private static void defineTopologyObjectTypeInScope(ScopeLogicalBlock scopeLogicalBlock, String domain) { + private void defineTopologyObjectTypeInScope(ScopeLogicalBlock scopeLogicalBlock, String domain) { if (scopeLogicalBlock.getScopeObject().getTopologyObjectType().equals(TopologyObjectType.UNDEFINED)) { boolean isResolved = false; if (SchemaRegistry.getEntityNamesByDomain(domain).contains(scopeLogicalBlock.getScopeObject() @@ -111,7 +459,7 @@ public class BasePathRefinement { } } - private static void defineTopologyObjectTypeForTarget(TargetObject targetObject, String domain) { + private void defineTopologyObjectTypeForTarget(TargetObject targetObject, String domain) { boolean isResolved = false; if (SchemaRegistry.getEntityNamesByDomain(domain).contains(targetObject.getTopologyObject())) { targetObject.setTopologyObjectType(TopologyObjectType.ENTITY); @@ -138,32 +486,38 @@ public class BasePathRefinement { * @param filterCriteria * the filter criteria */ - public static void validateContainers(FilterCriteria filterCriteria) { - filterCriteria.getTargets().stream().forEach(targetObject -> validateContainerWithMatchingParameters(targetObject - .getContainer(), targetObject.getParams(), targetObject.getTopologyObject(), targetObject - .getTopologyObjectType(), Collections.emptyList())); - runOnTree(filterCriteria.getScope(), filterCriteria.getDomain(), BasePathRefinement::validateScope); + public void validateContainers(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> innerFilterCriteria.getTargets().forEach( + targetObject -> validateContainerWithMatchingParameters(targetObject.getContainer(), targetObject + .getParams(), targetObject.getTopologyObject(), targetObject.getTopologyObjectType(), Collections + .emptyList()))); + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> runOnTree(innerFilterCriteria.getScope(), + filterCriteria.getDomain(), this::validateScope)); } - private static void validateScope(LogicalBlock logicalBlock, String domain) { + private void validateScope(LogicalBlock logicalBlock, String domain) { ScopeObject scopeObject = ((ScopeLogicalBlock) logicalBlock).getScopeObject(); - validateContainerWithMatchingParameters(scopeObject.getContainer(), new ArrayList<>(Arrays.asList(scopeObject - .getLeaf())), scopeObject.getTopologyObject(), scopeObject.getTopologyObjectType(), scopeObject + validateContainerWithMatchingParameters(scopeObject.getContainer(), new ArrayList<>(Collections.singletonList( + scopeObject.getLeaf())), scopeObject.getTopologyObject(), scopeObject.getTopologyObjectType(), scopeObject .getInnerContainer()); } - private static void validateContainerWithMatchingParameters(ContainerType containerType, List params, + private void validateContainerWithMatchingParameters(ContainerType containerType, List params, String topologyObject, TopologyObjectType topologyObjectType, List innerContainer) { switch (containerType) { case ID: - if (!params.isEmpty()) { + if (!params.isEmpty() && !(params.size() == 1 && params.contains(null))) { throw TiesPathException.grammarError("Adding parameters for id container is not supported"); } break; case ATTRIBUTES: - checkAttributesOfTopologyObject(params, topologyObject, topologyObjectType); + if (innerContainer.isEmpty()) { + checkAttributesOfTopologyObject(params, topologyObject, topologyObjectType); + } else { + checkAttributesOfTopologyObject(List.of(innerContainer.get(0)), topologyObject, topologyObjectType); + } break; - case SOURCE_IDS: + case SOURCE_IDS, CLASSIFIERS: checkSourceIdTopologyObject(params, topologyObject); break; case ASSOCIATION: @@ -174,101 +528,197 @@ public class BasePathRefinement { } } - private static void checkAssociationTopologyObject(List params, String topologyObject, + private void checkAssociationTopologyObject(List params, String topologyObject, TopologyObjectType topologyObjectType, List innerContainer) { if (innerContainer.isEmpty()) { throw TiesPathException.grammarError("Missing association name"); } RelationType relation; switch (topologyObjectType) { - case ENTITY: - relation = SchemaRegistry.getRelationTypes().stream().filter(relationType -> (relationType.getASide() - .getName().equals(topologyObject) && relationType.getBSideAssociation().getName().equals( - innerContainer.get(0))) || (relationType.getBSide().getName().equals( - topologyObject) && relationType.getASideAssociation().getName().equals( - innerContainer.get(0)))).findFirst().orElseThrow(() -> TiesPathException - .invalidAssociation(topologyObject, innerContainer.get(0))); - break; - case RELATION: + case ENTITY -> relation = SchemaRegistry.getRelationTypes().stream().filter(relationType -> (relationType + .getASide().getName().equals(topologyObject) && relationType.getASideAssociation().getName().equals( + innerContainer.get(0))) || (relationType.getBSide().getName().equals( + topologyObject) && relationType.getBSideAssociation().getName().equals(innerContainer + .get(0)))).findFirst().orElseThrow(() -> TiesPathException.invalidAssociation( + topologyObject, innerContainer.get(0))); + case RELATION -> { relation = SchemaRegistry.getRelationTypeByName(topologyObject); if (!relation.getASideAssociation().getName().equals(innerContainer.get(0)) && !relation .getBSideAssociation().getName().equals(innerContainer.get(0))) { throw TiesPathException.invalidAssociation(topologyObject, innerContainer.get(0)); } - - break; - default: - throw TiesPathException.containerValidationWithUndefinedTopologyObjectType(topologyObject); + } + default -> throw TiesPathException.containerValidationWithUndefinedTopologyObjectType(topologyObject); } if (!params.isEmpty() && params.get(0) != null) { checkParamsForAssociation(relation, innerContainer.get(0), params); } } - private static void checkParamsForAssociation(RelationType relationType, String associationName, List params) { + private void checkParamsForAssociation(RelationType relationType, String associationName, List params) { if ((relationType.getASideAssociation().getName().equals(associationName) && !params.stream().allMatch( - param -> relationType.getASide().getFields().containsKey(param))) || (relationType.getBSideAssociation() - .getName().equals(associationName) && !params.stream().allMatch(param -> relationType.getBSide() + param -> relationType.getBSide().getFields().containsKey(param))) || (relationType.getBSideAssociation() + .getName().equals(associationName) && !params.stream().allMatch(param -> relationType.getASide() .getFields().containsKey(param)))) { throw TiesPathException.invalidParamsForAssociation(associationName); } } - private static void checkSourceIdTopologyObject(List params, String topologyObject) { - if (params.stream().anyMatch(param -> !param.equals(ITEMS))) { + private void checkSourceIdTopologyObject(List params, String topologyObject) { + if (params.stream().anyMatch(param -> !param.equals(ITEM))) { throw TiesPathException.sourceIdNameError(topologyObject); } } - private static void checkAttributesOfTopologyObject(List params, String topologyObject, + private void checkAttributesOfTopologyObject(List params, String topologyObject, TopologyObjectType topologyObjectType) { switch (topologyObjectType) { - case ENTITY: + case ENTITY -> { EntityType entityType = SchemaRegistry.getEntityTypeByName(topologyObject); List notMatchingParams = params.stream().filter(a -> !entityType.getAttributeNames().contains(a)) .toList(); if (!notMatchingParams.isEmpty()) { throw TiesPathException.columnNamesError(topologyObject, notMatchingParams); } - break; - case RELATION: + } + case RELATION -> { RelationType relationType = SchemaRegistry.getRelationTypeByName(topologyObject); List notMatchingParams2 = params.stream().filter(a -> !relationType.getAttributes().containsKey(a)) .toList(); if (!notMatchingParams2.isEmpty()) { throw TiesPathException.columnNamesError(topologyObject, notMatchingParams2); } + } + } + } + + /** + * Validate scope parameters' data type. + * If resolverDataType does not match the accepted dataType of the attribute/id/source_id etc., error is thrown. + * resolverDataType: INTEGER - accepted dataTypes: INTEGER, BIGINT, DECIMAL + * resolverDataType: STRING - accepted dataTypes: all other + * + * @param filterCriteria + * the filter criteria + */ + public void validateScopeParametersDataType(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> runOnTree(innerFilterCriteria.getScope(), + filterCriteria.getDomain(), this::validateParameterOfScopeObject)); + } + + private void validateParameterOfScopeObject(ScopeLogicalBlock scopeLogicalBlock, String domain) { + ScopeObject so = scopeLogicalBlock.getScopeObject(); + switch (so.getContainer()) { + case ATTRIBUTES: + validateAttributesParameter(so); + break; + case ID: + validateIdParameter(so); + break; + case ASSOCIATION, RELATION: + validateAssociationAndRelationParameter(so); + break; + case SOURCE_IDS: + validateSourceIdsParameter(so); + break; + case CLASSIFIERS: + validateClassifiersParameter(so); + break; + case DECORATORS: + validateDecoratorsParameter(so); break; default: break; } } - @SuppressWarnings("squid:S4144") - public static void validateScopeParametersDataType(FilterCriteria filterCriteria) { - // can parameter parse as the given type, check given data type and stored dataType - // throw error - log.trace(filterCriteria.toString()); - throw new NotImplementedException(filterCriteria.toString()); + private void validateAttributesParameter(final ScopeObject so) { + if (so.getInnerContainer().isEmpty()) { + so.setDataType(SchemaRegistry.getEntityTypeByName(so.getTopologyObject()).getFields().get(so.getLeaf())); + compareResolverDataTypeToDataType(so); + } else { + setDataTypeForComplexAttribute(so); + } } - //// End of syntax check + private void validateIdParameter(final ScopeObject so) { + if (so.getResolverDataType().equals(ResolverDataType.INTEGER)) { + throw TiesPathException.grammarError("Data is given in invalid datatype in scopeFilter"); + } + so.setDataType(DataType.PRIMITIVE); + } + + private void validateAssociationAndRelationParameter(final ScopeObject so) { + if (so.getLeaf() != null && !ID_COLUMN_NAME.equals(so.getLeaf())) { + throw TiesPathException.grammarError("Only id condition can be queried in case of association container"); + } else if (so.getResolverDataType().equals(ResolverDataType.INTEGER)) { + throw TiesPathException.grammarError("Invalid data type provided for scopeFilter"); + } else if (so.getResolverDataType().equals(ResolverDataType.STRING)) { + so.setDataType(DataType.PRIMITIVE); + } + } + + private void validateSourceIdsParameter(final ScopeObject so) { + if (so.getResolverDataType().equals(ResolverDataType.INTEGER)) { + throw TiesPathException.grammarError("Invalid data type provided for scopeFilter"); + } + so.setDataType(DataType.PRIMITIVE); + } + + private void validateClassifiersParameter(final ScopeObject so) { + if (so.getResolverDataType().equals(ResolverDataType.INTEGER)) { + throw TiesPathException.grammarError("Invalid data type provided for scopeFilter"); + } + so.setDataType(DataType.PRIMITIVE); + Classifiers classifier = Classifiers.builder().data(List.of(so.getParameter())).build(); + consumerDataValidator.validate(classifier); + } + + private void validateDecoratorsParameter(final ScopeObject so) { + Object value = null; + if (so.getResolverDataType().equals(ResolverDataType.INTEGER)) { + so.setDataType(BIGINT); + value = Integer.valueOf(so.getParameter()); + } else { + so.setDataType(DataType.PRIMITIVE); + value = so.getParameter(); + } + Decorators decorator = Decorators.builder().data(Map.of(so.getLeaf(), value)).build(); + consumerDataValidator.validate(decorator); + } + + private void setDataTypeForComplexAttribute(final ScopeObject scopeObject) { + switch (scopeObject.getResolverDataType()) { + case INTEGER -> scopeObject.setDataType(INTEGER); + case STRING -> scopeObject.setDataType(PRIMITIVE); + default -> throw new IllegalStateException("Invalid data type for complex attribute"); + } + } + + private void compareResolverDataTypeToDataType(final ScopeObject scopeObject) { + List numericDataTypes = List.of(INTEGER, BIGINT, DECIMAL); + if ((scopeObject.getResolverDataType().equals(ResolverDataType.INTEGER) && !numericDataTypes.contains(scopeObject + .getDataType())) || (scopeObject.getResolverDataType().equals(ResolverDataType.STRING) && numericDataTypes + .contains(scopeObject.getDataType()))) { + throw TiesPathException.grammarError("Data is given in invalid datatype in scopeFilter"); + } + } /** * Check if target's topologyObjects match with scope's topologyObjects. * * @param filterCriteria + * - filter criteria * */ - @SuppressWarnings("squid:S4144") - public static void checkIfTargetMatchesWithScope(FilterCriteria filterCriteria) { + public void checkIfTargetMatchesWithScope(InnerFilterCriteria filterCriteria, String domain) { if (filterCriteria.getScope() instanceof EmptyLogicalBlock || filterCriteria.getTargets().isEmpty()) { return; } Set scopeTopologyObjects = new HashSet<>(); - runOnTree(filterCriteria.getScope(), filterCriteria.getDomain(), (ScopeLogicalBlock lb, - String domain) -> scopeTopologyObjects.add(lb.getScopeObject().getTopologyObject())); + runOnTree(filterCriteria.getScope(), domain, (ScopeLogicalBlock lb, String dom) -> scopeTopologyObjects.add(lb + .getScopeObject().getTopologyObject())); Set targetTopologyObjects = filterCriteria.getTargets().stream().map(TargetObject::getTopologyObject) .collect(Collectors.toSet()); @@ -283,16 +733,123 @@ public class BasePathRefinement { } } - @SuppressWarnings("squid:S4144") - public static boolean validateQuery(FilterCriteria filterCriteria) { - // remove invalid LB, when an AND block has an invalid LB set the AND block to invalid - // when an or has an invalid block, replace the OR block with the other child - // throw error when the last LB became invalid - log.trace(filterCriteria.toString()); - throw new NotImplementedException(filterCriteria.toString()); + /** + * Split inner filter criteria to multiple inner filter criteria and use union instance of or logical block + * + * @param filterCriteria + * the filter criteria + */ + public void splitFilterCriteria(FilterCriteria filterCriteria) { + Map innerFilterCriteriaMap = new HashMap<>(); + + for (InnerFilterCriteria base : filterCriteria.getFilterCriteriaList()) { + for (TargetObject targetObject : base.getTargets()) { + if (!innerFilterCriteriaMap.containsKey(targetObject.getTopologyObject())) { + innerFilterCriteriaMap.put(targetObject.getTopologyObject(), InnerFilterCriteria.builder().targets( + new ArrayList<>()).build()); + } + innerFilterCriteriaMap.get(targetObject.getTopologyObject()).getTargets().add(targetObject); + } + } + + for (InnerFilterCriteria base : filterCriteria.getFilterCriteriaList()) { + List types = base.getTargets().stream().map(TargetObject::getTopologyObject).toList(); + for (String type : types) { + innerFilterCriteriaMap.get(type).setScope(generateCutTree(base.getScope(), type)); + } + } + + filterCriteria.setFilterCriteriaList(new ArrayList<>(innerFilterCriteriaMap.values())); + } + + /** + * Validates the binary tree of LogicalBlocks (LB) in FilterCriteria based on isValid boolean of the objects.  + * Remove invalid LB, when an AND block has an invalid LB set the AND block to invalid + * When an OR has an invalid block, replace the OR block with the valid child element. + * Throw an error when the last LB became invalid. + * + * @param filterCriteria + * the filter criteria + */ + public void validateQuery(FilterCriteria filterCriteria) { + filterCriteria.getFilterCriteriaList().forEach(innerFilterCriteria -> { + innerFilterCriteria.setScope(traverseTree(innerFilterCriteria.getScope())); + if (!innerFilterCriteria.getScope().isValid()) { + throw TiesPathException.invalidQueryError(); + } + }); + } + + private LogicalBlock traverseTree(LogicalBlock logicalBlock) { + if (logicalBlock instanceof AndOrLogicalBlock andOrLogicalBlock && andOrLogicalBlock.getChildren().size() == 2) { + andOrLogicalBlock.getChildren().set(0, traverseTree(andOrLogicalBlock.getChildren().get(0))); + andOrLogicalBlock.getChildren().set(1, traverseTree(andOrLogicalBlock.getChildren().get(1))); + if (andOrLogicalBlock.getChildren().stream().anyMatch(child -> !child.isValid())) { + if (logicalBlock instanceof OrLogicalBlock orLogicalBlock) { + Optional validLogicalBlock = orLogicalBlock.getChildren().stream().filter( + LogicalBlock::isValid).findFirst(); + return validLogicalBlock.orElseGet(() -> invalidateLogicalBlock(orLogicalBlock)); + } + if (andOrLogicalBlock.getChildren().stream().anyMatch(child -> !child.isValid())) { + andOrLogicalBlock.getChildren().removeIf(child -> !child.isValid()); + return invalidateLogicalBlock(andOrLogicalBlock); + } + } + } + return logicalBlock; + } + + private LogicalBlock generateCutTree(LogicalBlock logicalBlock, String type) { + if (!logicalBlock.isValid() || logicalBlock instanceof EmptyLogicalBlock) { + return EmptyLogicalBlock.getInstance(); + } + if (logicalBlock instanceof AndLogicalBlock andLogicalBlock) { + return getAndOrLogicalBlock(type, andLogicalBlock, AndLogicalBlock::new); + } + if (logicalBlock instanceof OrLogicalBlock orLogicalBlock) { + return getAndOrLogicalBlock(type, orLogicalBlock, OrLogicalBlock::new); + } + if (logicalBlock instanceof ScopeLogicalBlock scopeLogicalBlock) { + if (!scopeLogicalBlock.getScopeObject().getTopologyObject().equals(type)) { + return EmptyLogicalBlock.getInstance(); + } + ScopeObject response = ScopeObject.builder(type).topologyObjectType(scopeLogicalBlock.getScopeObject() + .getTopologyObjectType()).container(scopeLogicalBlock.getScopeObject().getContainer()).innerContainer( + scopeLogicalBlock.getScopeObject().getInnerContainer()).leaf(scopeLogicalBlock.getScopeObject() + .getLeaf()).queryFunction(scopeLogicalBlock.getScopeObject().getQueryFunction()) + .parameter(scopeLogicalBlock.getScopeObject().getParameter()).dataType(scopeLogicalBlock + .getScopeObject().getDataType()).resolverDataType(scopeLogicalBlock.getScopeObject() + .getResolverDataType()).build(); + + return new ScopeLogicalBlock(response); + } + return EmptyLogicalBlock.getInstance(); } - public static void runOnTree(LogicalBlock logicalBlock, String domain, BiConsumer func) { + private LogicalBlock getAndOrLogicalBlock(String type, AndOrLogicalBlock andLogicalBlock, + Supplier constructor) { + LogicalBlock left = generateCutTree(andLogicalBlock.getChildren().get(0), type); + LogicalBlock right = generateCutTree(andLogicalBlock.getChildren().get(1), type); + + if (!left.isValid() || left instanceof EmptyLogicalBlock) { + return right; + } + if (!right.isValid() || right instanceof EmptyLogicalBlock || left.equals(right)) { + return left; + } + + AndOrLogicalBlock response = constructor.get(); + response.getChildren().add(left); + response.getChildren().add(right); + return response; + } + + private LogicalBlock invalidateLogicalBlock(LogicalBlock logicalBlock) { + logicalBlock.setValid(false); + return logicalBlock; + } + + public void runOnTree(LogicalBlock logicalBlock, String domain, BiConsumer func) { if (!logicalBlock.isValid() || logicalBlock instanceof EmptyLogicalBlock) { return; } @@ -303,4 +860,28 @@ public class BasePathRefinement { func.accept((ScopeLogicalBlock) logicalBlock, domain); } + private void applyRelationshipCriteria(FilterCriteria filterCriteria) { + if (filterCriteria.getResolvingTopologyObjectType().equals( + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP)) { + filterCriteria.getFilterCriteriaList().forEach(criteria -> { + if (criteria.getScope() instanceof EmptyLogicalBlock) { + criteria.setScope(buildScopeLogicalBlockForRelationship(criteria)); + } else if (criteria.getScope()instanceof AndOrLogicalBlock andOrLogicalBlock) { + AndOrLogicalBlock aolb = new AndLogicalBlock(); + aolb.setChildren(List.of(andOrLogicalBlock, buildScopeLogicalBlockForRelationship(criteria))); + criteria.setScope(aolb); + } else if (criteria.getScope()instanceof ScopeLogicalBlock scopeLogicalBlock) { + AndOrLogicalBlock aolb = new AndLogicalBlock(); + aolb.setChildren(List.of(scopeLogicalBlock, buildScopeLogicalBlockForRelationship(criteria))); + criteria.setScope(aolb); + } + }); + } + } + + private ScopeLogicalBlock buildScopeLogicalBlockForRelationship(InnerFilterCriteria criteria) { + return new ScopeLogicalBlock(ScopeObject.builder(criteria.getTargets().get(0).getTopologyObject()) + .topologyObjectType(TopologyObjectType.RELATION).queryFunction(QueryFunction.NOT_NULL).container( + ContainerType.ID).resolverDataType(ResolverDataType.STRING).dataType(PRIMITIVE).build()); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinement.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinement.java index 19e5ef3..8ac102d 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinement.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinement.java @@ -20,14 +20,36 @@ */ package org.oran.smo.teiv.exposure.tiespath.refiner; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; +import org.jooq.Field; +import org.jooq.JSONB; +import org.jooq.OrderField; +import org.jooq.Record; +import org.jooq.SelectConditionStep; +import org.jooq.SelectField; +import org.jooq.SelectOrderByStep; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; -import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; import lombok.experimental.UtilityClass; -import org.apache.commons.lang3.NotImplementedException; -import org.jooq.Condition; import org.jooq.SelectJoinStep; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.InnerFilterCriteria; +import org.oran.smo.teiv.schema.DataType; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.select; +import static org.jooq.impl.DSL.selectCount; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; + +@Slf4j @UtilityClass +@SuppressWarnings({ "rawtypes", "unchecked" }) public class PathToJooqRefinement { /** @@ -35,21 +57,128 @@ public class PathToJooqRefinement { * * @param filterCriteria * the InnerLanguageDTO - * @return the select join step + * @return the query */ - public static SelectJoinStep toJooq(FilterCriteria filterCriteria) { - throw new NotImplementedException(filterCriteria.toString()); + public static SelectOrderByStep toJooq(FilterCriteria filterCriteria, int offset, int limit) { + SelectOrderByStep basicQuery = createBasicQuery(filterCriteria, false); + SelectOrderByStep countQuery = createBasicQuery(filterCriteria, true); + + List>> selectList = new ArrayList<>(filterCriteria.getSelects() + .entrySet()); + + return createQueryWithCount(selectList, basicQuery, countQuery, offset, limit); } - /** - * Converts LogicalBlock to JooQ query part - * - * @param logicalBlock - * the LogicalBlock - * @return the condition - */ - public static Condition logicalBlockToJooq(LogicalBlock logicalBlock) { - // convert LB to JOOQ condition recursive! - throw new NotImplementedException(logicalBlock.toString()); + private static SelectOrderByStep createBasicQuery(FilterCriteria filterCriteria, boolean countMode) { + Map fields = new HashMap<>(); + if (countMode) { + for (SelectField id : filterCriteria.getSelects().keySet()) { + fields.put(id, DataType.PRIMITIVE); + } + } else { + for (Map fieldSet : filterCriteria.getSelects().values()) { + fields.putAll(fieldSet); + } + } + + SelectOrderByStep query = createInnerQuery(filterCriteria.getFilterCriteriaList().get(0), fields, + countMode); + + for (int i = 1; i < filterCriteria.getFilterCriteriaList().size(); i++) { + query = query.unionAll(createInnerQuery(filterCriteria.getFilterCriteriaList().get(i), fields, countMode)); + } + + return query; + } + + private static SelectOrderByStep createInnerQuery(InnerFilterCriteria filterCriteria, + Map otherFields, boolean countMode) { + Set selfFields = new HashSet<>(); + List resolvedFields = new ArrayList<>(); + + for (Map fieldSet : filterCriteria.getSelects().values()) { + selfFields.addAll(fieldSet.keySet()); + } + + for (Map.Entry field : otherFields.entrySet()) { + if (selfFields.contains(field.getKey())) { + resolvedFields.add(field.getKey()); + } else if (field.getValue() == DataType.CONTAINER) { + resolvedFields.add(field("null::jsonb", JSONB.class).as(field.getKey().getName())); + } else if (field.getValue() == DataType.INTEGER) { + resolvedFields.add(field("null::integer").as(field.getKey().getName())); + } else if (field.getValue() == DataType.BIGINT) { + resolvedFields.add(field("null::bigint").as(field.getKey().getName())); + } else if (field.getValue() == DataType.DECIMAL) { + resolvedFields.add(field("null::numeric").as(field.getKey().getName())); + } else { + resolvedFields.add(field("null").as(field.getKey().getName())); + } + } + + SelectJoinStep query = select(resolvedFields).from(filterCriteria.getTableFromTarget(filterCriteria + .getTargets().get(0))); + + List> joinConditions = new ArrayList<>(filterCriteria.getJoinCondition()); + + for (int i = 0; i < joinConditions.size(); i++) { + query = query.join(joinConditions.get(i).getLeft()).on(joinConditions.get(i).getRight()); + } + + SelectConditionStep conditionStep = query.where(filterCriteria.getCondition()); + if (countMode) { + return conditionStep; + } else { + return (SelectOrderByStep) conditionStep.orderBy(filterCriteria.getSelects().keySet().stream().map(i -> field(i) + .asc()).toList().toArray(new OrderField[0])); + } + } + + private static SelectOrderByStep createQueryWithCount( + List>> selectList, SelectOrderByStep basicQuery, + SelectOrderByStep countQuery, int offset, int limit) { + List fields = new ArrayList<>(); + for (Map.Entry> fieldSet : selectList) { + for (Map.Entry field : fieldSet.getValue().entrySet()) { + if (field.getValue() == DataType.CONTAINER) { + fields.add(field(String.format(QUOTED_STRING, field.getKey().getName()), JSONB.class)); + } else { + fields.add(field(String.format(QUOTED_STRING, field.getKey().getName()))); + } + } + } + + List fieldsWithNullCount = new ArrayList<>(fields); + fieldsWithNullCount.add(field("null").as("count")); + + List nullFieldsWithCount = getNulledFields(selectList); + nullFieldsWithCount.add(field(selectCount().from(countQuery)).as("count")); + + return select(nullFieldsWithCount).unionAll(select(fieldsWithNullCount).from(basicQuery).limit(offset, limit)); + } + + private static List getNulledFields(List>> selectList) { + List nulledFields = new ArrayList<>(); + for (int i = 0; i < selectList.size(); i++) { + addNullFields(selectList, nulledFields, i); + } + return nulledFields; + } + + private static void addNullFields(List>> selectList, + List nulledFields, int i) { + for (SelectField field : selectList.get(i).getValue().keySet()) { + if (selectList.get(i).getValue().get(field) == DataType.CONTAINER) { + nulledFields.add(field("null::jsonb", JSONB.class).as(field.getName())); + } else if (selectList.get(i).getValue().get(field) == DataType.INTEGER) { + nulledFields.add(field("null::integer").as(field.getName())); + } else if (selectList.get(i).getValue().get(field) == DataType.BIGINT) { + nulledFields.add(field("null::bigint").as(field.getName())); + } else if (selectList.get(i).getValue().get(field) == DataType.DECIMAL) { + nulledFields.add(field("null::numeric").as(field.getName())); + } else { + nulledFields.add(field("null").as(field.getName())); + } + } } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/PathResolver.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/PathResolver.java index 506656f..62b199c 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/PathResolver.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/PathResolver.java @@ -20,44 +20,48 @@ */ package org.oran.smo.teiv.exposure.tiespath.resolver; -import java.util.List; - -import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; -import jakarta.annotation.Nullable; -import lombok.NonNull; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.oran.smo.teiv.antlr4.tiesPathParser; +import org.oran.smo.teiv.utils.path.StrictErrorStrategy; +import org.oran.smo.teiv.utils.path.TiesPathErrorListener; +import org.oran.smo.teiv.utils.path.TiesPathLexer; +import org.oran.smo.teiv.utils.path.TiesPathParser; public interface PathResolver { - String NULL_ROOT_OBJECT = "*"; - - T resolve(String rootObject, @NonNull String filter); - - default String getTopologyObject(String rootObject, List containerNames) { - int noOfContainers = containerNames.size(); - if (noOfContainers > 2) { - throw TiesPathException.grammarError("More than two level deep path is not allowed"); - } else if (noOfContainers == 2) { - return getTopologyObjectWhenTwoContainers(rootObject, containerNames.get(0)); + /** + * Resolves the supplied filter. + * + * @param rootObject + * - root + * @param filter + * - filter for resolving + * @return T + */ + default T resolve(String rootObject, String filter) { + if (filter == null) { + return onEmptyFilter(rootObject); } - return isRootObjectNullOrEmpty(rootObject) ? NULL_ROOT_OBJECT : rootObject; + preCheck(rootObject, filter); + return process(rootObject, filter); } - default String getTopologyObjectWhenTwoContainers(String rootObject, String firstContainer) { - if (isRootObjectNullOrEmpty(rootObject) || firstContainer.equals(rootObject)) { - return firstContainer; - } else { - throw TiesPathException.grammarError( - "Target filter can only contain Root Object types mentioned in the path parameter"); - } - } + T onEmptyFilter(String rootObject); - default boolean isRootObjectNullOrEmpty(String rootObjectType) { - return rootObjectType == null || rootObjectType.isEmpty(); - } + void preCheck(String rootObject, String filter); + + T process(String rootObject, String filter); + + default tiesPathParser getTiesPathParser(String filter) { + final CharStream inputStream = CharStreams.fromString(filter); + final TiesPathLexer tiesPathLexer = new TiesPathLexer(inputStream); + final tiesPathParser tiesPathParser = new TiesPathParser(new CommonTokenStream(tiesPathLexer)); + tiesPathParser.removeErrorListeners(); + tiesPathParser.addErrorListener(new TiesPathErrorListener()); + tiesPathParser.setErrorHandler(new StrictErrorStrategy()); - @Nullable - default ContainerType getContainerType(List containerNames) { - return ContainerType.fromValue(containerNames.get(containerNames.size() - 1)); + return tiesPathParser; } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/query/TokenType.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverDataType.java similarity index 88% rename from teiv/src/main/java/org/oran/smo/teiv/utils/query/TokenType.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverDataType.java index 9a7f072..a796558 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/query/TokenType.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverDataType.java @@ -18,10 +18,10 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.utils.query; +package org.oran.smo.teiv.exposure.tiespath.resolver; -enum TokenType { - AND, - OR, - NO_TYPE +public enum ResolverDataType { + INTEGER, + STRING, + NOT_NULL } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverUtil.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverUtil.java new file mode 100644 index 0000000..4e4c841 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ResolverUtil.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.resolver; + +import java.util.List; +import java.util.Optional; + +import lombok.experimental.UtilityClass; + +import jakarta.annotation.Nullable; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; +import static org.oran.smo.teiv.utils.TiesConstants.WILDCARD; + +@UtilityClass +public class ResolverUtil { + + public static String getTopologyObject(final String rootObject, final List containerNames) { + final int noOfContainers = containerNames.size(); + final String firstContainer = containerNames.get(0); + + if (isComplexAttribute(containerNames)) { + return getTopologyObjectOnComplexAttributeCondition(rootObject, firstContainer); + } else if (noOfContainers > 2) { + throw TiesPathException.grammarError("More than two level deep path is not allowed"); + } else if (noOfContainers == 2) { + return getTopologyObjectWhenTwoContainers(rootObject, firstContainer); + } + + return Optional.ofNullable(rootObject).orElse(WILDCARD); + } + + public static boolean isComplexAttribute(final List containerNames) { + int index = containerNames.indexOf(ATTRIBUTES); + return index != -1 && containerNames.size() - 1 > index; + } + + @Nullable + public static ContainerType getContainerType(final List containerNames) { + return ContainerType.fromValue(containerNames.get(containerNames.size() - 1)); + } + + private static String getTopologyObjectWhenTwoContainers(final String rootObject, final String firstContainer) { + if (null == rootObject || firstContainer.equals(rootObject)) { + return firstContainer; + } else { + throw TiesPathException.grammarError( + "Target/Scope filter can only contain Root Object types mentioned in the path parameter"); + } + } + + private static String getTopologyObjectOnComplexAttributeCondition(String rootObject, String firstContainer) { + final ContainerType containerType = ContainerType.fromValue(firstContainer); + if (rootObject == null) { + if (containerType != null) { + return WILDCARD; + } + return firstContainer; + } else { + if (rootObject.equals(firstContainer) || containerType != null) { + return rootObject; + } + throw TiesPathException.grammarError( + "Target/Scope filter can only contain Root Object types mentioned in the path parameter"); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeFilterListener.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeFilterListener.java new file mode 100644 index 0000000..7e45e37 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeFilterListener.java @@ -0,0 +1,185 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.resolver; + +import org.oran.smo.teiv.antlr4.tiesPathBaseListener; +import org.oran.smo.teiv.antlr4.tiesPathParser; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndOrLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.QueryFunction; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeObject; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static org.oran.smo.teiv.exposure.tiespath.resolver.ResolverUtil.getContainerType; +import static org.oran.smo.teiv.exposure.tiespath.resolver.ResolverUtil.getTopologyObject; +import static org.oran.smo.teiv.exposure.tiespath.resolver.ResolverUtil.isComplexAttribute; +import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; +import static org.oran.smo.teiv.utils.TiesConstants.WILDCARD; + +public class ScopeFilterListener extends tiesPathBaseListener { + private final String rootObject; + private final List containerNames = new ArrayList<>(); + + public LogicalBlock getLogicalBlock() { + return Optional.ofNullable(logicalBlock).orElseGet(this::generateLBWithContainers); + } + + private LogicalBlock generateLBWithContainers() { + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = ScopeObject.builder(getTopologyObject(this.rootObject, + this.containerNames)).queryFunction(QueryFunction.NOT_NULL).innerContainer(new ArrayList<>(Arrays.asList( + this.containerNames.get(containerNames.size() - 1)))).resolverDataType(ResolverDataType.NOT_NULL); + addScopeLogicalBlock(scopeObjectBuilder); + return this.logicalBlock; + } + + private LogicalBlock logicalBlock; + + public ScopeFilterListener(String rootObject) { + this.rootObject = rootObject; + } + + @Override + public void exitContainerName(final tiesPathParser.ContainerNameContext ctx) { + final String containerName = ctx.getText(); + containerNames.add(containerName); + } + + @Override + public void exitTextFunctionCondition(tiesPathParser.TextFunctionConditionContext ctx) { + if (getContainerType(this.containerNames) == ContainerType.ID) { + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = getScopeObjectBuilder(null, QueryFunction.EQ); + scopeObjectBuilder.parameter(removeQuotes(ctx.StringLiteral().getText())).resolverDataType( + ResolverDataType.STRING); + addScopeLogicalBlock(scopeObjectBuilder); + } else { + throw TiesPathException.grammarError("text() is supported for ID only"); + } + } + + @Override + public void exitContainsTextFunctionCondition(tiesPathParser.ContainsTextFunctionConditionContext ctx) { + if (getContainerType(this.containerNames) == ContainerType.ID) { + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = getScopeObjectBuilder(null, QueryFunction.CONTAINS); + scopeObjectBuilder.parameter(removeQuotes(ctx.StringLiteral().getText())).resolverDataType( + ResolverDataType.STRING); + addScopeLogicalBlock(scopeObjectBuilder); + } else { + throw TiesPathException.grammarError("text() is supported for ID only"); + } + + } + + @Override + public void exitContainsFunctionCondition(final tiesPathParser.ContainsFunctionConditionContext ctx) { + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = getScopeObjectBuilder(ctx.leafName().getText(), + QueryFunction.CONTAINS); + scopeObjectBuilder.parameter(removeQuotes(ctx.StringLiteral().getText())).resolverDataType(ResolverDataType.STRING); + addScopeLogicalBlock(scopeObjectBuilder); + } + + @Override + public void exitLeafCondition(final tiesPathParser.LeafConditionContext ctx) { + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = getScopeObjectBuilder(ctx.leafName().getText(), + QueryFunction.fromValue(ctx.comparativeOperators().getText())); + + if (ctx.IntegerLiteral() != null) { + scopeObjectBuilder.parameter(ctx.IntegerLiteral().getText()).resolverDataType(ResolverDataType.INTEGER); + } else if (ctx.StringLiteral() != null) { + scopeObjectBuilder.parameter(removeQuotes(ctx.StringLiteral().getText())).resolverDataType( + ResolverDataType.STRING); + } else { + throw TiesPathException.grammarError("Unsupported comparison value encountered in expression" + ctx.getText()); + } + + addScopeLogicalBlock(scopeObjectBuilder); + } + + private String removeQuotes(String text) { + // Remove first occurrence of single or double quotes at the start and end of the string + return text.replaceAll("^['\"]+", "").replaceAll("['\"]+$", ""); + } + + @Override + public void exitBooleanOperators(final tiesPathParser.BooleanOperatorsContext ctx) { + final AndOrLogicalBlock andOrLogicalBlock; + if (ctx.getText().equals("and")) { + andOrLogicalBlock = new AndLogicalBlock(); + andOrLogicalBlock.addChild(this.logicalBlock); + } else { + andOrLogicalBlock = new OrLogicalBlock(); + andOrLogicalBlock.addChild(this.logicalBlock); + } + + this.logicalBlock = andOrLogicalBlock; + } + + @Override + public void exitFieldLeaf(final tiesPathParser.FieldLeafContext ctx) { + throw TiesPathException.grammarError("Parameter without any condition is not supported in scope filter"); + } + + private ScopeObject.ScopeObjectBuilder getScopeObjectBuilder(final String leafName, final QueryFunction queryFunction) { + final String topologyObject = getTopologyObject(this.rootObject, this.containerNames); + final ScopeObject.ScopeObjectBuilder scopeObjectBuilder = ScopeObject.builder(topologyObject).leaf(leafName) + .queryFunction(queryFunction); + + Optional.ofNullable(getContainerType(this.containerNames)).ifPresentOrElse(scopeObjectBuilder::container, () -> { + if (!isComplexAttribute(containerNames)) { + final String container = this.containerNames.get(containerNames.size() - 1); + if (topologyObject.equals(container)) { + Optional.ofNullable(getContainerType(List.of(leafName))).ifPresentOrElse( + containerType -> scopeObjectBuilder.container(containerType).leaf(null), () -> { + throw TiesPathException.grammarError(String.format( + "%s is not a valid leaf for topology object: %s", leafName, rootObject)); + }); + } else { + scopeObjectBuilder.topologyObject(Objects.equals(topologyObject, WILDCARD) ? null : topologyObject) + .innerContainer(new ArrayList<>(Arrays.asList(container))); + } + } else { + scopeObjectBuilder.topologyObject(topologyObject.equals(WILDCARD) ? null : topologyObject).container( + ContainerType.ATTRIBUTES).innerContainer(Collections.unmodifiableList(containerNames.subList( + containerNames.indexOf(ATTRIBUTES) + 1, containerNames.size()))); + } + + }); + return scopeObjectBuilder; + } + + private void addScopeLogicalBlock(ScopeObject.ScopeObjectBuilder scopeObjectBuilder) { + if (this.logicalBlock == null || this.logicalBlock instanceof ScopeLogicalBlock) { + this.logicalBlock = new ScopeLogicalBlock(scopeObjectBuilder.build()); + } else if (this.logicalBlock instanceof AndOrLogicalBlock andOrLogicalBlock) { + andOrLogicalBlock.addChild(new ScopeLogicalBlock(scopeObjectBuilder.build())); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolver.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolver.java new file mode 100644 index 0000000..857289d --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolver.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.resolver; + +import java.util.Optional; + +import org.antlr.v4.runtime.misc.ParseCancellationException; +import org.oran.smo.teiv.antlr4.tiesPathParser; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.EmptyLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; +import org.oran.smo.teiv.utils.path.exception.PathParsingException; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class ScopeResolver implements PathResolver { + + @Override + public LogicalBlock onEmptyFilter(String rootObject) { + return EmptyLogicalBlock.getInstance(); + } + + @Override + public void preCheck(String rootObject, String filter) { + //DO NOTHING + } + + @Override + public LogicalBlock process(String rootObject, String filter) { + final int lastIndexOf = getLastIndexOf(filter); + if (lastIndexOf != -1) { + final LogicalBlock logicalBlock = getLogicalBlock(rootObject, filter.substring(lastIndexOf + 1)); + final char c = filter.charAt(lastIndexOf); + if (c == ';') { + AndLogicalBlock andLogicalBlock = new AndLogicalBlock(); + andLogicalBlock.addChild(logicalBlock); + andLogicalBlock.addChild(resolve(rootObject, filter.substring(0, lastIndexOf))); + return andLogicalBlock; + } else if (c == '|') { + OrLogicalBlock orLogicalBlock = new OrLogicalBlock(); + orLogicalBlock.addChild(logicalBlock); + orLogicalBlock.addChild(resolve(rootObject, filter.substring(0, lastIndexOf))); + return orLogicalBlock; + } + } + return getLogicalBlock(rootObject, filter); + } + + private int getLastIndexOf(String string) { + final boolean containsAnd = string.contains(";"); + final boolean containsOr = string.contains("|"); + if (containsAnd && containsOr) { + return Math.max(string.lastIndexOf(";"), string.lastIndexOf("|")); + } else if (containsAnd) { + return string.lastIndexOf(";"); + } else { + return string.lastIndexOf("|"); + } + } + + private LogicalBlock getLogicalBlock(final String rootObject, final String filter) { + try { + final tiesPathParser tiesPathParser = getTiesPathParser(filter); + final ScopeFilterListener scopeFilterListener = new ScopeFilterListener(rootObject); + tiesPathParser.addParseListener(scopeFilterListener); + tiesPathParser.tiesPath(); + LogicalBlock logicalBlock = scopeFilterListener.getLogicalBlock(); + return Optional.ofNullable(logicalBlock).orElseThrow(() -> TiesPathException.grammarError(String.format( + "Unsupported filter token: %s", filter))); + } catch (ParseCancellationException | PathParsingException e) { + log.error("Parsing error on target {} :", filter, e); + throw TiesPathException.grammarError(e.getMessage()); + } + } + +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetFilterListener.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetFilterListener.java new file mode 100644 index 0000000..08e8bcc --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetFilterListener.java @@ -0,0 +1,109 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.resolver; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.antlr.v4.runtime.RuleContext; +import org.oran.smo.teiv.antlr4.tiesPathBaseListener; +import org.oran.smo.teiv.antlr4.tiesPathParser; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TargetObject; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +import static org.oran.smo.teiv.exposure.tiespath.resolver.ResolverUtil.getContainerType; +import static org.oran.smo.teiv.exposure.tiespath.resolver.ResolverUtil.getTopologyObject; + +public class TargetFilterListener extends tiesPathBaseListener { + private final String rootObject; + private final List containerNames = new ArrayList<>(); + private List attributeNames = new ArrayList<>(); + + public TargetFilterListener(String rootObject) { + this.rootObject = rootObject; + } + + public TargetObject getTargetObject() { + if (containerNames.isEmpty()) { + //invalid scenario + throw TiesException.serverException("Server unknown exception", "Requested query could not be processed", null); + } + return Optional.ofNullable(getContainerType(this.containerNames)).map(containerType -> { + validateIfParamsApplicable(containerType); + return TargetObject.builder(getTopologyObject(rootObject, containerNames)).container(containerType).params( + this.attributeNames).build(); + }).orElseGet(() -> checkAndProcessIfSingleContainerAndValidTopologyObject(rootObject, this.containerNames, + this.attributeNames)); + } + + private void validateIfParamsApplicable(ContainerType containerType) { + if (!containerType.isParamAllowedInTargetFilter() && !this.attributeNames.isEmpty()) { + throw TiesPathException.grammarError(String.format("Parameters are not supported for %s in target filter", + containerType.getValue())); + } + } + + @Override + public void exitContainerName(final tiesPathParser.ContainerNameContext ctx) { + final String containerName = ctx.getText(); + containerNames.add(containerName); + } + + @Override + public void exitContainsFunctionCondition(final tiesPathParser.ContainsFunctionConditionContext ctx) { + throw TiesPathException.grammarError(""); + } + + @Override + public void exitLeafCondition(final tiesPathParser.LeafConditionContext ctx) { + throw TiesPathException.grammarError("Parameter condition is not supported in target filter"); + } + + @Override + public void exitBooleanOperators(final tiesPathParser.BooleanOperatorsContext ctx) { + throw TiesPathException.grammarError(""); + } + + @Override + public void exitFieldLeaf(final tiesPathParser.FieldLeafContext ctx) { + attributeNames = ctx.leafName().stream().map(RuleContext::getText).toList(); + } + + private TargetObject checkAndProcessIfSingleContainerAndValidTopologyObject(String rootObject, + List containerNames, List attributeNames) { + final int noOfContainers = containerNames.size(); + if (noOfContainers == 1 && (null == rootObject || rootObject.equals(containerNames.get(0)))) { + assertAttributesApplicableForContainer(attributeNames); + return TargetObject.builder(containerNames.get(0)).build(); + } + throw TiesPathException.grammarError( + "Invalid Container name or Root Object name does not match to the path parameter"); + } + + private void assertAttributesApplicableForContainer(List attrNames) { + if (!attrNames.isEmpty()) { + throw TiesPathException.grammarError("Attributes cannot be associated at this level"); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolver.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolver.java index 588599a..927e2df 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolver.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolver.java @@ -22,26 +22,40 @@ package org.oran.smo.teiv.exposure.tiespath.resolver; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Optional; import org.antlr.v4.runtime.misc.ParseCancellationException; +import org.oran.smo.teiv.antlr4.tiesPathParser; import org.springframework.stereotype.Component; -import org.oran.smo.teiv.exception.TiesException; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TargetObject; -import org.oran.smo.teiv.utils.path.TiesPathQuery; -import org.oran.smo.teiv.utils.path.TiesPathUtil; import org.oran.smo.teiv.utils.path.exception.PathParsingException; import org.oran.smo.teiv.utils.query.exception.TiesPathException; -import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import static org.oran.smo.teiv.utils.TiesConstants.WILDCARD; + @Slf4j @Component public class TargetResolver implements PathResolver> { + @Override + public List onEmptyFilter(String rootObject) { + final String topologyObject = Optional.ofNullable(rootObject).orElse(WILDCARD); + final TargetObject targetObject = TargetObject.builder(topologyObject).build(); + final ArrayList objects = new ArrayList<>(); + objects.add(targetObject); + return objects; + } + + @Override + public void preCheck(String rootObject, String filter) { + if (filter.contains("|")) { + throw TiesPathException.grammarError("OR (|) is not supported for target filter"); + } + } + /** * Process filter and root objectType . Populates List of Target Object * @@ -51,59 +65,22 @@ public class TargetResolver implements PathResolver> { * filter in the query parameter * @return Immutable list of filter objects */ - public List resolve(String rootObject, @NonNull String filter) { - preCheck(filter); - if (filter.isEmpty()) { - final String topologyObject = isRootObjectNullOrEmpty(rootObject) ? NULL_ROOT_OBJECT : rootObject; - return List.of(TargetObject.builder(topologyObject).build()); - } else { - List targetObjects = new ArrayList<>(); - Arrays.stream(filter.split(";")).forEach(targetToken -> { - final TiesPathQuery tiesPathQuery; - try { - tiesPathQuery = TiesPathUtil.getTiesPathQuery(targetToken); - } catch (ParseCancellationException | PathParsingException e) { - log.error("Parsing error on target {} :", targetToken, e); - throw TiesPathException.grammarError(e.getMessage()); - } - - final int noOfContainers = tiesPathQuery.getContainerNames().size(); - if (noOfContainers == 0) { - //invalid scenario - throw TiesException.serverException("Server unknown exception", - "Requested query could not be processed", null); - } + @Override + public List process(String rootObject, String filter) { + List targetObjects = new ArrayList<>(); + Arrays.stream(filter.split(";")).forEach(targetToken -> { + try { + tiesPathParser pathParser = getTiesPathParser(targetToken); + final TargetFilterListener targetFilterListener = new TargetFilterListener(rootObject); + pathParser.addParseListener(targetFilterListener); + pathParser.tiesPath(); - Optional.ofNullable(getContainerType(tiesPathQuery.getContainerNames())).ifPresentOrElse( - containerType -> targetObjects.add(TargetObject.builder(getTopologyObject(rootObject, tiesPathQuery - .getContainerNames())).container(containerType).params(tiesPathQuery.getAttributeNames()) - .build()), () -> targetObjects.add(checkIfSingleContainerAndValidTopologyObject(rootObject, - tiesPathQuery.getContainerNames(), tiesPathQuery.getAttributeNames()))); - }); - return Collections.unmodifiableList(targetObjects); - } - } - - private void preCheck(String target) { - if (target.contains("|")) { - throw TiesPathException.grammarError("OR (|) is not supported for target filter"); - } - } - - private TargetObject checkIfSingleContainerAndValidTopologyObject(String rootObject, List containerNames, - List attributeNames) { - final int noOfContainers = containerNames.size(); - if (noOfContainers == 1 && (isRootObjectNullOrEmpty(rootObject) || rootObject.equals(containerNames.get(0)))) { - assertAttributesApplicableForContainer(attributeNames); - return TargetObject.builder(containerNames.get(0)).build(); - } - throw TiesPathException.grammarError( - "Invalid Container name or Root Object name does not match to the path parameter"); - } - - private void assertAttributesApplicableForContainer(List attrNames) { - if (!attrNames.isEmpty()) { - throw TiesPathException.grammarError("Attributes cannot be associated at this level"); - } + targetObjects.add(targetFilterListener.getTargetObject()); + } catch (ParseCancellationException | PathParsingException e) { + log.error("Parsing error on target {} :", targetToken, e); + throw TiesPathException.grammarError(e.getMessage()); + } + }); + return targetObjects; } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationDTO.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationDTO.java deleted file mode 100644 index 22eff16..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationDTO.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.utils; - -import lombok.Data; - -import java.util.HashMap; -import java.util.Map; - -@Data -public class PaginationDTO { - private int limit; - private int offset; - private int totalSize; - private Map queryParameters = new HashMap<>(); - private Map pathParameters = new HashMap<>(); - private String basePath; - - private PaginationDTO(int limit, int offset, Map queryParameters, Map pathParameters, - String basePath) { - this.limit = limit; - this.offset = offset; - this.queryParameters.putAll(queryParameters); - this.pathParameters.putAll(pathParameters); - this.basePath = basePath; - } - - public static PaginationDTOBuilder builder() { - return new PaginationDTOBuilder(); - } - - public static class PaginationDTOBuilder { - private int limit; - private int offset; - private final Map queryParameters = new HashMap<>(); - private final Map pathParameters = new HashMap<>(); - private String basePath; - - PaginationDTOBuilder() { - } - - public PaginationDTOBuilder limit(int limit) { - this.limit = limit; - return this; - } - - public PaginationDTOBuilder offset(int offset) { - this.offset = offset; - return this; - } - - public PaginationDTOBuilder addQueryParameters(String key, String value) { - queryParameters.put(key, value); - return this; - } - - public PaginationDTOBuilder addPathParameters(String key, String value) { - pathParameters.put(key, value); - return this; - } - - public PaginationDTOBuilder basePath(String basePath) { - this.basePath = basePath; - return this; - } - - public PaginationDTO build() { - return new PaginationDTO(limit, offset, queryParameters, pathParameters, basePath); - } - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationUtil.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationUtil.java new file mode 100644 index 0000000..150c201 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/PaginationUtil.java @@ -0,0 +1,159 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.utils; + +import lombok.experimental.UtilityClass; +import org.oran.smo.teiv.api.model.OranTeivHref; +import org.oran.smo.teiv.exception.TiesException; + +/** + * Generates the pagination link as href. + */ +@UtilityClass +public class PaginationUtil { + + /** + * Validates whether the offset is greater than the totalCount and throws exception. + */ + public static void validateOffset(int offset, int totalCount) { + if (totalCount > 0 && totalCount <= offset) { + throw TiesException.invalidValueException("Offset", totalCount - 1, true); + } + } + + /** + * Gets the viable offset based on given offset, limit and totalCount. + * + * @param offset + * - offset from the request + * @param totalCount + * - total count of the records + * @throws TiesException + * - if offset is greater than totalCount + */ + public static int getViableLimit(final int offset, final int limit, final int totalCount) { + validateOffset(offset, totalCount); + + return (totalCount == 0) ? totalCount : Math.min(limit, totalCount - offset); + } + + /** + * Gets the first page href. + * + * @param requestDetails + * - request details + * @return first page href as {@link OranTeivHref} + */ + public static OranTeivHref firstHref(RequestDetails requestDetails) { + return getHref(requestDetails, 0); + } + + /** + * Gets the prev page href. + * + * @param requestDetails + * - request details + * @param totalCount + * - total items count + * @return prev page href as {@link OranTeivHref} + */ + public static OranTeivHref prevHref(RequestDetails requestDetails, int totalCount) { + if (requestDetails.getOffset() > 0 && totalCount > 0) { + final int prevOffset = Math.max(requestDetails.getOffset() - requestDetails.getLimit(), 0); + return getHref(requestDetails, prevOffset); + } + return selfHref(requestDetails); + } + + /** + * Gets the self page href. + * + * @param requestDetails + * - request details + * @return self page href as {@link OranTeivHref} + */ + public static OranTeivHref selfHref(RequestDetails requestDetails) { + return getHref(requestDetails, requestDetails.getOffset()); + } + + /** + * Gets the next page href. + * + * @param requestDetails + * - request details + * @param totalCount + * - total items count + * @return next page href as {@link OranTeivHref} + */ + public static OranTeivHref nextHref(RequestDetails requestDetails, int totalCount) { + if (hasNextPage(requestDetails, totalCount)) { + final int nextOffset = Math.min(requestDetails.getOffset() + requestDetails.getLimit(), totalCount); + return getHref(requestDetails, nextOffset); + } + + return selfHref(requestDetails); + } + + /** + * Gets the last page href. + * + * @param requestDetails + * - request details + * @param totalCount + * - total items count + * @return last page href as {@link OranTeivHref} + */ + public static OranTeivHref lastHref(RequestDetails requestDetails, int totalCount) { + if (hasNextPage(requestDetails, totalCount)) { + final int diff = totalCount - requestDetails.getOffset(); + final int lastOffset; + if (diff % requestDetails.getLimit() == 0) { + lastOffset = (diff / requestDetails.getLimit() - 1) * requestDetails.getLimit() + requestDetails + .getOffset(); + } else { + lastOffset = (diff / requestDetails.getLimit()) * requestDetails.getLimit() + requestDetails.getOffset(); + } + return getHref(requestDetails, lastOffset); + } + + return selfHref(requestDetails); + } + + private static OranTeivHref getHref(RequestDetails requestDetails, int pageOffset) { + StringBuilder hrefString = new StringBuilder(requestDetails.getBasePath()).append(String.format( + "?offset=%s&limit=%s", pageOffset, requestDetails.getLimit())); + + requestDetails.getQueryParams().forEach((key, value) -> { + if (value != null) { + hrefString.append("&").append(key).append("=").append(value); + } + }); + return OranTeivHref.builder().href(hrefString.toString()).build(); + } + + private static boolean hasNextPage(final RequestDetails requestDetails, int totalCount) { + if (totalCount > 0) { + return (requestDetails.getOffset() + requestDetails.getLimit()) < totalCount; + } + + return false; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/collection/rest/controller/TopologyGroupsRestController.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestDetails.java similarity index 69% rename from teiv/src/main/java/org/oran/smo/teiv/exposure/collection/rest/controller/TopologyGroupsRestController.java rename to teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestDetails.java index d4d8cd2..8705258 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/collection/rest/controller/TopologyGroupsRestController.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestDetails.java @@ -18,16 +18,29 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ -package org.oran.smo.teiv.exposure.collection.rest.controller; +package org.oran.smo.teiv.exposure.utils; -import org.oran.smo.teiv.api.TopologyGroupsApi; -import org.oran.smo.teiv.utils.TiesConstants; +import java.util.Map; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.Builder; +import lombok.NonNull; +import lombok.Singular; +import lombok.Value; -@RestController -@RequestMapping(TiesConstants.REQUEST_MAPPING) -public class TopologyGroupsRestController implements TopologyGroupsApi { +@Value +@Builder +public class RequestDetails { + + @Builder.Default + int offset = 0; + + @Builder.Default + int limit = 500; + + @NonNull + String basePath; + + @Singular + Map queryParams; } diff --git a/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestValidator.java b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestValidator.java index 37f496b..6f87682 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestValidator.java +++ b/teiv/src/main/java/org/oran/smo/teiv/exposure/utils/RequestValidator.java @@ -20,14 +20,19 @@ */ package org.oran.smo.teiv.exposure.utils; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.oran.smo.teiv.exception.TiesException; import org.oran.smo.teiv.schema.SchemaRegistry; import lombok.RequiredArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Objects; @Service @RequiredArgsConstructor +@Slf4j public class RequestValidator { public void validateDomain(String domain) { @@ -62,13 +67,11 @@ public class RequestValidator { } } - public void validateFiltersForRelationships(String targetFilter, String scopeFilter) { - if (targetFilter != null) { - throw TiesException.notImplementedException("Using targetFilter for this endpoint is not implemented.", null); - } - if (scopeFilter != null && scopeFilter.startsWith("/attributes")) { - throw TiesException.notImplementedException( - "Using scopeFilter for filtering relationship attributes is not implemented.", null); + public void validateYangFile(MultipartFile file) { + + if (!Objects.equals(file.getContentType(), "application/yang")) { + throw TiesException.invalidFileInput("Invalid file"); } + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/CreateTopologyProcessor.java b/teiv/src/main/java/org/oran/smo/teiv/listener/CreateTopologyProcessor.java index 27a6010..bf508e4 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/CreateTopologyProcessor.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/CreateTopologyProcessor.java @@ -52,6 +52,7 @@ public class CreateTopologyProcessor implements TopologyProcessor { customMetrics.incrementNumUnsuccessfullyParsedCreateCloudEvents(); return; } + parsedCloudEventData.sort(); stopWatch.stop(); customMetrics.recordCloudEventCreateParseTime(stopWatch.lastTaskInfo().getTimeNanos()); customMetrics.incrementNumSuccessfullyParsedCreateCloudEvents(); diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/DeleteTopologyProcessor.java b/teiv/src/main/java/org/oran/smo/teiv/listener/DeleteTopologyProcessor.java index fc401ae..59c9395 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/DeleteTopologyProcessor.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/DeleteTopologyProcessor.java @@ -24,7 +24,6 @@ import io.cloudevents.CloudEvent; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Consumer; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -32,6 +31,7 @@ import org.jooq.DSLContext; import org.oran.smo.teiv.CustomMetrics; import org.oran.smo.teiv.schema.EntityType; import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.RelationshipDataLocation; import org.oran.smo.teiv.schema.SchemaRegistry; import org.oran.smo.teiv.service.TiesDbOperations; import org.oran.smo.teiv.service.TiesDbService; @@ -64,6 +64,7 @@ public class DeleteTopologyProcessor implements TopologyProcessor { customMetrics.incrementNumUnsuccessfullyParsedDeleteCloudEvents(); return; } + parsedCloudEventData.sort(); stopWatch.stop(); customMetrics.recordCloudEventDeleteParseTime(stopWatch.lastTaskInfo().getTimeNanos()); customMetrics.incrementNumSuccessfullyParsedDeleteCloudEvents(); @@ -75,23 +76,20 @@ public class DeleteTopologyProcessor implements TopologyProcessor { parsedCloudEventData.getEntities().forEach(entity -> { EntityType entityType = SchemaRegistry.getEntityTypeByName(entity.getType()); - dbOperations.add(dslContext -> operationResults.addAll( - tiesDbOperations.deleteEntity(dslContext, entityType, entity.getId()))); + dbOperations.add(dslContext -> operationResults + .addAll(tiesDbOperations.deleteEntity(dslContext, entityType, entity.getId()))); }); parsedCloudEventData.getRelationships().forEach(relationship -> { RelationType relationType = SchemaRegistry.getRelationTypeByName(relationship.getType()); - switch (Objects.requireNonNull(relationType).getRelationshipStorageLocation()) { - case RELATION -> dbOperations.add(dslContext -> { - Optional operationResult = tiesDbOperations.deleteManyToManyRelationByRelationId( - dslContext, relationType.getTableName(), relationship.getId()); - operationResult.ifPresent(operationResults::add); - }); - case A_SIDE, B_SIDE -> dbOperations.add(dslContext -> { - Optional operationResult = tiesDbOperations.deleteRelationFromEntityTableByRelationId( - dslContext, relationship.getId(), relationType); - operationResult.ifPresent(operationResults::add); - }); + if (Objects.requireNonNull(relationType) + .getRelationshipStorageLocation() == RelationshipDataLocation.RELATION) { + dbOperations.add(dslContext -> tiesDbOperations.deleteManyToManyRelationByRelationId(dslContext, + relationType, relationship.getId()).ifPresent(operationResults::add)); + } else { + dbOperations + .add(dslContext -> tiesDbOperations.deleteRelationFromEntityTableByRelationId(dslContext, + relationship.getId(), relationType).ifPresent(operationResults::add)); } }); @@ -99,7 +97,7 @@ public class DeleteTopologyProcessor implements TopologyProcessor { tiesDbService.execute(dbOperations); } catch (RuntimeException e) { log.error("Failed to process a CloudEvent. Discarded CloudEvent: {}. Used kafka message key: {}. Reason: {}", - CloudEventUtil.cloudEventToPrettyString(cloudEvent), messageKey, e.getMessage()); + CloudEventUtil.cloudEventToPrettyString(cloudEvent), messageKey, e.getMessage()); customMetrics.incrementNumUnsuccessfullyPersistedDeleteCloudEvents(); return; } diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/MergeTopologyProcessor.java b/teiv/src/main/java/org/oran/smo/teiv/listener/MergeTopologyProcessor.java index 095c599..e2e0ea8 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/MergeTopologyProcessor.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/MergeTopologyProcessor.java @@ -60,6 +60,7 @@ public class MergeTopologyProcessor implements TopologyProcessor { customMetrics.incrementNumUnsuccessfullyParsedMergeCloudEvents(); return; } + parsedCloudEventData.sort(); stopWatch.stop(); customMetrics.recordCloudEventMergeParseTime(stopWatch.lastTaskInfo().getTimeNanos()); customMetrics.incrementNumSuccessfullyParsedMergeCloudEvents(); diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessor.java b/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessor.java index 91171bf..bb3f915 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessor.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessor.java @@ -48,9 +48,7 @@ import org.oran.smo.teiv.service.TiesDbService; @Slf4j @AllArgsConstructor @Profile("ingestion") - public class SourceEntityDeleteTopologyProcessor implements TopologyProcessor { - private final TiesDbService tiesDbService; private final ObjectMapper objectMapper; private final CustomMetrics customMetrics; @@ -86,8 +84,8 @@ public class SourceEntityDeleteTopologyProcessor implements TopologyProcessor { List operationResults = new ArrayList<>(); try { List> dbOperations = new ArrayList<>(); - SchemaRegistry.getEntityTypesWithCmId().forEach(entityType -> dbOperations.add(dslContext -> { - List results = tiesDbOperations.selectByCmHandle(dslContext, entityType.getTableName(), + SchemaRegistry.getEntityTypes().forEach(entityType -> dbOperations.add(dslContext -> { + List results = tiesDbOperations.selectByCmHandleFormSourceIds(dslContext, entityType.getTableName(), sourceEntityDelete.value); if (!results.isEmpty()) { for (String result : results) { diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1.java b/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1.java deleted file mode 100644 index f3fb9fc..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.listener; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import org.oran.smo.teiv.service.models.OperationResult; -import org.oran.smo.teiv.utils.CloudEventUtil; -import org.jooq.DSLContext; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; -import org.springframework.util.StopWatch; - -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.service.TiesDbOperations; -import org.oran.smo.teiv.service.TiesDbService; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.cloudevents.CloudEvent; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Component -@Slf4j -@AllArgsConstructor -@Profile("ingestion") -public class SourceEntityDeleteTopologyProcessorV1 implements TopologyProcessor { - private final TiesDbService tiesDbService; - private final ObjectMapper objectMapper; - private final CustomMetrics customMetrics; - private final TiesDbOperations tiesDbOperations; - - @Override - public void process(CloudEvent cloudEvent, String messageKey) { - StopWatch stopWatch = new StopWatch(); - stopWatch.start(); - - SourceEntityDeleteV1 sourceEntityDelete; - try { - sourceEntityDelete = objectMapper.readValue(cloudEvent.getData().toBytes(), SourceEntityDeleteV1.class); - } catch (IOException e) { - log.error("Error while parsing the {} event.", e.getMessage()); - customMetrics.incrementNumUnsuccessfullyParsedSourceEntityDeleteCloudEvents(); - return; - } - - //currently only cmHandle delete supported - if (!"cmHandle".equalsIgnoreCase(sourceEntityDelete.type)) { - log.error("Unsupported type: {} for source-entity-delete event. Event: {}", sourceEntityDelete.type, - cloudEvent); - customMetrics.incrementNumReceivedCloudEventNotSupported(); - return; - } - - stopWatch.stop(); - customMetrics.recordCloudEventSourceEntityDeleteParseTime(stopWatch.lastTaskInfo().getTimeNanos()); - customMetrics.incrementNumSuccessfullyParsedSourceEntityDeleteCloudEvents(); - - stopWatch.start(); - List operationResults = new ArrayList<>(); - try { - List> dbOperations = new ArrayList<>(); - SchemaRegistry.getEntityTypes().forEach(entityType -> dbOperations.add(dslContext -> { - List results = tiesDbOperations.selectByCmHandleFormSourceIds(dslContext, entityType.getTableName(), - sourceEntityDelete.value); - if (!results.isEmpty()) { - for (String result : results) { - operationResults.addAll(tiesDbOperations.deleteEntity(dslContext, entityType, result)); - } - } - })); - tiesDbService.execute(dbOperations); - } catch (RuntimeException e) { - log.error("Failed to process a CloudEvent. Discarded CloudEvent: {}. Used kafka message key: {}. Reason: {}", - CloudEventUtil.cloudEventToPrettyString(cloudEvent), messageKey, e.getMessage()); - customMetrics.incrementNumUnsuccessfullyPersistedSourceEntityDeleteCloudEvents(); - return; - } - - stopWatch.stop(); - customMetrics.recordCloudEventSourceEntityDeletePersistTime(stopWatch.lastTaskInfo().getTimeNanos()); - customMetrics.incrementNumSuccessfullyPersistedSourceEntityDeleteCloudEvents(); - } - - @JsonIgnoreProperties(ignoreUnknown = true) - record SourceEntityDeleteV1(@JsonProperty(value = "type", required = true) String type, - @JsonProperty(value = "value", required = true) String value) { - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyListener.java b/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyListener.java index 3cc7530..236adc3 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyListener.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyListener.java @@ -45,7 +45,7 @@ public class TopologyListener { private final TopologyProcessorRegistry topologyProcessorRegistry; private final LogAccessor logger = new LogAccessor(TopologyListener.class); - @KafkaListener(id = "${kafka.topology-ingestion.consumer.group-id}", topics = "${kafka.topology-ingestion.consumer.topic.name}", containerFactory = "topologyListenerContainerFactory", autoStartup = "false") + @KafkaListener(id = "${kafka.topology-ingestion.consumer.group-id}", topics = "${kafka.topology-ingestion.topic.name}", containerFactory = "topologyListenerContainerFactory", autoStartup = "false") public void processEvents(List> events) { log.info("Processing events: {}", events.size()); for (ConsumerRecord rec : events) { diff --git a/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyProcessorRegistry.java b/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyProcessorRegistry.java index fe8dfde..9e83acd 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyProcessorRegistry.java +++ b/teiv/src/main/java/org/oran/smo/teiv/listener/TopologyProcessorRegistry.java @@ -20,7 +20,6 @@ */ package org.oran.smo.teiv.listener; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import io.cloudevents.CloudEvent; @@ -41,12 +40,8 @@ public class TopologyProcessorRegistry { private final MergeTopologyProcessor mergeTopologyProcessor; private final DeleteTopologyProcessor deleteTopologyProcessor; private final SourceEntityDeleteTopologyProcessor sourceEntityDeleteTopologyProcessor; - private final SourceEntityDeleteTopologyProcessorV1 sourceEntityDeleteTopologyProcessorV1; private final UnsupportedTopologyEventProcessor unsupportedTopologyEventProcessor; - @Value("${feature_flags.use_alternate_delete_logic}") - private boolean useAlternateDeleteLogic; - public TopologyProcessor getProcessor(CloudEvent event) { String cloudEventType = getCloudEventType(event); switch (cloudEventType) { @@ -68,9 +63,7 @@ public class TopologyProcessorRegistry { case TiesConstants.CLOUD_EVENT_WITH_TYPE_SOURCE_ENTITY_DELETE -> { log.debug("Source Entity Delete CloudEvent received with id: {}", event.getId()); metrics.incrementNumReceivedCloudEventSourceEntityDelete(); - return useAlternateDeleteLogic ? - sourceEntityDeleteTopologyProcessorV1 : - sourceEntityDeleteTopologyProcessor; + return sourceEntityDeleteTopologyProcessor; } default -> { metrics.incrementNumReceivedCloudEventNotSupported(); diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/BidiDbNameMapper.java b/teiv/src/main/java/org/oran/smo/teiv/schema/BidiDbNameMapper.java index e2b6827..5cacbb2 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/BidiDbNameMapper.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/BidiDbNameMapper.java @@ -42,6 +42,9 @@ public class BidiDbNameMapper { * @return the mapped DB name */ public static String getDbName(String name) { + if (!nameMap.containsKey(name)) { + return name; + } return nameMap.get(name); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/ConsumerDataCache.java b/teiv/src/main/java/org/oran/smo/teiv/schema/ConsumerDataCache.java index 102ca05..4ef6125 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/ConsumerDataCache.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/ConsumerDataCache.java @@ -20,9 +20,9 @@ */ package org.oran.smo.teiv.schema; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataRepository; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.scheduling.annotation.Scheduled; @@ -38,20 +38,20 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class ConsumerDataCache { - private final DataPersistanceService dataPersistanceService; + private final ConsumerDataRepository consumerDataRepository; @Cacheable("classifiers") public Set getClassifiers() { - return Collections.unmodifiableSet(dataPersistanceService.loadClassifiers()); + return Collections.unmodifiableSet(consumerDataRepository.loadClassifiers()); } @Cacheable("decorators") - public Map getDecorators() { - return Collections.unmodifiableMap(dataPersistanceService.loadDecorators()); + public Map getDecorators() { + return Collections.unmodifiableMap(consumerDataRepository.loadDecorators()); } @Cacheable("validClassifiers") - public Set getValidClassifiers(String partialClassifier) { + public Set getValidClassifiers(final String partialClassifier) { return getClassifiers().stream().filter(c -> c.contains(partialClassifier)).collect(Collectors.toSet()); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/DataType.java b/teiv/src/main/java/org/oran/smo/teiv/schema/DataType.java index 449a696..155eb9a 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/DataType.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/DataType.java @@ -25,6 +25,7 @@ import java.util.Locale; public enum DataType { PRIMITIVE, DECIMAL, + INTEGER, BIGINT, CONTAINER, GEOGRAPHIC; @@ -33,6 +34,7 @@ public enum DataType { return switch (dbDatatype.toUpperCase(Locale.US)) { case "TEXT", "VARCHAR" -> PRIMITIVE; case "NUMERIC", "DECIMAL" -> DECIMAL; + case "INT4" -> INTEGER; case "BIGINT", "INT8" -> BIGINT; case "JSONB" -> CONTAINER; case "GEOGRAPHY" -> GEOGRAPHIC; diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/EntityType.java b/teiv/src/main/java/org/oran/smo/teiv/schema/EntityType.java index 9211d1a..654f10e 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/EntityType.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/EntityType.java @@ -21,89 +21,88 @@ package org.oran.smo.teiv.schema; import static org.jooq.impl.DSL.field; +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; import static org.oran.smo.teiv.schema.BidiDbNameMapper.getDbName; -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; -import static org.oran.smo.teiv.schema.DataType.BIGINT; import static org.oran.smo.teiv.schema.DataType.CONTAINER; -import static org.oran.smo.teiv.schema.DataType.DECIMAL; import static org.oran.smo.teiv.schema.DataType.GEOGRAPHIC; +import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES_ABBREVIATION; +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; import static org.oran.smo.teiv.utils.TiesConstants.CONSUMER_DATA_PREFIX; +import static org.oran.smo.teiv.utils.TiesConstants.DECORATORS; import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; import static org.oran.smo.teiv.utils.TiesConstants.REL_PREFIX; import static org.oran.smo.teiv.utils.TiesConstants.ST_TO_STRING; -import static org.oran.smo.teiv.utils.TiesConstants.ST_TO_STRING_COLUMN_WITH_TABLE_NAME; import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; import static org.oran.smo.teiv.utils.TiesConstants.SOURCE_IDS; -import java.math.BigDecimal; -import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.Value; import org.jooq.Field; import org.jooq.JSONB; import lombok.Builder; import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; -@Getter +import org.oran.smo.teiv.exposure.spi.Module; + +@Value @Builder -@ToString public class EntityType implements Persistable { @EqualsAndHashCode.Include - private final String name; - private final Map fields; - private final Module module; + String name; + Map fields; + String tableName; + Module module; @Override public String getTableName() { - return String.format(TIES_DATA, getDbName(this.name)); + return String.format(TIES_DATA, getDbName(this.tableName)); } @Override public String getIdColumnName() { - return getTableName() + "." + ID_COLUMN_NAME; + return ID_COLUMN_NAME; } @Override - public List getAttributeColumnsWithId() { - final List columnList = new ArrayList<>(); - this.fields.forEach((fieldName, dataType) -> { - if ((fieldName.startsWith(REL_PREFIX)) || fieldName.startsWith(CONSUMER_DATA_PREFIX)) { - return; - } - final String tableString = getTableName() + "."; - columnList.add(tableString + String.format(QUOTED_STRING, getDbName(fieldName))); - }); - return columnList; + public String getIdColumnNameWithTableName() { + return getTableName() + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME); } @Override - public List getAllFieldsWithId() { - final List fieldList = new ArrayList<>(); + @SuppressWarnings("java:S5738") + public Map getSpecificAttributeColumns(List attributes) { + final Map fieldList = new HashMap<>(); this.fields.forEach((fieldName, dataType) -> { - if (fieldName.startsWith(REL_PREFIX)) { + if (!attributes.contains(fieldName) && !attributes.isEmpty()) { + return; + } + if (fieldName.startsWith(REL_PREFIX) || fieldName.startsWith(CONSUMER_DATA_PREFIX) || fieldName.equals( + ID_COLUMN_NAME)) { return; } if (GEOGRAPHIC.equals(dataType)) { - fieldList.add(field(String.format(ST_TO_STRING, getDbName(fieldName))).as(getDbName(fieldName))); + fieldList.put(field(String.format(ST_TO_STRING, getTableName() + "." + String.format(QUOTED_STRING, + getDbName(fieldName)))).as(hashAlias( + getFullyQualifiedName() + ATTRIBUTES_ABBREVIATION + fieldName)), dataType); } else if (CONTAINER.equals(dataType)) { - fieldList.add(field(String.format(QUOTED_STRING, getDbName(fieldName)), JSONB.class).as(getDbName( - fieldName))); + fieldList.put(field(getTableName() + "." + String.format(QUOTED_STRING, getDbName(fieldName)), JSONB.class) + .as(hashAlias(getFullyQualifiedName() + ATTRIBUTES_ABBREVIATION + fieldName)), dataType); } else { - fieldList.add(field(String.format(QUOTED_STRING, getDbName(fieldName))).as(getDbName(fieldName))); + fieldList.put(field(getTableName() + "." + String.format(QUOTED_STRING, getDbName(fieldName))).as(hashAlias( + getFullyQualifiedName() + ATTRIBUTES_ABBREVIATION + fieldName)), dataType); } }); return fieldList; } public List getAttributeNames() { - return this.fields.keySet().stream().filter(field -> (!field.startsWith(REL_PREFIX) || !field.startsWith( - CONSUMER_DATA_PREFIX))).toList(); + return this.fields.keySet().stream().filter(field -> (!field.startsWith(REL_PREFIX) && !field.startsWith( + CONSUMER_DATA_PREFIX) && !field.equals(ID_COLUMN_NAME))).toList(); } /** @@ -111,38 +110,28 @@ public class EntityType implements Persistable { * * @return the fully qualified name */ + @Override public String getFullyQualifiedName() { return String.format("%s:%s", module.getName(), name); } - public Field getField(String column, String prefix, String tableName) { - final String columnName = column.contains(".") ? column.split("\\.")[2].replace("\"", "") : column; - final String alias = (prefix != null ? (prefix + ".") : "") + column; - final String tableString = tableName != null ? (String.format(TIES_DATA, tableName) + ".") : ""; - - if (!this.fields.containsKey(getModelledName(columnName))) { - return null; - } - - DataType type = this.fields.get(getModelledName(columnName)); - - if (type.equals(GEOGRAPHIC) && column.contains(TIES_DATA_SCHEMA)) { - return field(String.format(ST_TO_STRING_COLUMN_WITH_TABLE_NAME, column), String.class).as(alias); - } else if (type.equals(GEOGRAPHIC)) { - return field(tableString + String.format(ST_TO_STRING, column), String.class).as(alias); - } else if (type.equals(CONTAINER)) { - return field(tableString + column, JSONB.class).as(alias); - } else if (type.equals(DECIMAL)) { - return field(tableString + column, BigDecimal.class).as(alias); - } else if (type.equals(BIGINT)) { - return field(tableString + column, Long.class).as(alias); - } else { - return field(tableString + column, String.class).as(alias); - } - } - @Override public String getSourceIdsColumnName() { return getDbName(CONSUMER_DATA_PREFIX + SOURCE_IDS); } + + @Override + public String getClassifiersColumnName() { + return getDbName(CONSUMER_DATA_PREFIX + CLASSIFIERS); + } + + @Override + public String getDecoratorsColumnName() { + return getDbName(CONSUMER_DATA_PREFIX + DECORATORS); + } + + @Override + public String getCategory() { + return "entity"; + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/Persistable.java b/teiv/src/main/java/org/oran/smo/teiv/schema/Persistable.java index 0448a15..d9c6575 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/Persistable.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/Persistable.java @@ -20,9 +20,17 @@ */ package org.oran.smo.teiv.schema; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.jooq.Field; +import org.jooq.JSONB; + +import static org.jooq.impl.DSL.field; +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; +import static org.oran.smo.teiv.utils.PersistableUtil.getFullyQualifiedNameWithColumnName; +import static org.oran.smo.teiv.utils.TiesConstants.*; public interface Persistable { @@ -42,18 +50,43 @@ public interface Persistable { String getIdColumnName(); /** - * Gets all the column names. + * Gets the column name used for storing the unique identifier. + * + * @return the id column name with table name + */ + String getIdColumnNameWithTableName(); + + /** + * Gets specific columns. + * + * @param attributes + * specific attributes names * - * @return the list of column names + * @return the list of columns */ - List getAttributeColumnsWithId(); + Map getSpecificAttributeColumns(List attributes); /** * Gets all the columns names as list of {@link Field} * + * * @return the list of {@link Field} */ - List getAllFieldsWithId(); + default List getAllFieldsWithId() { + List result = new ArrayList<>(getSpecificAttributeColumns(List.of()).keySet()); + String fullyQuelifiedName = getFullyQualifiedName(); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, getIdColumnName())).as(hashAlias( + getFullyQualifiedNameWithColumnName(fullyQuelifiedName, ID_COLUMN_NAME)))); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, getSourceIdsColumnName()), JSONB.class).as( + hashAlias(getFullyQualifiedNameWithColumnName(fullyQuelifiedName, SOURCE_IDS)))); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, getClassifiersColumnName()), JSONB.class).as( + hashAlias(getFullyQualifiedNameWithColumnName(fullyQuelifiedName, CLASSIFIERS)))); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, getDecoratorsColumnName()), JSONB.class).as( + hashAlias(getFullyQualifiedNameWithColumnName(fullyQuelifiedName, DECORATORS)))); + return result; + } + + List getAttributeNames(); /** * Gets sourceIds column name as String @@ -61,4 +94,34 @@ public interface Persistable { * @return the String value of sourceIds column */ String getSourceIdsColumnName(); + + /** + * Gets classifiers column name as String + * + * @return the String value of classifiers column + */ + String getClassifiersColumnName(); + + /** + * Gets decorators column name as String + * + * @return the String value of decorators column + */ + String getDecoratorsColumnName(); + + String getName(); + + /** + * Gets the fully qualified name of the entity. Format - : + * + * @return the fully qualified name + */ + String getFullyQualifiedName(); + + /** + * Gets the category of the persistable. e.g.: "relationship", "entity" + * + * @return category as a String + */ + String getCategory(); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/PostgresSchemaLoader.java b/teiv/src/main/java/org/oran/smo/teiv/schema/PostgresSchemaLoader.java index 207a32c..a393a05 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/PostgresSchemaLoader.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/PostgresSchemaLoader.java @@ -27,7 +27,7 @@ import static org.oran.smo.teiv.utils.TiesConstants.TIES_MODEL; import static org.jooq.impl.DSL.field; import java.io.IOException; -import java.util.Collections; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,31 +40,32 @@ import org.jooq.Record3; import org.jooq.SelectConditionStep; import org.jooq.SelectJoinStep; import org.springframework.stereotype.Component; +import lombok.extern.slf4j.Slf4j; -import org.oran.smo.teiv.exception.TiesException; import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.Module; @Slf4j @Component public class PostgresSchemaLoader extends SchemaLoader { - private final DSLContext readDataDslContext; + private final DSLContext readWriteDataDslContext; private final ObjectMapper objectMapper; - public PostgresSchemaLoader(DSLContext readDataDslContext, ObjectMapper objectMapper) { - this.readDataDslContext = readDataDslContext; + public PostgresSchemaLoader(DSLContext readWriteDataDslContext, ObjectMapper objectMapper) { + this.readWriteDataDslContext = readWriteDataDslContext; this.objectMapper = objectMapper; } @Override protected void loadBidiDbNameMapper() { log.debug("Start loading bidirectional DB name mapper"); - SelectJoinStep records = readDataDslContext.select().from(String.format(TIES_MODEL, "hash_info")); + SelectJoinStep records = readWriteDataDslContext.select().from(String.format(TIES_MODEL, "hash_info")); Map hash = new HashMap<>(); Map reverseHash = new HashMap<>(); - records.forEach(record -> { - hash.put((String) record.get("name"), (String) record.get("hashedValue")); - reverseHash.put((String) record.get("hashedValue"), (String) record.get("name")); + records.forEach(entry -> { + hash.put((String) entry.get("name"), (String) entry.get("hashedValue")); + reverseHash.put((String) entry.get("hashedValue"), (String) entry.get("name")); }); BidiDbNameMapper.initialize(hash, reverseHash); log.debug("BidiDBNameMapper initialized successfully"); @@ -73,15 +74,16 @@ public class PostgresSchemaLoader extends SchemaLoader { @Override public void loadModules() throws SchemaLoaderException { log.debug("Start loading modules"); - SelectConditionStep moduleRecords = runMethodSafe(() -> readDataDslContext.select().from(String.format( - TIES_MODEL, "module_reference")).where(field("domain").isNotNull())); + SelectConditionStep moduleRecords = runMethodSafe(() -> readWriteDataDslContext.select().from(String.format( + TIES_MODEL, "module_reference")).where(field("name").isNotNull())); Map moduleMap = new HashMap<>(); for (Record moduleRecord : moduleRecords) { JSONB includedModules = (JSONB) moduleRecord.get("includedModules"); try { List modules = objectMapper.readValue(includedModules.data(), List.class); Module module = Module.builder().name((String) moduleRecord.get("name")).namespace((String) moduleRecord - .get("namespace")).domain((String) moduleRecord.get("domain")).includedModuleNames(modules).build(); + .get("namespace")).domain((String) moduleRecord.get("domain")).includedModuleNames(modules).content( + (String) moduleRecord.get("content")).build(); moduleMap.put(module.getName(), module); } catch (IOException e) { log.error("Exception occurred while retrieving included modules.", e); @@ -98,67 +100,75 @@ public class PostgresSchemaLoader extends SchemaLoader { @Override public void loadEntityTypes() { log.debug("Start loading entities"); - Map entityTypeMap = new HashMap<>(); - Map entityTypeBuilderMap = new HashMap<>(); - SelectJoinStep entityInfoRecords = runMethodSafe(() -> readDataDslContext.select().from(String.format( + List entityTypes = new ArrayList<>(); + final String tableName = "table_name"; + final String columnName = "column_name"; + SelectConditionStep> tableDetails = runMethodSafe(() -> readWriteDataDslContext + .select(field(tableName), field(columnName), field("udt_name")).from("information_schema.columns").where( + field("table_schema").equal(TIES_DATA_SCHEMA))); + + SelectJoinStep entityInfoRecords = runMethodSafe(() -> readWriteDataDslContext.select().from(String.format( TIES_MODEL, "entity_info"))); + entityInfoRecords.forEach(entityInfoRecord -> { String name = (String) entityInfoRecord.get("name"); - EntityType.EntityTypeBuilder entityTypeBuilder = EntityType.builder().name(name).module(SchemaRegistry - .getModuleByName((String) entityInfoRecord.get("moduleReferenceName"))); - entityTypeBuilderMap.put(name, entityTypeBuilder); - }); - //load attributes - String tableName = "table_name"; - String columnName = "column_name"; - SelectConditionStep> record3s = runMethodSafe(() -> readDataDslContext.select(field( - tableName), field(columnName), field("udt_name")).from("information_schema.columns").where(field( - "table_schema").equal(TIES_DATA_SCHEMA))); - entityTypeBuilderMap.keySet().forEach(entityName -> { + final String storedAt = (String) entityInfoRecord.get("storedAt"); + + //load attributes Map fields = new HashMap<>(); - record3s.stream().filter(record3 -> entityName.equals(getModelledName((String) record3.get(tableName)))) + tableDetails.stream().filter(record3 -> storedAt.equals(getModelledName((String) record3.get(tableName)))) .forEach(record3 -> { String colName = getModelledName((String) record3.get(columnName)); fields.put(colName, DataType.fromDbDataType((String) record3.get("udt_name"))); }); - entityTypeBuilderMap.get(entityName).fields(Collections.unmodifiableMap(fields)); - }); - for (var entityTypeBuilder : entityTypeBuilderMap.entrySet()) { - entityTypeMap.put(entityTypeBuilder.getKey(), entityTypeBuilder.getValue().build()); - } + final EntityType entityType = EntityType.builder().name(name).tableName(storedAt).fields(fields).module( + SchemaRegistry.getModuleByName((String) entityInfoRecord.get("moduleReferenceName"))).build(); + entityTypes.add(entityType); + }); - SchemaRegistry.initializeEntityTypes(entityTypeMap); + SchemaRegistry.initializeEntityTypes(entityTypes); log.debug("Entities initialized successfully"); } @Override - public void loadRelationTypes() { + public void loadRelationTypes() throws SchemaLoaderException { log.debug("Start loading relations"); - Map relationTypeMap = new HashMap<>(); - SelectJoinStep relationInfoResult = runMethodSafe(() -> readDataDslContext.select().from(String.format( + List relationTypes = new ArrayList<>(); + SelectJoinStep relationInfoResult = runMethodSafe(() -> readWriteDataDslContext.select().from(String.format( TIES_MODEL, "relationship_info"))); - relationInfoResult.forEach(result -> { + for (Record entry : relationInfoResult) { //build associations - Association aSideAssociation = Association.builder().name(((String) result.get("aSideAssociationName"))) - .minCardinality((long) (result.get("aSideMinCardinality"))).maxCardinality((long) (result.get( + Association aSideAssociation = Association.builder().name(((String) entry.get("aSideAssociationName"))) + .minCardinality((long) (entry.get("aSideMinCardinality"))).maxCardinality((long) (entry.get( "aSideMaxCardinality"))).build(); - Association bSideAssociation = Association.builder().name(((String) result.get("bSideAssociationName"))) - .minCardinality((long) (result.get("bSideMinCardinality"))).maxCardinality((long) (result.get( + Association bSideAssociation = Association.builder().name(((String) entry.get("bSideAssociationName"))) + .minCardinality((long) (entry.get("bSideMinCardinality"))).maxCardinality((long) (entry.get( "bSideMaxCardinality"))).build(); - RelationType relationType = RelationType.builder().name((String) result.get("name")).aSideAssociation( - aSideAssociation).aSide(SchemaRegistry.getEntityTypeByName((String) result.get("aSideMOType"))) - .bSideAssociation(bSideAssociation).bSide(SchemaRegistry.getEntityTypeByName((String) result.get( - "bSideMOType"))).relationshipStorageLocation(RelationshipDataLocation.valueOf((String) result - .get("relationshipDataLocation"))).connectsSameEntity((Boolean) (result.get( - "connectSameEntity"))).module(SchemaRegistry.getModuleByName((String) result - .get("moduleReferenceName"))).build(); - relationTypeMap.put(relationType.getName(), relationType); - }); + final EntityType aSide; + final EntityType bSide; + try { + aSide = SchemaRegistry.getEntityTypeByModuleAndName((String) entry.get("aSideModule"), (String) entry.get( + "aSideMOType")); + bSide = SchemaRegistry.getEntityTypeByModuleAndName((String) entry.get("bSideModule"), (String) entry.get( + "bSideMOType")); + } catch (SchemaRegistryException e) { + log.error("Error while getting aside / bSide entity type.", e); + throw new SchemaLoaderException(e.getMessage(), e.getCause()); + } + + RelationType relationType = RelationType.builder().name((String) entry.get("name")).aSideAssociation( + aSideAssociation).aSide(aSide).bSideAssociation(bSideAssociation).bSide(bSide) + .relationshipStorageLocation(RelationshipDataLocation.valueOf((String) entry.get( + "relationshipDataLocation"))).connectsSameEntity((Boolean) (entry.get("connectSameEntity"))) + .tableName((String) entry.get("storedAt")).module(SchemaRegistry.getModuleByName((String) entry.get( + "moduleReferenceName"))).build(); + relationTypes.add(relationType); + } //load registry - SchemaRegistry.initializeRelationTypes(relationTypeMap); + SchemaRegistry.initializeRelationTypes(relationTypes); log.debug("Relations initialized successfully"); } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/RelationType.java b/teiv/src/main/java/org/oran/smo/teiv/schema/RelationType.java index 6f64579..546bffe 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/RelationType.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/RelationType.java @@ -20,55 +20,53 @@ */ package org.oran.smo.teiv.schema; +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; import static org.oran.smo.teiv.schema.BidiDbNameMapper.getDbName; import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; +import static org.jooq.impl.DSL.field; +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; import static org.oran.smo.teiv.utils.TiesConstants.CONSUMER_DATA_PREFIX; +import static org.oran.smo.teiv.utils.TiesConstants.DECORATORS; import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; -import static org.oran.smo.teiv.utils.TiesConstants.REL_FK; import static org.oran.smo.teiv.utils.TiesConstants.SOURCE_IDS; import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.jooq.impl.DSL.field; +import org.oran.smo.teiv.exposure.spi.Module; import java.util.List; import java.util.Map; -import org.jooq.Field; -import org.jooq.JSONB; - import lombok.Builder; -import lombok.Getter; import lombok.Singular; -import lombok.ToString; +import lombok.Value; +import org.jooq.Field; -@Getter +@Value @Builder -@ToString public class RelationType implements Persistable { private static final String REL_ID_COL_PREFIX = "REL_ID_%s"; private static final String REL_FK_COL_PREFIX = "REL_FK_%s"; private static final String A_SIDE_PREFIX = "aSide_%s"; private static final String B_SIDE_PREFIX = "bSide_%s"; private static final String REL_SOURCE_IDS_COL_PREFIX = "REL_CD_sourceIds_%s"; - - private String name; - private Association aSideAssociation; - private EntityType aSide; - private Association bSideAssociation; - private EntityType bSide; + private static final String REL_CLASSIFIERS_COL_PREFIX = "REL_CD_classifiers_%s"; + private static final String REL_DECORATORS_COL_PREFIX = "REL_CD_decorators_%s"; + + String name; + Association aSideAssociation; + EntityType aSide; + Association bSideAssociation; + EntityType bSide; @Singular - private Map attributes; - private boolean connectsSameEntity; - private RelationshipDataLocation relationshipStorageLocation; - private Module module; + Map attributes; + boolean connectsSameEntity; + RelationshipDataLocation relationshipStorageLocation; + String tableName; + Module module; @Override public String getTableName() { - return switch (relationshipStorageLocation) { - case RELATION -> String.format(TIES_DATA, getDbName(name)); - case A_SIDE -> aSide.getTableName(); - case B_SIDE -> bSide.getTableName(); - }; + return String.format(TIES_DATA, getDbName(this.tableName)); } @Override @@ -81,17 +79,28 @@ public class RelationType implements Persistable { } @Override - public List getAttributeColumnsWithId() { + public String getIdColumnNameWithTableName() { + if (relationshipStorageLocation.equals(RELATION)) { + return getTableName() + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME); + } else { + return getTableName() + "." + String.format(QUOTED_STRING, getDbName(String.format(REL_ID_COL_PREFIX, name))); + } + } + + @Override + public Map getSpecificAttributeColumns(List attributes) { // attributes are yet to be supported for relations - return List.of(); + return Map.of(); } @Override public List getAllFieldsWithId() { - return List.of(field(getTableName() + "." + String.format(QUOTED_STRING, aSideColumnName())), field( - getTableName() + "." + String.format(QUOTED_STRING, bSideColumnName())), field(getTableName() + "." + String - .format(QUOTED_STRING, getIdColumnName())), field(getTableName() + "." + String.format( - QUOTED_STRING, getSourceIdsColumnName()), JSONB.class)); + List result = Persistable.super.getAllFieldsWithId(); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, aSideColumnName())).as(hashAlias( + getFullyQualifiedName() + ".aSide"))); + result.add(field(getTableName() + "." + String.format(QUOTED_STRING, bSideColumnName())).as(hashAlias( + getFullyQualifiedName() + ".bSide"))); + return result; } /** @@ -114,6 +123,24 @@ public class RelationType implements Persistable { } } + @Override + public String getClassifiersColumnName() { + if (relationshipStorageLocation.equals(RELATION)) { + return getDbName(CONSUMER_DATA_PREFIX + CLASSIFIERS); + } else { + return getDbName(String.format(REL_CLASSIFIERS_COL_PREFIX, name)); + } + } + + @Override + public String getDecoratorsColumnName() { + if (relationshipStorageLocation.equals(RELATION)) { + return getDbName(CONSUMER_DATA_PREFIX + DECORATORS); + } else { + return getDbName(String.format(REL_DECORATORS_COL_PREFIX, name)); + } + } + /** * Gets the aSide column name of the relation. * @@ -140,31 +167,9 @@ public class RelationType implements Persistable { }; } - /** - * Gets the fully qualified name of the entity. - * Format - : - * - * @return the fully qualified name - */ + @Override public String getFullyQualifiedName() { - return String.format("%s:%s", this.getModule().getName(), this.getName()); - } - - public String getTableNameWithoutSchema() { - return switch (relationshipStorageLocation) { - case RELATION -> name; - case A_SIDE -> aSide.getName(); - case B_SIDE -> bSide.getName(); - }; - } - - /** - * Gets the bSide relationship foreign key column name for the entity. - * - * @return the bSide foreign key column name, or null if not found. - */ - public String getReferenceColumnOnBSide() { - return getDbName(REL_FK + this.getBSideAssociation().getName()); + return String.format("%s:%s", module.getName(), name); } public String getNotStoringSideTableName() { @@ -199,4 +204,13 @@ public class RelationType implements Persistable { }; } + public List getAttributeNames() { + // attributes are yet to be supported for relations + return List.of(); + } + + @Override + public String getCategory() { + return "relationship"; + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistry.java b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistry.java index 0b387d8..19a3532 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistry.java +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistry.java @@ -20,31 +20,43 @@ */ package org.oran.smo.teiv.schema; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.ENTITY_NOT_FOUND_IN_DOMAIN; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.ENTITY_NOT_FOUND_IN_MODULE; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.RELATIONSHIP_NOT_FOUND_IN_DOMAIN; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.RELATIONSHIP_NOT_FOUND_IN_MODULE; + import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; import org.springframework.cache.annotation.Cacheable; - -import jakarta.annotation.Nullable; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import lombok.experimental.UtilityClass; +import jakarta.annotation.Nullable; + +import org.oran.smo.teiv.utils.TiesConstants; import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.Module; +@Slf4j @UtilityClass public class SchemaRegistry { @Getter private static Map moduleRegistry; - private static Map entityTypeRegistry; - private static Map relationTypeRegistry; + @Getter + private static List entityTypes; + @Getter + private static List relationTypes; //Modules section - /** * Initializes the modules. Once set cannot be overridden. * @@ -74,8 +86,8 @@ public class SchemaRegistry { * @return the {@link Module} */ public static Module getModuleByDomain(String domain) { - return moduleRegistry.values().stream().filter(module -> module.getDomain().equals(domain)).findFirst().orElseThrow( - () -> TiesException.unknownDomain(domain, getDomains())); + return moduleRegistry.values().stream().filter(module -> module.getDomain() != null && module.getDomain().equals( + domain)).findFirst().orElseThrow(() -> TiesException.unknownDomain(domain, getDomains())); } /** @@ -87,7 +99,7 @@ public class SchemaRegistry { */ public static List getIncludedDomains(String domain) { return getModuleByDomain(domain).getIncludedModuleNames().stream().map(moduleName -> getModuleByName(moduleName) - .getDomain()).toList(); + .getDomain()).filter(Objects::nonNull).toList(); } /** @@ -97,47 +109,95 @@ public class SchemaRegistry { */ @Cacheable("availableDomains") public static Set getDomains() { - return moduleRegistry.values().stream().map(Module::getDomain).collect(Collectors.toCollection(TreeSet::new)); + return moduleRegistry.values().stream().map(Module::getDomain).filter(Objects::nonNull).collect(Collectors + .toCollection(TreeSet::new)); } //Entities section + /** * Initializes the entity types. Once set cannot be overridden. * * @param entityTypes * - entity types */ - static void initializeEntityTypes(Map entityTypes) { - entityTypeRegistry = Collections.unmodifiableMap(entityTypes); + static void initializeEntityTypes(final List entityTypes) { + entityTypes.sort(Comparator.comparing(EntityType::getName)); + SchemaRegistry.entityTypes = Collections.unmodifiableList(entityTypes); } /** - * Gets the list of supported {@link EntityType} from the entity type registry. + * Gets all the supported entity names. * - * @return the list of {@link EntityType} + * @return the list of entity names */ - public static List getEntityTypes() { - return entityTypeRegistry.values().stream().toList(); + public static List getEntityNames() { + return entityTypes.stream().map(EntityType::getName).toList(); } /** - * Gets all the supported entity names from the entity type registry. + * Deprecated: Gets the {@link EntityType} by the given name. * - * @return the set of entity names + * @param name + * - entity name + * @return the {@link EntityType} + * @deprecated Use {@link #getEntityTypeByDomainAndName(String, String)} or + * {@link #getEntityTypeByModuleAndName(String, String)} instead. */ - public static Set getEntityNames() { - return entityTypeRegistry.keySet(); + @Nullable + @Deprecated(since = "Entity type should be retrieved by supplying the domain or module name") + public static EntityType getEntityTypeByName(String name) { + return entityTypes.stream().filter(entityType -> entityType.getName().equals(name)).findFirst().orElseGet(() -> { + log.warn("Unknown entity name: {}", name); + return null; + }); } /** - * Gets the {@link EntityType} by the given name. + * Gets the {@link EntityType} by the given module name and the entity type name. + * Since TIES supports TEIV as top level domain on the exposure side, there is possibility to return more than one + * EntityType for a given name + * with domain as TIEV. * - * @param name - * - entity name - * @return the {@link EntityType} + * @param domain + * - name of the domain + * @param entityTypeName + * - name of the entityType + * @return the list of {@link EntityType} + * @throws SchemaRegistryException + * if entity type is not found in the domain */ - public static EntityType getEntityTypeByName(String name) { - return entityTypeRegistry.get(name); + public static List getEntityTypeByDomainAndName(final String domain, final String entityTypeName) + throws SchemaRegistryException { + final List matchedEntityTypes = entityTypes.stream().filter(entityType -> entityType.getModule() + .getDomain().equals(domain) && entityType.getName().equals(entityTypeName)).toList(); + if (matchedEntityTypes.isEmpty()) { + log.warn("Domain: {} does not contain the entity type: {}", domain, entityTypeName); + throw new SchemaRegistryException(ENTITY_NOT_FOUND_IN_DOMAIN, String.format( + "Entity type: %s not found in domain: %s", entityTypeName, domain)); + } + return matchedEntityTypes; + } + + /** + * Gets the {@link EntityType} by the given module name and the entity type name. + * + * @param moduleName + * - name of the module + * @param entityTypeName + * - name of the entityType + * @return the list of {@link EntityType} + * @throws SchemaRegistryException + * if entity type is not found in the module + */ + public static EntityType getEntityTypeByModuleAndName(final String moduleName, final String entityTypeName) + throws SchemaRegistryException { + return entityTypes.stream().filter(entityType -> entityType.getModule().getName().equals(moduleName) && entityType + .getName().equals(entityTypeName)).findFirst().orElseThrow(() -> { + log.warn("Module: {} does not contain the entity type: {}", moduleName, entityTypeName); + return new SchemaRegistryException(ENTITY_NOT_FOUND_IN_MODULE, String.format( + "Entity type: %s not found in module: %s", entityTypeName, moduleName)); + }); } /** @@ -149,7 +209,7 @@ public class SchemaRegistry { */ public static List getEntityTypesByDomain(String domain) { List domains = getIncludedDomains(domain); - return entityTypeRegistry.values().stream().filter(entityType -> { + return entityTypes.stream().filter(entityType -> { String entityDomain = entityType.getModule().getDomain(); return domains.contains(entityDomain) || entityDomain.equals(domain); }).toList(); @@ -167,70 +227,90 @@ public class SchemaRegistry { return getEntityTypesByDomain(domain).stream().map(EntityType::getName).sorted().toList(); } - public static boolean isValidEntityName(String entityName) { - return entityTypeRegistry.containsKey(entityName); - } - - public static boolean hasDirectHopBetween(String entityName1, String entityName2) { - return hasDirectHopBetween(entityName1, entityName2, null); - } - - public static boolean hasDirectHopBetween(String entity1, String entity2, List relationships) { - return getRelationTypes().stream().anyMatch(relationType -> (relationships == null || relationships - .isEmpty() || relationships.contains(relationType.getName())) && ((relationType.getASide().getName().equals( - entity1) && relationType.getBSide().getName().equals(entity2)) || (relationType.getASide().getName() - .equals(entity2) && relationType.getBSide().getName().equals(entity1)))); - } + //Relations section /** - * Gets all managed objects with cmId attribute + * Initializes the relation types. Once set cannot be overridden. * - * @return a list of managed objects + * @param relationTypes + * - relation types */ - public static List getEntityTypesWithCmId() { - return entityTypeRegistry.values().stream().filter(entityType -> entityType.getFields().containsKey("cmId")) - .toList(); + static void initializeRelationTypes(final List relationTypes) { + relationTypes.sort(Comparator.comparing(RelationType::getName)); + SchemaRegistry.relationTypes = Collections.unmodifiableList(relationTypes); } - //Relations section /** - * Initializes the relation types. Once set cannot be overridden. + * Gets all the supported relation names. * - * @param relationTypes - * - relation types + * @return the list of relation names. */ - static void initializeRelationTypes(Map relationTypes) { - relationTypeRegistry = Collections.unmodifiableMap(relationTypes); + public static List getRelationNames() { + return relationTypes.stream().map(RelationType::getName).toList(); } /** - * Gets all the supported {@link RelationType} from the relation type registry. + * Deprecated: Gets the relation type by the given name. * - * @return the list of {@link RelationType} + * @param name + * - relation name + * @return the {@link RelationType} + * @deprecated Use {@link #getRelationTypeByDomainAndName(String, String)} or + * {@link #getRelationTypeByModuleAndName(String, String)} instead. */ - public static List getRelationTypes() { - return relationTypeRegistry.values().stream().toList(); + @Nullable + @Deprecated(since = "Relation type should be retrieved by supplying the domain or module name") + public static RelationType getRelationTypeByName(String name) { + return relationTypes.stream().filter(entityType -> entityType.getName().equals(name)).findFirst().orElseGet(() -> { + log.warn("Unknown relationship name: {}", name); + return null; + }); } /** - * Gets all the supported relation names from the relation type registry. + * Gets the {@link RelationType} (could be more than one when domain is TEIV) by the given module name and the relation + * type + * name. * - * @return the set of relation names. + * @param domain + * - name of the domain + * @param relationTypeName + * - name of the relation type + * @return the list of {@link RelationType} + * @throws SchemaRegistryException + * if relation type is not found in the domain */ - public static Set getRelationNames() { - return relationTypeRegistry.keySet(); + public static List getRelationTypeByDomainAndName(final String domain, final String relationTypeName) + throws SchemaRegistryException { + final List matchedRelationTypes = relationTypes.stream().filter(relationType -> relationType + .getModule().getDomain().equals(domain) && relationType.getName().equals(relationTypeName)).toList(); + if (matchedRelationTypes.isEmpty()) { + log.warn("Domain: {} does not contain the relation type: {}", domain, relationTypeName); + throw new SchemaRegistryException(RELATIONSHIP_NOT_FOUND_IN_DOMAIN, String.format( + "Relation type: %s not found in domain: %s", relationTypeName, domain)); + } + return matchedRelationTypes; } /** - * Gets the relation type by the given name. + * Gets the {@link RelationType} by the given module name and the relation type name. * - * @param relationName - * - relation relationName + * @param moduleName + * - name of the module + * @param relationTypeName + * - name of the relation type * @return the {@link RelationType} + * @throws SchemaRegistryException + * if relation type is not found in the module */ - @Nullable - public static RelationType getRelationTypeByName(String relationName) { - return relationTypeRegistry.get(relationName); + public static RelationType getRelationTypeByModuleAndName(final String moduleName, final String relationTypeName) + throws SchemaRegistryException { + return relationTypes.stream().filter(relationType -> relationType.getModule().getName().equals( + moduleName) && relationType.getName().equals(relationTypeName)).findFirst().orElseThrow(() -> { + log.warn("Module: {} does not contain the relation type: {}", moduleName, relationTypeName); + return new SchemaRegistryException(RELATIONSHIP_NOT_FOUND_IN_MODULE, String.format( + "Relation type: %s not found in module: %s", relationTypeName, moduleName)); + }); } /** @@ -241,7 +321,7 @@ public class SchemaRegistry { * @return the list of the {@link RelationType} */ public static List getRelationTypesByEntityName(final String entityName) { - return relationTypeRegistry.values().stream().filter(relationType -> relationType.getASide().getName().equals( + return relationTypes.stream().filter(relationType -> relationType.getASide().getName().equals( entityName) || relationType.getBSide().getName().equals(entityName)).toList(); } @@ -251,8 +331,7 @@ public class SchemaRegistry { public static List getAssociationNamesByEntityName(final String entityName) { return getRelationTypesByEntityName(entityName).stream().map(relationType -> { - RelationshipDataLocation relDataLocation = relationType.getRelationshipStorageLocation(); - if (relDataLocation.equals(RelationshipDataLocation.A_SIDE)) { + if (relationType.getASide().getName().equals(entityName)) { return relationType.getASideAssociation().getName(); } else { return relationType.getBSideAssociation().getName(); @@ -269,7 +348,7 @@ public class SchemaRegistry { */ public static List getRelationTypesByDomain(String domain) { List includedDomains = getIncludedDomains(domain); - return relationTypeRegistry.values().stream().filter(relationType -> { + return relationTypes.stream().filter(relationType -> { String relDomain = relationType.getModule().getDomain(); return includedDomains.contains(relDomain) || relDomain.equals(domain); }).toList(); @@ -287,34 +366,42 @@ public class SchemaRegistry { return getRelationTypesByDomain(domain).stream().map(RelationType::getName).sorted().toList(); } - public static boolean doesEntityContainsAttribute(String entityName, String attributeName) { - if (entityName == null) { - return false; - } - EntityType entityType = getEntityTypeByName(entityName); - if (entityType == null) { - return false; - } - return entityType.getAttributeNames().contains(attributeName); + /** + * Gets the relation names for a given entity by the given domain. + * + * @param entityName + * - entity name + * @param domain + * - name of the domain + * @return the list of relation names + */ + @Cacheable("relationTypesByDomain") + public static List getRelationNamesForEntityByDomain(final String entityName, final String domain) { + return getRelationTypesByDomain(domain).stream().filter(relationType -> relationType.getASide().getName().equals( + entityName) || relationType.getBSide().getName().equals(entityName)).toList(); } - public static List getRelationTypesBetweenEntities(String entity1, String entity2, - List relationships) { - return getRelationTypes().stream().filter(relationType -> (relationships == null || relationships - .isEmpty() || relationships.contains(relationType.getName())) && ((relationType.getASide().getName().equals( - entity1) && relationType.getBSide().getName().equals(entity2)) || (relationType.getBSide().getName() - .equals(entity1) && relationType.getASide().getName().equals(entity2)))).toList(); + public static List getAllRelationNamesByAssociationName(String associationName) { + return relationTypes.stream().filter(relationType -> relationType.getASideAssociation().getName().equals( + associationName) || relationType.getBSideAssociation().getName().equals(associationName)).toList(); } - public static Boolean isEntityPartOfRelationships(String entity, List relationships) { - return getRelationTypes().stream().anyMatch(relationType -> relationships.isEmpty() || (relationships.contains( - relationType.getName()) && (relationType.getASide().getName().equals(entity) || relationType.getBSide() - .getName().equals(entity)))); + public static String getReferenceColumnName(RelationType relationType) { + if (relationType.getRelationshipStorageLocation().equals(RelationshipDataLocation.A_SIDE)) { + return Objects.requireNonNull(relationType).getTableName() + "." + String.format(TiesConstants.QUOTED_STRING, + relationType.bSideColumnName()); + } else if (relationType.getRelationshipStorageLocation().equals(RelationshipDataLocation.B_SIDE)) { + return Objects.requireNonNull(relationType).getTableName() + "." + String.format(TiesConstants.QUOTED_STRING, + relationType.aSideColumnName()); + } + return Objects.requireNonNull(relationType).getTableName() + "." + relationType.getIdColumnName(); } - public static String getRelationNameByAssociationName(String associationName) { - return getRelationTypes().stream().filter(relationType -> relationType.getASideAssociation().getName().equals( - associationName) || relationType.getBSideAssociation().getName().equals(associationName)).map( - RelationType::getName).findFirst().get(); + public static EntityType getEntityTypeOnAssociationSide(RelationType relationType, String associationName) { + boolean isAssociationASide = relationType.getASideAssociation().getName().equals(associationName); + if (isAssociationASide) { + return relationType.getASide(); + } + return relationType.getBSide(); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryErrorCode.java b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryErrorCode.java new file mode 100644 index 0000000..384b693 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryErrorCode.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.schema; + +/** + * Enum representing error codes for the Schema Registry. + */ +public enum SchemaRegistryErrorCode { + ENTITY_NOT_FOUND_IN_DOMAIN, + ENTITY_NOT_FOUND_IN_MODULE, + RELATIONSHIP_NOT_FOUND_IN_DOMAIN, + RELATIONSHIP_NOT_FOUND_IN_MODULE +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryException.java b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryException.java new file mode 100644 index 0000000..bd4f4d8 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/SchemaRegistryException.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.schema; + +import lombok.Getter; + +/** + * Custom exception class for schema registry errors. + */ +@Getter +public class SchemaRegistryException extends Exception { + private final SchemaRegistryErrorCode errorCode; + + public SchemaRegistryException(final SchemaRegistryErrorCode errorCode, final String message) { + super(message); + this.errorCode = errorCode; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/schema/YangDataTypes.java b/teiv/src/main/java/org/oran/smo/teiv/schema/YangDataTypes.java new file mode 100644 index 0000000..df7e0dd --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/schema/YangDataTypes.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.schema; + +import java.util.Locale; + +public enum YangDataTypes { + STRING, + BOOLEAN, + NUMERIC; + + public static YangDataTypes fromYangDataType(final String yangDatatype) { + return switch (yangDatatype.toUpperCase(Locale.US)) { + case "TEXT" -> STRING; + case "BOOLEAN" -> BOOLEAN; + case "INT", "DOUBLE" -> NUMERIC; + default -> throw new IllegalStateException("Unexpected value: " + yangDatatype.toUpperCase(Locale.US)); + }; + } + + public static YangDataTypes fromRequestDataType(final Class requestDatatype) { + return switch (requestDatatype.getSimpleName()) { + case "String" -> STRING; + case "Integer", "Double" -> NUMERIC; + case "Boolean" -> BOOLEAN; + default -> throw new IllegalStateException("Unexpected value: " + requestDatatype); + }; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/SchemaCleanUpService.java b/teiv/src/main/java/org/oran/smo/teiv/service/SchemaCleanUpService.java new file mode 100644 index 0000000..3396dc8 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/service/SchemaCleanUpService.java @@ -0,0 +1,205 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.service; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exposure.consumerdata.model.Classifiers; +import org.oran.smo.teiv.exposure.consumerdata.model.Decorators; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteDecoratorsOperation; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.exposure.spi.DataRepository; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataOperationRegistry; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.service.models.OperationResult; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class SchemaCleanUpService { + private final ModelRepository modelRepository; + private final DataRepository dataRepository; + private final ConsumerDataOperationRegistry consumerDataOperationRegistry; + private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + @Value("${spring.caching.consumer-data-ttl-ms}") + private long timeToLeave; + + @Async + public void cleanUpModule(final String name) { + + boolean cleanUpInProgress = true; + long waitInLoop = timeToLeave; + + while (cleanUpInProgress) { + try { + waitInLoop = (long) (1.2 * waitInLoop); + ScheduledFuture resp = executor.schedule(() -> innerCleanUp(name), waitInLoop, + TimeUnit.MILLISECONDS); + cleanUpInProgress = resp.get(); + } catch (InterruptedException ex) { + log.error("InterruptedException during [{}] schema deletion: {}", name, ex.getMessage()); + Thread.currentThread().interrupt(); + } catch (Exception ex) { + log.error("Exception during [{}] schema deletion: {}", name, ex.getMessage(), ex); + } + } + + modelRepository.deleteModuleByName(name); + } + + private boolean innerCleanUp(final String schemaName) { + log.info("Start cleanup for {} schema", schemaName); + + boolean shouldRerun = false; + + final Set decorators = dataRepository.getDecoratorsForSchema(schemaName); + final Set classifiers = dataRepository.getClassifiersForSchema(schemaName); + + final List entityTypes = new ArrayList<>(SchemaRegistry.getEntityTypes()); + final List relationTypes = new ArrayList<>(SchemaRegistry.getRelationTypes()); + + Collections.shuffle(entityTypes); + Collections.shuffle(relationTypes); + + for (EntityType e : entityTypes) { + try { + deleteClassifiersFromEntity(e, classifiers); + } catch (Exception ex) { + shouldRerun = true; + log.error("Exception during [{}] schema deletion from entity type: {} : {}", schemaName, e, ex.getMessage(), + ex); + } + try { + deleteDecoratorsFromEntity(e, decorators); + } catch (Exception ex) { + shouldRerun = true; + log.error("Exception during [{}] schema deletion from entity type: {} : {}", schemaName, e, ex.getMessage(), + ex); + } + } + for (RelationType r : relationTypes) { + try { + deleteClassifiersFromRelationship(r, classifiers); + } catch (Exception ex) { + shouldRerun = true; + log.error("Exception during [{}] schema deletion from relationship type: {} : {}", schemaName, r, ex + .getMessage(), ex); + } + try { + deleteDecoratorsFromRelationship(r, decorators); + } catch (Exception ex) { + shouldRerun = true; + log.error("Exception during [{}] schema deletion from relationship type: {} : {}", schemaName, r, ex + .getMessage(), ex); + } + } + + log.info("Cleanup for {} schema has been finished", schemaName); + + return shouldRerun; + } + + private void deleteClassifiersFromEntity(final EntityType entityType, final Set classifiers) { + Set idsForDeletion; + do { + idsForDeletion = new LinkedHashSet<>(dataRepository.getEntityIdsForClassifierDeletion(entityType, classifiers)); + + final DeleteClassifiersOperation deleteClassifiersOperation = (DeleteClassifiersOperation) consumerDataOperationRegistry + .getClassifiersOperation(OranTeivClassifier.OperationEnum.DELETE); + + List results = deleteClassifiersOperation.delete(new Classifiers(new ArrayList<>(classifiers), + new ArrayList<>(idsForDeletion), new ArrayList<>()), entityType); + } while (!idsForDeletion.isEmpty()); + } + + private void deleteDecoratorsFromEntity(final EntityType entityType, final Set decorators) { + Set idsForDeletion; + do { + idsForDeletion = new LinkedHashSet<>(dataRepository.getEntityIdsForDecoratorDeletion(entityType, decorators)); + + final Map decoratorsMap = new HashMap<>(); + for (String decorator : decorators) { + decoratorsMap.put(decorator, ""); + } + + final DeleteDecoratorsOperation deleteDecoratorsOperation = (DeleteDecoratorsOperation) consumerDataOperationRegistry + .getDecoratorsOperation(OranTeivDecorator.OperationEnum.DELETE); + + List results = deleteDecoratorsOperation.delete(new Decorators(decoratorsMap, new ArrayList<>( + idsForDeletion), new ArrayList<>()), entityType); + } while (!idsForDeletion.isEmpty()); + } + + private void deleteClassifiersFromRelationship(final RelationType relationType, final Set classifiers) { + Set idsForDeletion; + do { + idsForDeletion = new LinkedHashSet<>(dataRepository.getRelationshipIdsForClassifierDeletion(relationType, + classifiers)); + + final DeleteClassifiersOperation deleteClassifiersOperation = (DeleteClassifiersOperation) consumerDataOperationRegistry + .getClassifiersOperation(OranTeivClassifier.OperationEnum.DELETE); + + List results = deleteClassifiersOperation.delete(new Classifiers(new ArrayList<>(classifiers), + new ArrayList<>(), new ArrayList<>(idsForDeletion)), relationType); + } while (!idsForDeletion.isEmpty()); + } + + private void deleteDecoratorsFromRelationship(final RelationType relationType, final Set decorators) { + Set idsForDeletion; + do { + idsForDeletion = new LinkedHashSet<>(dataRepository.getRelationshipIdsForDecoratorDeletion(relationType, + decorators)); + + final Map decoratorsMap = new HashMap<>(); + for (String decorator : decorators) { + decoratorsMap.put(decorator, ""); + } + + final DeleteDecoratorsOperation deleteDecoratorsOperation = (DeleteDecoratorsOperation) consumerDataOperationRegistry + .getDecoratorsOperation(OranTeivDecorator.OperationEnum.DELETE); + + List results = deleteDecoratorsOperation.delete(new Decorators(decoratorsMap, + new ArrayList<>(), new ArrayList<>(idsForDeletion)), relationType); + } while (!idsForDeletion.isEmpty()); + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbOperations.java b/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbOperations.java index bb636ae..2e94883 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbOperations.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbOperations.java @@ -21,7 +21,6 @@ package org.oran.smo.teiv.service; import static org.oran.smo.teiv.schema.BidiDbNameMapper.getDbName; -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; import static org.oran.smo.teiv.utils.TiesConstants.FOREIGN_KEY_VIOLATION_ERROR_CODE; @@ -44,6 +43,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.stream.Collectors; +import org.jooq.Field; import org.oran.smo.teiv.exception.IllegalManyToManyRelationshipUpdateException; import org.oran.smo.teiv.exception.IllegalOneToManyRelationshipUpdateException; import org.jooq.Configuration; @@ -51,6 +51,7 @@ import org.jooq.Condition; import org.jooq.DSLContext; import org.jooq.JSON; import org.jooq.exception.DataAccessException; +import org.oran.smo.teiv.utils.JooqTypeConverter; import org.springframework.stereotype.Component; import lombok.AllArgsConstructor; @@ -72,7 +73,6 @@ import org.oran.smo.teiv.service.cloudevent.data.Entity; import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; import org.oran.smo.teiv.service.cloudevent.data.Relationship; -import org.oran.smo.teiv.utils.ConvertToJooqTypeUtil; import org.oran.smo.teiv.utils.TiesConstants; import org.oran.smo.teiv.utils.schema.Geography; @@ -89,8 +89,7 @@ public class TiesDbOperations { /** * Insert or update a row in the given table. *

- * Note: Free version of Jooq doesn't support spatial types like Geography. Instead of that the OTHER type is used. - * Instead of that the OTHER type is used. + * Note: Free version of Jooq doesn't support spatial types like Geography. Instead of that the OTHER type is used *

* * @param context @@ -98,26 +97,30 @@ public class TiesDbOperations { * @param tableName * Name of the database table to use. * @param values - * A map of column name and value pairs. The value is converted - * to the corresponding Postgres type based on the + * A map of column name and value pairs. The value is converted to the corresponding Postgres type based on the * dynamic type of the value. For - * example: <"column1", 5L> means that the value 5 should be - * inserted to the column1 as a BIGINT. + * example: <"column1", 5L> means that the value 5 should be inserted to the column1 as a BIGINT. * @return The number of modified rows. */ public int merge(DSLContext context, String tableName, Map values) { - Map valuesToMerge = new HashMap<>(values.size()); + Map valuesToInsert = new HashMap<>(values.size()); values.forEach((key, value) -> { if (value instanceof Geography geographyValue) { - valuesToMerge.put(key, field("'" + geographyValue + "'", OTHER)); + valuesToInsert.put(key, field("'" + geographyValue + "'", OTHER)); } else { - valuesToMerge.put(key, value); + valuesToInsert.put(key, value); } }); - - return context.insertInto(table(tableName)).set(valuesToMerge).onConflict(field(ID_COLUMN_NAME)).doUpdate().set( - valuesToMerge).execute(); + Map valuesToUpdate = new HashMap<>(valuesToInsert); + valuesToUpdate.remove(ID_COLUMN_NAME); + if (valuesToUpdate.isEmpty()) { + return context.insertInto(table(tableName)).set(valuesToInsert).onConflict(field(ID_COLUMN_NAME)).doNothing() + .execute(); + } else { + return context.insertInto(table(tableName)).set(valuesToInsert).onConflict(field(ID_COLUMN_NAME)).doUpdate() + .set(valuesToUpdate).execute(); + } } public List deleteEntity(DSLContext context, EntityType entityType, String entityId) { @@ -127,7 +130,7 @@ public class TiesDbOperations { int affectedRows = context.delete(table(entityType.getTableName())).where(field(ID_COLUMN_NAME).eq(entityId)) .execute(); if (affectedRows > 0) { - result.add(new OperationResult(entityId, entityType.getName(), null)); + result.add(OperationResult.createEntityOperationResult(entityId, entityType.getName())); } return result; } @@ -141,14 +144,14 @@ public class TiesDbOperations { List relationshipList = context.select(field(String.format(QUOTED_STRING, relationType .getIdColumnName()), String.class)).from(table(relationType.getTableName())).where(field(String.format( QUOTED_STRING, manySideEntityIdColumn)).eq(manySideEntityId)).forUpdate().fetchInto(String.class) - .stream().filter(Objects::nonNull).map(id -> new OperationResult(id, extractTypeFromColumn( - oneSideEntityIdColumn), null)).collect(Collectors.toList()); + .stream().filter(Objects::nonNull).map(id -> OperationResult.createRelationshipOperationResult(id, + relationType.getName())).collect(Collectors.toList()); if (relationshipList.isEmpty()) { return relationshipList; } else { int updateResult = context.update(table(relationType.getTableName())).setNull(field(String.format(QUOTED_STRING, relationType.getIdColumnName()))).setNull(field(String.format(QUOTED_STRING, oneSideEntityIdColumn))) - .set(field(String.format(QUOTED_STRING, relationType.getSourceIdsColumnName())), ConvertToJooqTypeUtil + .set(field(String.format(QUOTED_STRING, relationType.getSourceIdsColumnName())), JooqTypeConverter .toJsonb(List.of())).where(field(String.format(QUOTED_STRING, manySideEntityIdColumn)).eq( manySideEntityId)).execute(); return updateResult > 0 ? relationshipList : List.of(); @@ -164,31 +167,31 @@ public class TiesDbOperations { int affectedRows = context.update(table(relationType.getTableName())).setNull(field(String.format(QUOTED_STRING, relationType.getIdColumnName()))).setNull(field(String.format(QUOTED_STRING, oneSideEntityIdColumn))).set( - field(String.format(QUOTED_STRING, relationType.getSourceIdsColumnName())), ConvertToJooqTypeUtil + field(String.format(QUOTED_STRING, relationType.getSourceIdsColumnName())), JooqTypeConverter .toJsonb(List.of())).where(field(String.format(QUOTED_STRING, relationType .getIdColumnName())).eq(relationshipId)).execute(); return affectedRows > 0 ? - Optional.of(new OperationResult(relationshipId, extractTypeFromColumn(oneSideEntityIdColumn), null)) : + Optional.of(OperationResult.createRelationshipOperationResult(relationshipId, relationType.getName())) : Optional.empty(); } - public List deleteManyToManyRelationByEntityId(DSLContext context, String tableName, String entityId, - String aSideColumnName, String bSideColumnName) { - List deletedIds = context.delete(table(tableName)).where(field(String.format(QUOTED_STRING, - aSideColumnName)).eq(entityId).or(field(String.format(QUOTED_STRING, bSideColumnName)).eq(entityId))) - .returning(field(TiesConstants.ID_COLUMN_NAME)).fetch().getValues(field(TiesConstants.ID_COLUMN_NAME), - String.class); + public List deleteManyToManyRelationByEntityId(DSLContext context, RelationType relationType, + String entityId, String aSideColumnName, String bSideColumnName) { + List deletedIds = context.delete(table((relationType.getTableName()))).where(field(String.format( + QUOTED_STRING, aSideColumnName)).eq(entityId).or(field(String.format(QUOTED_STRING, bSideColumnName)).eq( + entityId))).returning(field(TiesConstants.ID_COLUMN_NAME)).fetch().getValues(field( + TiesConstants.ID_COLUMN_NAME), String.class); - return deletedIds.stream().map(id -> new OperationResult(id, extractTypeFromTable(tableName), null)).collect( - Collectors.toList()); + return deletedIds.stream().map(id -> OperationResult.createRelationshipOperationResult(id, relationType.getName())) + .collect(Collectors.toList()); } - public Optional deleteManyToManyRelationByRelationId(DSLContext context, String tableName, + public Optional deleteManyToManyRelationByRelationId(DSLContext context, RelationType relationType, String relationshipId) { - - int affectedRows = context.delete(table(tableName)).where(field(ID_COLUMN_NAME).eq(relationshipId)).execute(); + int affectedRows = context.delete(table(relationType.getTableName())).where(field(ID_COLUMN_NAME).eq( + relationshipId)).execute(); return affectedRows > 0 ? - Optional.of(new OperationResult(relationshipId, extractTypeFromTable(tableName), null)) : + Optional.of(OperationResult.createRelationshipOperationResult(relationshipId, relationType.getName())) : Optional.empty(); } @@ -209,18 +212,11 @@ public class TiesDbOperations { return results; } - public List selectByCmHandle(DSLContext context, String tableName, String cmHandle) { - String path = "$.** ? (@.cmHandle == \"" + cmHandle + "\")"; - return context.select(field(String.format(QUOTED_STRING, "id"), String.class)).from(tableName).where(jsonExists( - field(String.format(QUOTED_STRING, "cmId"), JSON.class), path)).fetch().getValues(field(String.format( - QUOTED_STRING, "id"), String.class)); - } - public List selectByCmHandleFormSourceIds(DSLContext context, String tableName, String cmHandle) { - String path = String.format("$[*] ? (@ == \"urn:cmHandle:/%s\")", cmHandle); + String path = String.format("$[*] ? (@ == \"urn:cmHandle:%s\")", cmHandle); return context.select(field(String.format(QUOTED_STRING, "id"), String.class)).from(tableName).where(jsonExists( - field(String.format(QUOTED_STRING, "CD_sourceIds"), JSON.class), path)).fetch().getValues(field(String - .format(QUOTED_STRING, "id"), String.class)); + field(String.format(QUOTED_STRING, "CD_sourceIds"), JSON.class), path)).orderBy(field(String.format( + QUOTED_STRING, "id"))).fetch().getValues(field(String.format(QUOTED_STRING, "id"), String.class)); } private Consumer getEntityOperation(Entity entity, List results) @@ -235,22 +231,22 @@ public class TiesDbOperations { "Received field: %s isn't a valid field of entity type: %s", entry.getKey(), entity.getType())); } switch (dataType) { - case GEOGRAPHIC -> dbMap.put(getDbName(entry.getKey()), ConvertToJooqTypeUtil.toGeography(entry - .getValue())); - case CONTAINER -> dbMap.put(getDbName(entry.getKey()), ConvertToJooqTypeUtil.toJsonb(entry.getValue())); - case PRIMITIVE, DECIMAL, BIGINT -> dbMap.put(getDbName(entry.getKey()), entry.getValue()); + case GEOGRAPHIC -> dbMap.put(getDbName(entry.getKey()), JooqTypeConverter.toGeography(entry.getValue())); + case CONTAINER -> dbMap.put(getDbName(entry.getKey()), JooqTypeConverter.toJsonb(entry.getValue())); + case PRIMITIVE, DECIMAL, INTEGER, BIGINT -> dbMap.put(getDbName(entry.getKey()), entry.getValue()); } } dbMap.put(ID_COLUMN_NAME, entity.getId()); if (entity.getSourceIds() != null) { - dbMap.put(entityType.getSourceIdsColumnName(), ConvertToJooqTypeUtil.toJsonb(entity.getSourceIds())); + dbMap.put(entityType.getSourceIdsColumnName(), JooqTypeConverter.toJsonb(entity.getSourceIds())); } return dslContext -> { int affectedRows = merge(dslContext, entityType.getTableName(), dbMap); if (affectedRows > 0) { dbMap.remove(ID_COLUMN_NAME); dbMap.remove(entityType.getSourceIdsColumnName()); - results.add(new OperationResult(entity.getId(), entity.getType(), dbMap)); + results.add(OperationResult.createEntityOperationResult(entity.getId(), entity.getType(), dbMap, entity + .getSourceIds())); } }; } @@ -265,7 +261,7 @@ public class TiesDbOperations { dbMap.put(relationType.aSideColumnName(), relationship.getASide()); dbMap.put(relationType.bSideColumnName(), relationship.getBSide()); if (relationship.getSourceIds() != null) { - dbMap.put(relationType.getSourceIdsColumnName(), ConvertToJooqTypeUtil.toJsonb(relationship.getSourceIds())); + dbMap.put(relationType.getSourceIdsColumnName(), JooqTypeConverter.toJsonb(relationship.getSourceIds())); } if (relationshipDataLocation == RELATION) { @@ -294,16 +290,17 @@ public class TiesDbOperations { List results, RelationType relationType, Map dbMap) { AtomicBoolean isManySideEntityMissingAtTheBeginning = new AtomicBoolean(false); try { - dslContext.dsl().transaction((Configuration nested) -> updateOneToManyRelationship(nested.dsl(), relationship, - relationType, dbMap).ifPresentOrElse(results::add, () -> { - Record manySideRow = selectByIdForUpdate(relationType.getTableName(), ID_COLUMN_NAME, relationship - .getStoringSideEntityId(), dslContext); + dslContext.dsl().transaction((Configuration nested) -> updateRelationshipInEntityTable(nested.dsl(), + relationship, relationType, dbMap).ifPresentOrElse(results::add, () -> { + Record manySideRow = selectColumnsByIdForUpdate(List.of(relationType.aSideColumnName(), relationType + .bSideColumnName(), relationType.getIdColumnName()), relationType.getTableName(), + ID_COLUMN_NAME, relationship.getStoringSideEntityId(), dslContext); if (manySideRow == null) { isManySideEntityMissingAtTheBeginning.set(true); createMissingStoringSideEntity(dslContext, relationship, relationType); addEntityToOperationResults(results, relationship.getStoringSideEntityId(), relationType .getStoringSideEntityType()); - updateOneToManyRelationship(dslContext, relationship, relationType, dbMap).ifPresentOrElse( + updateRelationshipInEntityTable(dslContext, relationship, relationType, dbMap).ifPresentOrElse( results::add, () -> { throw new IllegalOneToManyRelationshipUpdateException(relationship, true); }); @@ -323,7 +320,7 @@ public class TiesDbOperations { createMissingNotStoringSideEntity(dslContext, relationship, relationType); addEntityToOperationResults(results, relationship.getNotStoringSideEntityId(), relationType .getNotStoringSideEntityType()); - updateOneToManyRelationship(dslContext, relationship, relationType, dbMap).ifPresentOrElse(results::add, + updateRelationshipInEntityTable(dslContext, relationship, relationType, dbMap).ifPresentOrElse(results::add, () -> { throw new IllegalOneToManyRelationshipUpdateException(relationship, false); }); @@ -333,18 +330,19 @@ public class TiesDbOperations { } } - private Optional updateOneToManyRelationship(DSLContext dslContext, Relationship relationship, + private Optional updateRelationshipInEntityTable(DSLContext dslContext, Relationship relationship, RelationType relationType, Map values) { Condition condition = field(ID_COLUMN_NAME).eq(relationship.getStoringSideEntityId()).and(field(name(relationType .getIdColumnName())).isNull().or(field(name(relationType.getIdColumnName())).eq(relationship.getId()).and( field(name(relationType.getNotStoringSideEntityIdColumnNameInStoringSideTable())).eq(relationship .getNotStoringSideEntityId())))); - - int numberOfUpdatedRows = dslContext.update(table(relationType.getTableName())).set(values).where(condition) + Map valuesToUpdate = new HashMap<>(values); + valuesToUpdate.remove(ID_COLUMN_NAME); + int numberOfUpdatedRows = dslContext.update(table(relationType.getTableName())).set(valuesToUpdate).where(condition) .execute(); return numberOfUpdatedRows != 0 ? - Optional.of(OperationResult.createFromRelationship(relationship)) : + Optional.of(OperationResult.createRelationshipOperationResult(relationship)) : Optional.empty(); } @@ -366,14 +364,17 @@ public class TiesDbOperations { } private void mergeManyToManyRelationship(DSLContext dslContext, Relationship relationship, - List results, RelationType relationType, Map dbMap) { - int affectedRows = dslContext.insertInto(table(relationType.getTableName())).set(dbMap).onConflict(field( - relationType.getIdColumnName())).doUpdate().set(dbMap).where(field(relationType.getTableName() + "." + name( + List results, RelationType relationType, Map valuesToInsert) { + String primaryKeyColumn = relationType.getIdColumnName(); + Map valuesToUpdate = new HashMap<>(valuesToInsert); + valuesToUpdate.remove(primaryKeyColumn); + int affectedRows = dslContext.insertInto(table(relationType.getTableName())).set(valuesToInsert).onConflict(field( + primaryKeyColumn)).doUpdate().set(valuesToUpdate).where(field(relationType.getTableName() + "." + name( relationType.aSideColumnName())).eq(relationship.getASide()).and(field(relationType .getTableName() + "." + name(relationType.bSideColumnName())).eq(relationship.getBSide()))) .execute(); if (affectedRows > 0) { - results.add(OperationResult.createFromRelationship(relationship)); + results.add(OperationResult.createRelationshipOperationResult(relationship)); } else { throw new IllegalManyToManyRelationshipUpdateException(relationship); } @@ -387,10 +388,10 @@ public class TiesDbOperations { String bSideId = relationship.getBSide(); if (createMissingEntity(aSideTableName, ID_COLUMN_NAME, aSideId, dslContext) == 1) { - results.add(new OperationResult(aSideId, relationType.getASide().getName(), new HashMap<>())); + results.add(OperationResult.createEntityOperationResult(aSideId, relationType.getASide().getName())); } if (createMissingEntity(bSideTableName, ID_COLUMN_NAME, bSideId, dslContext) == 1) { - results.add(new OperationResult(bSideId, relationType.getBSide().getName(), new HashMap<>())); + results.add(OperationResult.createEntityOperationResult(bSideId, relationType.getBSide().getName())); } } @@ -404,8 +405,8 @@ public class TiesDbOperations { relationType.aSideColumnName() : relationType.bSideColumnName(); if (relationType.getRelationshipStorageLocation() == RELATION) { - deletedIds.addAll(deleteManyToManyRelationByEntityId(dslContext, relationType.getTableName(), entityId, - relationType.aSideColumnName(), relationType.bSideColumnName())); + deletedIds.addAll(deleteManyToManyRelationByEntityId(dslContext, relationType, entityId, relationType + .aSideColumnName(), relationType.bSideColumnName())); } else { deletedIds.addAll(deleteRelationshipByManySideEntityId(dslContext, entityId, columnNameForWhereCondition, @@ -432,25 +433,18 @@ public class TiesDbOperations { createMissingEntity(relationType.getTableName(), ID_COLUMN_NAME, relationship.getStoringSideEntityId(), dslContext); } - private Record selectByIdForUpdate(String tableName, String idFieldName, String manySideEntityId, - DSLContext dslContext) { - return dslContext.selectFrom(table(tableName)).where(field(idFieldName).eq(manySideEntityId)).forUpdate() + private Record selectColumnsByIdForUpdate(List columnNames, String tableName, String idFieldName, + String manySideEntityId, DSLContext dslContext) { + List> fields = columnNames.stream().map(n -> field(name(n))).toList(); + return dslContext.select(fields).from(table(tableName)).where(field(idFieldName).eq(manySideEntityId)).forUpdate() .fetchOne(); } private void addEntityToOperationResults(List results, String entityId, String entityType) { - OperationResult result = new OperationResult(entityId, entityType, Map.of()); + OperationResult result = OperationResult.createEntityOperationResult(entityId, entityType); if (!results.contains(result)) { results.add(result); } } - private String extractTypeFromTable(String tableName) { - return tableName.split("\\\"")[1]; - } - - private String extractTypeFromColumn(String oneSideEntityIdColumn) { - String associationName = getModelledName(oneSideEntityIdColumn).replace("REL_FK_", ""); - return SchemaRegistry.getRelationNameByAssociationName(associationName); - } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbService.java b/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbService.java index ebc4750..82e9c82 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbService.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/TiesDbService.java @@ -20,15 +20,11 @@ */ package org.oran.smo.teiv.service; -import static org.jooq.impl.DSL.table; - import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; import org.jooq.DSLContext; -import org.jooq.Record; -import org.jooq.Result; import org.jooq.impl.DSL; import org.springframework.retry.support.RetryTemplate; import org.springframework.stereotype.Service; @@ -67,10 +63,6 @@ public class TiesDbService { }); } - protected Result selectAllRowsFromTable(final String tableName) { - return runMethodSafe(() -> readDataDslContext.selectFrom(table(tableName)).fetch()); - } - private T runMethodSafe(Supplier supp) { try { return supp.get(); diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/CloudEventParser.java b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/CloudEventParser.java index 45ce58e..97fcfbe 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/CloudEventParser.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/CloudEventParser.java @@ -31,6 +31,11 @@ import io.cloudevents.CloudEvent; import io.cloudevents.CloudEventData; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.exception.InvalidRelationshipException; +import org.oran.smo.teiv.exception.YangModelException; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.utils.TiesConstants; +import org.oran.smo.yangtools.parser.data.dom.YangDataDomNode; import org.springframework.stereotype.Component; import org.oran.smo.yangtools.parser.data.dom.YangDataDomDocumentRoot; import org.oran.smo.teiv.service.cloudevent.data.Entity; @@ -38,12 +43,15 @@ import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; import org.oran.smo.teiv.service.cloudevent.data.Relationship; import org.oran.smo.teiv.utils.YangParser; +import static org.oran.smo.teiv.utils.CloudEventUtil.hasInvalidCharacter; + @Slf4j @Component @RequiredArgsConstructor public class CloudEventParser { private static final String ENTITIES = "entities"; private static final String RELATIONSHIPS = "relationships"; + private static final String ILLEGAL_CHARACTER_FOUND = "Illegal character found in relationship %s: %s"; private final ObjectMapper objectMapper; public ParsedCloudEventData getCloudEventData(CloudEvent cloudEvent) { @@ -55,6 +63,10 @@ public class CloudEventParser { log.error("Cannot parse CloudEvent data: ", e); return null; } + + boolean areSidesMandatory = !cloudEvent.getType().split("\\.")[1].equals( + TiesConstants.CLOUD_EVENT_WITH_TYPE_DELETE); + final List entities = new ArrayList<>(); Boolean parsedEntities = processEntities(eventPayload, entities); if (parsedEntities.equals(Boolean.FALSE)) { @@ -62,7 +74,7 @@ public class CloudEventParser { } final List relationships = new ArrayList<>(); - Boolean parsedRelationship = processRelationships(eventPayload, relationships); + Boolean parsedRelationship = processRelationships(eventPayload, relationships, areSidesMandatory); if (parsedRelationship.equals(Boolean.FALSE)) { return null; } @@ -74,51 +86,64 @@ public class CloudEventParser { JsonNode entitiesJsonNode = eventPayload.get(ENTITIES); if (entitiesJsonNode != null && (entitiesJsonNode.getNodeType() == JsonNodeType.ARRAY)) { for (JsonNode entityNode : entitiesJsonNode) { - try { - parseEntities(entityNode, entities); - } catch (IOException e) { - log.error("Cannot parse entity: " + entitiesJsonNode, e); + if (!parseEntities(entities, entitiesJsonNode, entityNode)) { return false; } } } - //TODO: Remove support for old format DnR events when RTA has been updated. - if (entitiesJsonNode != null && (entitiesJsonNode.getNodeType() == JsonNodeType.OBJECT)) { - try { - parseEntities(entitiesJsonNode, entities); - } catch (IOException e) { - log.error("Cannot parse entity: " + entitiesJsonNode, e); - return false; - } + return true; + } + + private boolean parseEntities(List entities, JsonNode entitiesJsonNode, JsonNode entityNode) { + try { + parseEntities(entityNode, entities); + } catch (IOException | YangModelException e) { + log.error("Cannot parse entity: " + entitiesJsonNode, e); + return false; } return true; } - private Boolean processRelationships(JsonNode eventPayload, List relationships) { + private Boolean processRelationships(JsonNode eventPayload, List relationships, + boolean areSidesMandatory) { JsonNode relationshipJsonNode = eventPayload.get(RELATIONSHIPS); if (relationshipJsonNode != null && (relationshipJsonNode.getNodeType() == JsonNodeType.ARRAY)) { - for (JsonNode relationshipNode : relationshipJsonNode) { - try { - parseRelationships(relationshipNode, relationships); - } catch (IOException e) { - log.error("Cannot parse relationship: " + relationshipNode, e); - return false; - } - } + return processRelationshipsArray(relationshipJsonNode, relationships, areSidesMandatory); } - //TODO: Remove support for old format DnR events when RTA has been updated. - if (relationshipJsonNode != null && (relationshipJsonNode.getNodeType() == JsonNodeType.OBJECT)) { + return true; + } + + private boolean processRelationshipsArray(JsonNode relationshipJsonNode, List relationships, + boolean areSidesMandatory) { + for (JsonNode relationshipNode : relationshipJsonNode) { try { - parseRelationships(relationshipJsonNode, relationships); + parseRelationships(relationshipNode, relationships, areSidesMandatory); } catch (IOException e) { log.error("Cannot parse relationship: " + relationshipJsonNode, e); return false; + } catch (InvalidRelationshipException e) { + log.error("Invalid relationship: " + e); + return false; } } return true; } - public void parseEntities(JsonNode entitiesJsonNode, List entities) throws IOException { + private boolean processRelationshipsObject(JsonNode relationshipJsonNode, List relationships, + boolean areSidesMandatory) { + try { + parseRelationships(relationshipJsonNode, relationships, areSidesMandatory); + } catch (IOException e) { + log.error("Cannot parse relationship: " + relationshipJsonNode, e); + return false; + } catch (InvalidRelationshipException e) { + log.error("Invalid relationship: " + e); + return false; + } + return true; + } + + public void parseEntities(JsonNode entitiesJsonNode, List entities) throws IOException, YangModelException { YangDataDomDocumentRoot entityDom = YangParser.getYangDataDomDocumentRoot(entitiesJsonNode); entityDom.getChildren().forEach(child -> { Entity entity = new Entity(); @@ -127,12 +152,51 @@ public class CloudEventParser { }); } - private void parseRelationships(JsonNode relationshipNode, List relationships) throws IOException { + private static void validateCharactersInId(Entity entity) throws IOException { + if (hasInvalidCharacter(entity.getId())) { + throw new IOException("Illegal character found in entity id:" + entity.getId()); + } + } + + private void parseRelationships(JsonNode relationshipNode, List relationships, boolean areSidesMandatory) + throws IOException, InvalidRelationshipException { YangDataDomDocumentRoot relDom = YangParser.getYangDataDomDocumentRoot(relationshipNode); - relDom.getChildren().forEach(child -> { + + for (YangDataDomNode child : relDom.getChildren()) { Relationship relationship = new Relationship(); relationship.parseObject(child); + if (relationship.getId() == null) { + throw new InvalidRelationshipException("Relationship is missing id! " + objectMapper.writeValueAsString( + relationship)); + } + if (areSidesMandatory && (relationship.getASide() == null || relationship.getBSide() == null)) { + throw new InvalidRelationshipException("Relationship is missing a side! " + relationship.getId()); + } + if (SchemaRegistry.getRelationTypeByName(relationship.getType()) == null) { + throw new InvalidRelationshipException("Invalid relationship type! " + relationship.getId()); + } + if (!SchemaRegistry.getModuleRegistry().containsKey(relationship.getModule())) { + throw new InvalidRelationshipException("Invalid relationship module! " + relationship.getId()); + } + String moduleName = SchemaRegistry.getRelationTypeByName(relationship.getType()).getModule().getName(); + if (!moduleName.equals(relationship.getModule())) { + log.error("Type: {} corresponding module: {}", relationship.getType(), moduleName); + throw new InvalidRelationshipException("Invalid relationship module-type pair! " + relationship.getId()); + } + validateCharactersInId(relationship); relationships.add(relationship); - }); + } + } + + private static void validateCharactersInId(Relationship relationship) throws IOException { + if (hasInvalidCharacter(relationship.getId())) { + throw new IOException(String.format(ILLEGAL_CHARACTER_FOUND, "id", relationship.getId())); + } + if (hasInvalidCharacter(relationship.getASide())) { + throw new IOException(String.format(ILLEGAL_CHARACTER_FOUND, "aSide", relationship.getASide())); + } + if (hasInvalidCharacter(relationship.getBSide())) { + throw new IOException(String.format(ILLEGAL_CHARACTER_FOUND, "bSide", relationship.getBSide())); + } } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Entity.java b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Entity.java index d8de9ce..6528c06 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Entity.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Entity.java @@ -39,7 +39,11 @@ public class Entity extends ModuleObject { public Entity(String module, String type, String id, Map attributes, List sourceIds) { super(module, type, id, sourceIds); - this.attributes = new HashMap<>(attributes); + if (attributes == null) { + this.attributes = new HashMap<>(); + } else { + this.attributes = new HashMap<>(attributes); + } } public Entity() { diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ModuleObject.java b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ModuleObject.java index 87f351d..a6b89bb 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ModuleObject.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ModuleObject.java @@ -36,9 +36,9 @@ import static org.oran.smo.teiv.utils.TiesConstants.SOURCE_IDS; @Getter public class ModuleObject { - private String module; - private String type; - private String id; + protected String module; + protected String type; + protected String id; private List sourceIds; public void parseObject(final YangDataDomNode node) { diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventData.java b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventData.java index 96527bb..46dd2f6 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventData.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventData.java @@ -23,6 +23,7 @@ package org.oran.smo.teiv.service.cloudevent.data; import lombok.AllArgsConstructor; import lombok.Data; +import java.util.Comparator; import java.util.List; @Data @@ -31,4 +32,25 @@ public class ParsedCloudEventData { private List entities; private List relationships; + + /** + * Sorts the entity and relationship list by type and id. + * The goal is to decrease the possibility of deadlocks in the database by executing the database operations in the same + * order in every pod's every consumer. + * For example: 2 transactions are trying to update both entity1 and entity2. If + * they both start with entity1, then one transaction gets the row level lock on entity1 and can go ahead while the + * other is blocked. + * If it's not sorted, then the first transaction can get the lock for entity1, the other gets the lock for entity2, and + * it's a deadlock. + */ + public void sort() { + if (entities != null) { + entities = getEntities().stream().sorted(Comparator.comparing(Entity::getType).thenComparing(Entity::getId)) + .toList(); + } + if (relationships != null) { + relationships = getRelationships().stream().sorted(Comparator.comparing(Relationship::getType).thenComparing( + Relationship::getStoringTablePrimaryKey)).toList(); + } + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Relationship.java b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Relationship.java index 47a3c8d..ed821b9 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Relationship.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/cloudevent/data/Relationship.java @@ -74,4 +74,12 @@ public class Relationship extends ModuleObject { }; } + public String getStoringTablePrimaryKey() { + RelationType relationType = SchemaRegistry.getRelationTypeByName(getType()); + return switch (relationType.getRelationshipStorageLocation()) { + case RELATION -> getId(); + case A_SIDE -> getASide(); + case B_SIDE -> getBSide(); + }; + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaAddressSupplierConfig.java b/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaAddressSupplierConfig.java index 1ca66e8..919ff67 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaAddressSupplierConfig.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaAddressSupplierConfig.java @@ -21,11 +21,9 @@ package org.oran.smo.teiv.service.kafka; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; @Service -@Profile("ingestion") public class KafkaAddressSupplierConfig implements KafkaAddressSupplier { @Value("${kafka.server.bootstrap-server-host}") diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaFactory.java b/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaFactory.java index 67dedfc..6c49d7a 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaFactory.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/kafka/KafkaFactory.java @@ -25,14 +25,13 @@ import io.cloudevents.kafka.CloudEventDeserializer; import java.time.Duration; import java.util.HashMap; import java.util.Map; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.apache.kafka.clients.admin.AdminClientConfig; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.common.serialization.StringDeserializer; import org.oran.smo.teiv.config.KafkaAdminConfig; import org.oran.smo.teiv.config.KafkaConfig; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Profile; import org.springframework.kafka.annotation.EnableKafka; import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.core.ConsumerFactory; @@ -46,8 +45,7 @@ import org.springframework.util.backoff.FixedBackOff; @Component @EnableKafka -@AllArgsConstructor -@Profile("ingestion") +@RequiredArgsConstructor public class KafkaFactory { private final KafkaConfig kafkaConfig; diff --git a/teiv/src/main/java/org/oran/smo/teiv/service/models/OperationResult.java b/teiv/src/main/java/org/oran/smo/teiv/service/models/OperationResult.java index ef1757e..0e73c4c 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/service/models/OperationResult.java +++ b/teiv/src/main/java/org/oran/smo/teiv/service/models/OperationResult.java @@ -20,28 +20,83 @@ */ package org.oran.smo.teiv.service.models; -import java.util.HashMap; +import java.util.List; import java.util.Map; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.oran.smo.teiv.service.cloudevent.data.Entity; import org.oran.smo.teiv.service.cloudevent.data.Relationship; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_A_SIDE; -import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_B_SIDE; @Data @AllArgsConstructor @NoArgsConstructor public class OperationResult { private String id; - private String entryType; - private Map content; - - public static OperationResult createFromRelationship(Relationship relationship) { - Map relationshipSides = new HashMap<>(); - relationshipSides.put(PROPERTY_A_SIDE, relationship.getASide()); - relationshipSides.put(PROPERTY_B_SIDE, relationship.getBSide()); - return new OperationResult(relationship.getId(), relationship.getType(), relationshipSides); + private String type; // e.g.: NRCellDU, Site, CloudNativeApplication + private String category; // "entity" or "relationship" + private Map attributes; + private String aSide; + private String bSide; + private List classifiers; + private Map decorators; + private List sourceIds; + + public static OperationResult createEntityOperationResult(String id, String type, Map attributes, + List sourceIds) { + return new OperationResult(id, type, "entity", attributes, null, null, null, null, sourceIds); + } + + public static OperationResult createEntityOperationResult(String id, String type, Map attributes) { + return createEntityOperationResult(id, type, attributes, null); + } + + public static OperationResult createEntityOperationResult(String id, String type) { + return OperationResult.createEntityOperationResult(id, type, null, null); + } + + public static OperationResult createEntityOperationResult(Entity entity) { + return OperationResult.createEntityOperationResult(entity.getId(), entity.getType(), entity.getAttributes(), entity + .getSourceIds()); + } + + public static OperationResult createRelationshipOperationResult(String id, String type, String aSide, String bSide, + List sourceIds) { + return new OperationResult(id, type, "relationship", null, aSide, bSide, null, null, sourceIds); + } + + public static OperationResult createRelationshipOperationResult(String id, String type, String aSide, String bSide) { + return createRelationshipOperationResult(id, type, aSide, bSide, null); + } + + public static OperationResult createRelationshipOperationResult(String id, String type) { + return OperationResult.createRelationshipOperationResult(id, type, null, null, null); + } + + public static OperationResult createRelationshipOperationResult(Relationship relationship) { + return OperationResult.createRelationshipOperationResult(relationship.getId(), relationship.getType(), relationship + .getASide(), relationship.getBSide(), relationship.getSourceIds()); + } + + public static OperationResult createClassifierOperationResult(String id, String type, String category, + List classifiers) { + return new OperationResult(id, type, category, null, null, null, classifiers, null, null); + } + + public static OperationResult createDecoratorOperationResult(String id, String type, String category, + Map decorators) { + return new OperationResult(id, type, category, null, null, null, null, decorators, null); + } + + @JsonIgnore + public boolean isRelationship() { + return getCategory().equals("relationship"); + } + + @JsonIgnore + public boolean isEntity() { + return getCategory().equals("entity"); } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/startup/SchemaHandler.java b/teiv/src/main/java/org/oran/smo/teiv/startup/SchemaHandler.java index a95bd9c..d88f90f 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/startup/SchemaHandler.java +++ b/teiv/src/main/java/org/oran/smo/teiv/startup/SchemaHandler.java @@ -20,6 +20,8 @@ */ package org.oran.smo.teiv.startup; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.service.SchemaCleanUpService; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; @@ -37,6 +39,8 @@ import lombok.extern.slf4j.Slf4j; public class SchemaHandler { private final SchemaLoader postgresSchemaLoader; private final HealthStatus healthStatus; + private final ModelRepository modelRepository; + private final SchemaCleanUpService schemaCleanUpService; /** * Loads the schema registry at application startup. @@ -50,4 +54,15 @@ public class SchemaHandler { log.info("Schema initialized successfully..."); healthStatus.setSchemaInitialized(true); } + + /** + * Continue schema clean up at application startup. + */ + @Order(value = 15) + @EventListener(value = ApplicationReadyEvent.class) + public void cleanUpSchema() { + log.debug("Start schema clean up"); + modelRepository.getDeletingModulesOnStartup().forEach(module -> schemaCleanUpService.cleanUpModule(module + .getName())); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/CloudEventUtil.java b/teiv/src/main/java/org/oran/smo/teiv/utils/CloudEventUtil.java index d511c38..162b7f9 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/CloudEventUtil.java +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/CloudEventUtil.java @@ -38,4 +38,16 @@ public class CloudEventUtil { return String.format("CloudEvent{id=%s, source=%s, type=%s, dataschema=%s, data=%s}", cloudEvent.getId(), cloudEvent .getSource(), cloudEvent.getType(), cloudEvent.getDataSchema(), cloudEventData); } + + public static boolean hasInvalidCharacter(String id) { + if (id == null || id.isEmpty()) { + return false; + } + // Characters that are permitted in URL components according to RFC3986, https://datatracker.ietf.org/doc/html/rfc3986, + // as well as the ':' character which is used in IDs + final String permittedCharactersPattern = "[-!$&'()*+,:;=._~0-9a-zA-Z]+"; + // General delimiters meant for delimiting URL components - these are not expected to be part of an id (: excluded) + final String forbiddenCharactersPattern = "[\\[\\]/?#@]+"; + return (!id.matches(permittedCharactersPattern) || id.matches(forbiddenCharactersPattern)); + } } diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/JooqTypeConverter.java b/teiv/src/main/java/org/oran/smo/teiv/utils/JooqTypeConverter.java new file mode 100644 index 0000000..d4ae088 --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/JooqTypeConverter.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.utils; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.jooq.JSONB; +import org.jooq.tools.json.JSONArray; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.experimental.UtilityClass; + +import lombok.extern.slf4j.Slf4j; +import org.oran.smo.teiv.exception.InvalidFieldInYangDataException; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.utils.schema.Geography; + +@UtilityClass +@Slf4j +public class JooqTypeConverter { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static List jsonbToList(final JSONB jsonb) { + try { + return objectMapper.readValue(jsonb.data(), List.class); + } catch (JsonProcessingException e) { + String message = "Exception during converting jsonb to list"; + log.error(message, e); + throw TiesException.serverException(message, null, e); + } + } + + public static Map jsonbToMap(final JSONB jsonb) { + try { + return objectMapper.readValue(jsonb.data(), Map.class); + } catch (JsonProcessingException e) { + String message = "Exception during converting jsonb to map"; + log.error(message, e); + throw TiesException.serverException(message, null, e); + } + } + + /** + * Creates a jooq.JSONB object from a json formatted String. + * + * The Yang Parser library parses the single element arrays as a JSON primitive. + * The use of yang models will solve this problem. As a temporary workaround, + * if one of the following is true, then the @param value is transformed into + * a single element json array before creating the JSONB object: + * - @param value is not a String, or + * - @param value is a String, but does not contain a JSON. + * + * @param value + * @return The jooq.JSONB object created from the value. + */ + public static JSONB toJsonb(Object value) { + if (value == null) { + return null; + } else if (value instanceof String str && isJsonObjectOrArray(str)) { + return JSONB.jsonb(str); + } else { + return JSONB.jsonb(makeSingleElementJsonArray(value)); + } + } + + /** + * Creates a jooq.JSONB object from a List of strings. + * + * @param stringList + * @return The jooq.JSONB object created from the value. + */ + public static JSONB toJsonb(List stringList) { + return JSONB.jsonb(JSONArray.toJSONString(stringList)); + } + + private static boolean isJsonObjectOrArray(String str) { + String trimmedStr = str.stripLeading(); + return trimmedStr.startsWith("{") || trimmedStr.startsWith("["); + } + + private static String makeSingleElementJsonArray(Object obj) { + return JSONArray.toJSONString(List.of(obj)); + } + + public static Geography toGeography(Object value) throws InvalidFieldInYangDataException { + try { + if (value == null) { + return null; + } + return new Geography((String) value); + } catch (ClassCastException | IOException e) { + throw new InvalidFieldInYangDataException(String.format("Can't create a Geography object from: %s", value), e); + } + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/PersistableUtil.java b/teiv/src/main/java/org/oran/smo/teiv/utils/PersistableUtil.java new file mode 100644 index 0000000..427982c --- /dev/null +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/PersistableUtil.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.utils; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class PersistableUtil { + public static String getFullyQualifiedNameWithColumnName(String fullyQualifiedName, String columnName) { + return fullyQualifiedName + "." + columnName; + } + + public static String getTableNameWithColumnName(String tableName, String columnName) { + return tableName + ".\"" + columnName + "\""; + } +} diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/TiesConstants.java b/teiv/src/main/java/org/oran/smo/teiv/utils/TiesConstants.java index c057c15..99c3d8b 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/TiesConstants.java +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/TiesConstants.java @@ -31,17 +31,21 @@ public class TiesConstants { public static final String TIES_DATA_SCHEMA = "ties_data"; public static final String TIES_DATA = TIES_DATA_SCHEMA + ".\"%s\""; public static final String TIES_MODEL = "ties_model.%s"; - public static final String ST_TO_STRING = "ST_AsText(\"%s\")"; + public static final String TIES_CONSUMER_DATA = "ties_consumer_data.%s"; + public static final String ST_TO_STRING = "ST_AsText(%s)"; public static final String ST_TO_STRING_COLUMN_WITH_TABLE_NAME = "ST_AsText(%s)"; public static final String QUOTED_STRING = "\"%s\""; public static final String ID_COLUMN_NAME = "id"; public static final String CONSUMER_DATA_PREFIX = "CD_"; public static final String SOURCE_IDS = "sourceIds"; + public static final String CLASSIFIERS = "classifiers"; + public static final String DECORATORS = "decorators"; public static final String REL_PREFIX = "REL_"; public static final String PROPERTY_A_SIDE = "aSide"; public static final String PROPERTY_B_SIDE = "bSide"; - public static final String ITEMS = "items"; + public static final String ITEM = "item"; public static final String ATTRIBUTES = "attributes"; + public static final String ATTRIBUTES_ABBREVIATION = ".attr."; public static final String TARGET_FILTER = "targetFilter"; public static final String SCOPE_FILTER = "scopeFilter"; public static final String QUERY = "query"; @@ -52,7 +56,15 @@ public class TiesConstants { public static final long INFINITE_MAXIMUM_CARDINALITY = 9223372036854775807L; public static final String FOREIGN_KEY_VIOLATION_ERROR_CODE = "23503"; public static final String UNIQUE_CONSTRAINT_VIOLATION_CODE = "23505"; + public static final String MODULE_REFERENCE = "module_reference"; public static final String REL_FK = "REL_FK_"; public static final String IN_USAGE = "IN_USAGE"; + public static final String MODULE_REFERENCE_NAME = "moduleReferenceName"; + public static final String NAME = "name"; + public static final String SCHEMA_ALREADY_EXISTS = "Schema already exists"; + public static final String SEMICOLON_SEPARATION = "%s:%s"; + public static final String DOT_SEPARATION = "%s.%s"; + public static final String WILDCARD = "*"; + public static final String INVALID_SCHEMA = "Invalid schema"; } diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/YangParser.java b/teiv/src/main/java/org/oran/smo/teiv/utils/YangParser.java index af20fbb..762d349 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/YangParser.java +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/YangParser.java @@ -28,7 +28,10 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.*; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exception.YangModelException; import org.oran.smo.yangtools.parser.data.YangData; +import org.oran.smo.yangtools.parser.findings.FindingSeverity; import org.oran.smo.yangtools.parser.findings.ModuleAndFindingTypeAndSchemaNodePathFilterPredicate; import org.oran.smo.yangtools.parser.input.BufferedStreamYangInput; import org.oran.smo.yangtools.parser.input.ByteArrayYangInput; @@ -37,6 +40,7 @@ import org.oran.smo.yangtools.parser.model.YangModel; import org.oran.smo.yangtools.parser.model.statements.StatementModuleAndName; import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; +import org.oran.smo.yangtools.parser.model.yangdom.YangDomElement; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -51,6 +55,11 @@ import org.oran.smo.yangtools.parser.model.ConformanceType; import org.oran.smo.yangtools.parser.model.statements.AbstractStatement; import org.oran.smo.teiv.api.model.OranTeivSchema; import org.oran.smo.teiv.api.model.OranTeivHref; +import org.springframework.web.multipart.MultipartFile; + +import static org.oran.smo.teiv.utils.TiesConstants.CLASSIFIERS; +import static org.oran.smo.teiv.utils.TiesConstants.INVALID_SCHEMA; +import static org.oran.smo.teiv.utils.TiesConstants.SEMICOLON_SEPARATION; @Service @Slf4j @@ -84,6 +93,67 @@ public class YangParser { return yangDeviceModel; } + /** + * Validating yang file from /schemas POST request + * + * @return map of validated and parsed yang + */ + public Map validateSchemasYang(MultipartFile file) throws YangModelException { + + Map result = new HashMap<>(); + + YangDeviceModel yangDeviceModel = new YangDeviceModel("r1"); + YangModel inputYangModel = null; + final List yangModels = new ArrayList<>(); + try { + inputYangModel = new YangModel(new ByteArrayYangInput(file.getBytes(), "requestYang"), ConformanceType.IMPORT); + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(this.getClass().getClassLoader()); + Resource[] yangResourcesImplement = resolver.getResources("classpath:models/*.yang"); + Resource[] yangResourcesImport = resolver.getResources("classpath:models/import/*.yang"); + + for (Resource yangResource : yangResourcesImplement) { + yangModels.add(new YangModel(new ByteArrayYangInput(yangResource.getContentAsByteArray(), Objects + .requireNonNull(yangResource.getFilename())), ConformanceType.IMPLEMENT)); + } + + for (Resource yangResource : yangResourcesImport) { + yangModels.add(new YangModel(new ByteArrayYangInput(yangResource.getContentAsByteArray(), Objects + .requireNonNull(yangResource.getFilename())), ConformanceType.IMPORT)); + } + + yangModels.add(inputYangModel); + } catch (final IOException ex) { + log.error("Unable to load schema", ex); + } + + final ModifyableFindingSeverityCalculator severityCalculator = new ModifyableFindingSeverityCalculator(); + final FindingsManager findingsManager = new FindingsManager(severityCalculator); + findingsManager.addFilterPredicate(ModuleAndFindingTypeAndSchemaNodePathFilterPredicate.fromString("ietf-*;*;*")); + findingsManager.addFilterPredicate(ModuleAndFindingTypeAndSchemaNodePathFilterPredicate.fromString("_3gpp*;*;*")); + final ParserExecutionContext context = new ParserExecutionContext(findingsManager); + context.setIgnoreImportedProtocolAccessibleObjects(true); + context.setFailFast(false); + yangDeviceModel.parseIntoYangModels(context, yangModels); + checkFindings(context.getFindingsManager(), severityCalculator); + + assert inputYangModel != null; + String prefixName = null; + + for (YangDomElement children : inputYangModel.getYangDomDocumentRoot().getChildren().get(0).getChildren()) { + if (children.getValue().contains("common-yang-types")) { + prefixName = children.getChildren().get(0).getValue(); + break; + } + } + + result.put("classifiers", getClassifiers(inputYangModel.getYangDomDocumentRoot().getChildren().get(0).getChildren(), + prefixName)); + result.put("decorators", getDecorators(inputYangModel.getYangDomDocumentRoot().getChildren().get(0).getChildren())); + result.put("moduleName", inputYangModel.getModuleIdentity().getModuleName()); + result.put("revision", inputYangModel.getModuleIdentity().getRevision()); + return result; + } + /** * Store domains and revision by schema name, return object of all schemas * @@ -160,6 +230,63 @@ public class YangParser { return yangDataDomDocument; } + private List getClassifiers(List elements, String prefixName) { + + List result = new ArrayList<>(); + String formattedName = String.format(SEMICOLON_SEPARATION, prefixName, CLASSIFIERS); + + elements.stream().filter(element -> element.getName().contains("identity")).forEach(element -> { + String childValue = element.getChildren().get(0).getValue(); + + if (!childValue.equals(formattedName)) { + List domElement = element.getParentElement().getChildren().stream().filter(parent -> parent + .getName().contains("identity")).filter(parent -> parent.getValue().equals(childValue) && parent + .getChildren().get(0).getValue().equals(formattedName)).toList(); + + if (domElement.isEmpty()) { + throw TiesException.invalidSchema("Invalid classifier " + element.getValue()); + } else { + result.add(element.getValue()); + } + } else { + result.add(element.getValue()); + } + }); + + return result; + } + + private Map getDecorators(List elements) { + Map result = new HashMap<>(); + + elements.forEach(keys -> { + if (keys.getValue().contains("decorators")) { + keys.getChildren().forEach(values -> result.put(values.getValue(), switch (values.getChildren().get(0) + .getValue()) { + case "string" -> "TEXT"; + case "boolean" -> "BOOLEAN"; + case "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64" -> "INT"; + default -> throw TiesException.invalidFileInput("Invalid data type"); + })); + } + }); + + return result; + } + + private static void checkFindings(FindingsManager findingsManager, + ModifyableFindingSeverityCalculator severityCalculator) { + for (Finding finding : findingsManager.getAllFindings()) { + if (severityCalculator.calculateSeverity(finding.getFindingType()).equals(FindingSeverity.ERROR)) { + if (finding.getMessage().contains("exception") || finding.getFindingType().contains("UNSPECIFIED_ERROR")) { + throw TiesException.invalidFileInput(INVALID_SCHEMA); + } else { + throw TiesException.invalidFileInput(finding.getMessage()); + } + } + } + } + private static YangDataDomDocumentRoot parse(final String yangTopology) throws IOException { final ModifyableFindingSeverityCalculator severityCalculator = new ModifyableFindingSeverityCalculator(); diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryElement.java b/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryElement.java deleted file mode 100644 index c389b03..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryElement.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils.query; - -import org.oran.smo.teiv.utils.path.TiesPathQuery; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -@Getter -@NoArgsConstructor -class QueryElement { - private String objectType; - private List attributes = null; - private Map> filters = null; - private List children = new ArrayList<>(); - private boolean isIncluded = false; - private boolean isManyToMany = false; - private boolean isRelConnectingSameEntity = false; - - public QueryElement(String objectType) { - this.objectType = objectType; - } - - public QueryElement(String objectType, boolean isIncluded) { - this.objectType = objectType; - this.isIncluded = isIncluded; - } - - public void addAttribute(String attribute) { - attributes.add(attribute); - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } - - public void addFilter(TokenType type, TiesPathQuery filter) { - filters.putIfAbsent(type, new ArrayList<>()); - filters.get(type).add(filter); - - } - - public boolean hasFilters() { - return filters != null; - } - - public void setFilters(Map> filters) { - this.filters = filters; - } - - public void addChild(QueryElement child) { - addChild(child, true); - } - - public void addChild(QueryElement child, boolean safeAdd) { - if (safeAdd && this.hasChild(child.objectType)) { - return; - } - children.add(child); - } - - public void removeChild(QueryElement child) { - children.remove(child); - } - - public boolean hasAttributes() { - return attributes != null; - } - - public List getFiltersOfTypes(List types) { - return types.stream().flatMap(type -> filters.containsKey(type) ? filters.get(type).stream() : null).toList(); - } - - public boolean hasFilterOfType(TokenType type) { - return filters.containsKey(type); - } - - public boolean hasChild(String child) { - return children.stream().anyMatch(c -> c.getObjectType().equals(child)); - } - - public QueryElement getChild(String objectType) { - Optional result = children.stream().filter(child -> child.getObjectType().equals(objectType)) - .findFirst(); - return result.orElse(null); - } - - public boolean hasChildren() { - return !children.isEmpty(); - } - - public void include() { - isIncluded = true; - } - - public void setManyToMany() { - isManyToMany = true; - } - - public void setRelConnectingSameEntity() { - isRelConnectingSameEntity = true; - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryMonad.java b/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryMonad.java deleted file mode 100644 index 086a236..0000000 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/query/QueryMonad.java +++ /dev/null @@ -1,989 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils.query; - -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getDbName; -import static org.oran.smo.teiv.schema.BidiDbNameMapper.getModelledName; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; -import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.oran.smo.teiv.utils.path.TiesPathUtil.getTiesPathQuery; -import static org.jooq.impl.DSL.asterisk; -import static org.jooq.impl.DSL.condition; -import static org.jooq.impl.DSL.field; -import static org.jooq.impl.DSL.not; -import static org.jooq.impl.DSL.one; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Function; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.oran.smo.teiv.schema.RelationshipDataLocation; -import org.antlr.v4.runtime.misc.ParseCancellationException; -import org.jooq.Condition; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.Record; -import org.jooq.Record1; -import org.jooq.ResultQuery; -import org.jooq.Select; -import org.jooq.SelectConditionStep; -import org.jooq.SelectJoinStep; -import org.jooq.SelectSelectStep; -import org.jooq.impl.DSL; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.utils.path.TiesPathQuery; -import org.oran.smo.teiv.utils.path.exception.PathParsingException; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; - -@Builder -public class QueryMonad { - - private static final String SEMICOLON = ";"; - private static final String BAR = "|"; - private String managedObject; - private String targets; - private String scope; - private String relationships; - private String domain; - - /** - * Builds a jooq query using the SchemaRegistry, based on the filters. - * - * @return the prepared jooq query - */ - public Function> withSchema(final PaginationDTO paginationDTO) { - return context -> buildQuery(context, paginationDTO); - } - - public Function>> countWithSchema() { - return this::buildQueryCount; - } - - private QueryElement constructRoot() { - List targetTokens = targets != null ? processPath(targets, true) : new ArrayList<>(); - List scopeTokens = scope != null ? processPath(scope, false) : new ArrayList<>(); - - return buildQueryTree(managedObject, targetTokens, scopeTokens, domain); - } - - private ResultQuery buildQuery(DSLContext context, final PaginationDTO paginationDTO) { - List relationshipTypes = parseRelationships(relationships); - - return buildJooqQuery(context, constructRoot(), relationshipTypes, paginationDTO); - } - - private SelectConditionStep> buildQueryCount(DSLContext context) { - List relationshipTypes = parseRelationships(relationships); - - return buildJooqQueryCount(context, constructRoot(), relationshipTypes); - } - - private static Select buildInnerQuery(DSLContext context, QueryElement root, List relationships) { - SelectSelectStep selectStep = buildSelectStep(context, root, root.getObjectType()); - - boolean[] isValidHop = { false }; - Select query = buildFromStep(selectStep, root, relationships, isValidHop, root.getObjectType()); - Condition joinFilter = null; - - for (QueryElement child : root.getChildren()) { - if (root.getObjectType() != null && !SchemaRegistry.hasDirectHopBetween(root.getObjectType(), child - .getObjectType(), relationships)) { - continue; - } - - joinFilter = setJoinFilter(root, joinFilter, child); - } - - for (QueryElement child : root.getChildren()) { - if (root.getObjectType() == null || SchemaRegistry.hasDirectHopBetween(root.getObjectType(), child - .getObjectType())) { - query = query.union(buildUnionBody(context, root, child.getObjectType(), relationships, joinFilter, - isValidHop)); - } - } - - buildJooqQueryCheckIfRootHasConnections(root, isValidHop[0]); - - query = buildWhereStep(query, root, joinFilter, relationships); - - return query; - } - - private static SelectConditionStep> buildJooqQueryCount(DSLContext context, QueryElement root, - List relationships) { - - Select query = buildInnerQuery(context, root, relationships); - - return context.selectCount().from(query.asTable("TiesPathQuery")).where(not(field("\"TiesPathQuery\"").isNull())); - } - - private static SelectJoinStep buildJooqQuery(DSLContext context, QueryElement root, List relationships, - final PaginationDTO paginationDTO) { - - Select query = buildInnerQuery(context, root, relationships); - - return (SelectJoinStep) context.selectDistinct(asterisk()).from(query.asTable("TiesPathQuery")).orderBy( - one().asc()).limit(paginationDTO.getOffset(), paginationDTO.getLimit()); - } - - private static Condition setJoinFilter(QueryElement root, Condition joinFilter, QueryElement child) { - if (root.getObjectType() != null || child.getFilters() == null) { - Field condition = field(String.format(TIES_DATA, getDbName(child.getObjectType())) + "." + String - .format(QUOTED_STRING, ID_COLUMN_NAME)).isNotNull(); - if (joinFilter != null && root.getObjectType() != null) { - joinFilter = joinFilter.and(condition); - } else if (joinFilter != null) { - joinFilter = joinFilter.or(condition); - } else { - joinFilter = DSL.condition(condition); - } - } - return joinFilter; - } - - private static void buildJooqQueryCheckIfRootHasConnections(QueryElement root, Boolean isValidHop) { - if ((root.hasChildren() && !isValidHop && root.getObjectType() != null) || (!root.hasChildren() && !root - .isIncluded())) { - throw TiesPathException.noConnectionFound(root.getObjectType()); - } else if ((root.hasChildren() && !isValidHop) || (!root.hasChildren() && !root.isIncluded())) { - throw TiesPathException.noConnectionFoundWhenRootIsNull(); - } - } - - private static SelectSelectStep buildSelectStep(DSLContext context, QueryElement root, String returnObject) { - List columnNames = getColumnList(root); - if (returnObject == null) { - return context.select(columnNames.stream().map(column -> field("null").cast(SchemaRegistry.getEntityTypeByName( - getModelledName(column.split("\\.")[1].replaceAll("\"", ""))).getField(column, null, returnObject) - .getType()).as(column)).collect(Collectors.toList())); - } - if (root.isManyToMany()) { - return context.select(columnNames.stream().map(DSL::field).toList()); - } else if (root.isRelConnectingSameEntity()) { - return context.selectDistinct(columnNames.stream().map(DSL::field).toList()); - } else { - return context.select(columnNames.stream().map(column -> column.split("\\.")[1].replaceAll("\"", "").equals( - getDbName(returnObject)) ? - SchemaRegistry.getEntityTypeByName(returnObject).getField(column, null, null) : - field("null").cast(SchemaRegistry.getEntityTypeByName(getModelledName(column.split("\\.")[1] - .replaceAll("\"", ""))).getField(column, null, returnObject).getType()).as(column)) - .collect(Collectors.toList())); - } - } - - private static SelectSelectStep buildSelectStepForUnion(DSLContext context, QueryElement root, - String returnObject) { - List columnNames = getColumnList(root); - if (root.getObjectType() != null && root.getObjectType().equals(returnObject)) { - return context.select(columnNames.stream().map(column -> field("null").cast(SchemaRegistry.getEntityTypeByName( - column.split("\\.")[1].replaceAll("\"", "")).getField(column, null, returnObject).getType()).as(column)) - .collect(Collectors.toList())); - } else { - return buildSelectStep(context, root, returnObject); - } - } - - private static SelectJoinStep buildFromStep(SelectSelectStep selectStep, QueryElement root, - List relationships, boolean[] isValidHop, String returnObject) { - if (root.getObjectType() == null) { - SelectJoinStep fromStep = selectStep.from("(SELECT '') as dual_table"); - - for (QueryElement child : root.getChildren()) { - if (SchemaRegistry.isEntityPartOfRelationships(child.getObjectType(), relationships)) { - TableJoinConnection connection = new TableJoinConnection(B_SIDE, null, List.of(condition(field(String - .format(TIES_DATA, getDbName(child.getObjectType())) + "." + ID_COLUMN_NAME).eq(field( - "(SELECT '')")))), false); - - fromStep = buildFromStepSetJoin(child, returnObject, fromStep, connection); - - isValidHop[0] = true; - } - } - return fromStep; - } - SelectJoinStep fromStep = selectStep.from(String.format(TIES_DATA, getDbName(root.getObjectType()))); - for (QueryElement child : root.getChildren()) { - for (TableJoinConnection connection : findJoinConnections(root, child, relationships)) { - fromStep = getRecords(root, fromStep, child, connection); - isValidHop[0] = true; - } - } - return fromStep; - } - - private static SelectJoinStep getRecords(QueryElement root, SelectJoinStep fromStep, QueryElement child, - TableJoinConnection connection) { - if (connection.relConnectingSameEntity) { - fromStep = fromStep.join(connection.getTableName()).on(connection.getConditions().get(0)).or(connection - .getConditions().get(1)); - } else { - if (!root.isManyToMany() && connection.getRelationshipDataLocation().equals(RELATION)) { - fromStep = fromStep.join(connection.getTableName()).on(connection.getConditions().get(1)); - } - if (!root.isManyToMany()) { - fromStep = fromStep.leftJoin(String.format(TIES_DATA, getDbName(child.getObjectType()))).on(connection - .getConditions().get(0)); - } else { - fromStep = fromStep.join(String.format(TIES_DATA, getDbName(child.getObjectType()))).on(connection - .getConditions().get(0)); - } - } - return fromStep; - } - - private static SelectJoinStep buildFromStepSetJoin(QueryElement child, String returnObject, - SelectJoinStep fromStep, TableJoinConnection connection) { - if (child.getObjectType().equals(returnObject)) { - return fromStep.rightJoin(String.format(TIES_DATA, getDbName(child.getObjectType()))).on(connection - .getConditions().get(0)); - } else { - return fromStep.leftJoin(String.format(TIES_DATA, getDbName(child.getObjectType()))).on(connection - .getConditions().get(0)); - } - } - - private static List findJoinConnections(QueryElement qe1, QueryElement qe2, - List relationships) { - List relationTypes; - if (qe1.isManyToMany() || qe1.isRelConnectingSameEntity()) { - relationTypes = List.of(SchemaRegistry.getRelationTypeByName(qe1.getObjectType())); - } else { - relationTypes = SchemaRegistry.getRelationTypesBetweenEntities(qe1.getObjectType(), qe2.getObjectType(), - relationships); - } - return createJoinConnections(qe1, qe2, relationTypes); - } - - private static List createJoinConnections(QueryElement qe1, QueryElement qe2, - List relationTypes) { - List joins = new ArrayList<>(); - for (RelationType relationType : relationTypes) { - switch (relationType.getRelationshipStorageLocation()) { - case A_SIDE: - joins.add(createASideJoin(relationType)); - break; - case B_SIDE: - joins.add(createBSideJoin(relationType)); - break; - case RELATION: - joins.add(createRelationJoin(qe1, qe2, relationType)); - break; - } - } - return joins; - } - - private static TableJoinConnection createSameEntityJoin(QueryElement qe1, QueryElement qe2, RelationType relationType) { - String table = relationType.getTableName() + "."; - if (!qe1.isRelConnectingSameEntity()) { - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), relationType.getTableName(), List - .of(condition(field(table + String.format(QUOTED_STRING, relationType.bSideColumnName())).eq(field( - String.format(TIES_DATA, getDbName(qe2.getObjectType())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME)))), condition(field(table + String.format(QUOTED_STRING, relationType - .aSideColumnName())).eq(field(String.format(TIES_DATA, qe1 - .getObjectType()) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), true); - } else { - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), String.format(TIES_DATA, - getDbName(qe2.getObjectType())), List.of(condition(field(table + String.format(QUOTED_STRING, - relationType.bSideColumnName())).eq(field(String.format(TIES_DATA, getDbName(qe2 - .getObjectType())) + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME)))), condition( - field(table + String.format(QUOTED_STRING, relationType.aSideColumnName())).eq( - field(String.format(TIES_DATA, getDbName(qe2 - .getObjectType())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), true); - } - } - - private static TableJoinConnection createASideJoin(RelationType relationType) { - String table = relationType.getTableName() + "."; - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), null, List.of(condition(field( - table + String.format(QUOTED_STRING, relationType.bSideColumnName())).eq(field(String.format(TIES_DATA, - getDbName(relationType.getBSide().getName())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), false); - } - - private static TableJoinConnection createBSideJoin(RelationType relationType) { - String table = relationType.getTableName() + "."; - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), null, List.of(condition(field( - table + String.format(QUOTED_STRING, relationType.aSideColumnName())).eq(field(String.format(TIES_DATA, - getDbName(relationType.getASide().getName())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), false); - } - - private static TableJoinConnection createRelationJoin(QueryElement qe1, QueryElement qe2, RelationType relationType) { - String table = relationType.getTableName() + "."; - if (relationType.isConnectsSameEntity()) { - return createSameEntityJoin(qe1, qe2, relationType); - } else if (!qe1.isManyToMany()) { - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), relationType.getTableName(), List - .of(condition(field(table + String.format(QUOTED_STRING, relationType.bSideColumnName())).eq(field( - String.format(TIES_DATA, getDbName(qe2.getObjectType())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME)))), condition(field(table + String.format(QUOTED_STRING, relationType - .aSideColumnName())).eq(field(String.format(TIES_DATA, qe1 - .getObjectType()) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), false); - } else { - String colInManyToManyTable = relationType.getASide().getName().equals(qe2.getObjectType()) ? - relationType.aSideColumnName() : - relationType.bSideColumnName(); - return new TableJoinConnection(relationType.getRelationshipStorageLocation(), relationType.getTableName(), List - .of(condition(field(table + String.format(QUOTED_STRING, colInManyToManyTable)).eq(field(String.format( - TIES_DATA, getDbName(qe2.getObjectType())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME))))), false); - } - } - - private static Select buildUnionBody(DSLContext context, QueryElement root, String returnObject, - List relationships, Condition joinFilter, boolean[] isValidHop) { - SelectSelectStep selectStep = buildSelectStepForUnion(context, root, returnObject); - SelectJoinStep fromStep = buildFromStep(selectStep, root, relationships, isValidHop, returnObject); - return buildWhereStep(fromStep, root, joinFilter, relationships); - } - - private static Select buildWhereStep(Select query, QueryElement root, Condition joinFilter, - List relationships) { - Condition condition = DSL.noCondition(); - condition = buildWhereAnd(condition, root, relationships); - for (QueryElement child : root.getChildren()) { - condition = buildWhereAnd(condition, child, null); - } - if (!root.isManyToMany()) { - condition = buildWhereOr(condition, root); - } - for (QueryElement child : root.getChildren()) { - condition = buildWhereOr(condition, child); - } - if (joinFilter != null && root.getObjectType() != null) { - condition = condition.and(joinFilter); - } else if (joinFilter != null) { - condition = condition.or(joinFilter); - } - return query.$where(condition); - } - - private static Condition buildWhereAnd(Condition condition, QueryElement root, List relationships) { - if (root.hasFilters() && (root.hasFilterOfType(TokenType.AND) || root.hasFilterOfType(TokenType.NO_TYPE))) { - condition = condition.and(DSL.and(Stream.concat(root.getFiltersOfTypes(List.of(TokenType.AND, - TokenType.NO_TYPE)).stream().flatMap(filter -> filter.hasLeafConditions() ? - filter.getLeavesData().stream().map(leaf -> field(String.format(TIES_DATA, getDbName(root - .getObjectType())) + "." + String.format(QUOTED_STRING, getDbName(leaf.getName()))).eq( - leaf.getValue())) : - null), root.getFiltersOfTypes(List.of(TokenType.AND, TokenType.NO_TYPE)).stream().map( - filter -> filter.hasContainsFunctionCondition() ? - field(String.format(TIES_DATA, getDbName(root.getObjectType())) + "." + String - .format(QUOTED_STRING, getDbName(filter - .getContainsFunctionConditionLeafName()))).contains(filter - .getContainsFunctionConditionValue()) : - DSL.noCondition())).toList())); - } - - condition = getConditionsWithRelationships(condition, relationships); - - return condition; - } - - private static Condition getConditionsWithRelationships(Condition condition, List relationships) { - if (relationships != null) { - List relationTypes = new ArrayList<>(); - - for (String relationship : relationships) { - relationTypes.add(SchemaRegistry.getRelationTypeByName(relationship)); - } - - for (RelationType relationType : relationTypes) { - for (Field field : relationType.getBaseFieldsWithId()) { - condition = condition.and(field.isNotNull()); - } - } - } - return condition; - } - - private static Condition buildWhereOr(Condition condition, QueryElement root) { - if (root.hasFilters() && root.hasFilterOfType(TokenType.OR)) { - condition = condition.or(DSL.or(root.getFiltersOfTypes(List.of(TokenType.OR)).stream().map(filter -> DSL.and( - filter.hasLeafConditions() ? - filter.getLeavesData().stream().map(leaf -> field(String.format(TIES_DATA, getDbName(root - .getObjectType())) + "." + String.format(QUOTED_STRING, getDbName(leaf.getName()))).eq( - leaf.getValue())).toList() : - List.of(DSL.noCondition()))).toList())); - condition = condition.or(DSL.or(root.getFiltersOfTypes(List.of(TokenType.OR)).stream().map(filter -> filter - .hasContainsFunctionCondition() ? - field(String.format(TIES_DATA, getDbName(root.getObjectType())) + "." + String.format( - QUOTED_STRING, getDbName(filter.getContainsFunctionConditionLeafName()))).contains( - filter.getContainsFunctionConditionValue()) : - DSL.noCondition()).toList())); - } - return condition; - } - - private static List getColumnList(QueryElement root) { - List columns = new ArrayList<>(); - - if (root.isIncluded()) { - if (!root.hasAttributes()) { - columns.add(String.format(TIES_DATA, getDbName(root.getObjectType())) + "." + String.format(QUOTED_STRING, - ID_COLUMN_NAME)); - } else { - if (root.getAttributes().isEmpty()) { - columns.addAll(SchemaRegistry.getEntityTypeByName(root.getObjectType()).getAttributeColumnsWithId()); - } else { - columns.addAll(root.getAttributes().stream().map(attribute -> String.format(TIES_DATA, getDbName(root - .getObjectType())) + "." + String.format(QUOTED_STRING, getDbName(attribute))).toList()); - if (!columns.contains(String.format(TIES_DATA, getDbName(root.getObjectType())) + "." + String.format( - QUOTED_STRING, ID_COLUMN_NAME))) { - columns.add(String.format(TIES_DATA, getDbName(root.getObjectType())) + "." + String.format( - QUOTED_STRING, ID_COLUMN_NAME)); - } - } - } - } - if (root.hasChildren()) { - columns.addAll(root.getChildren().stream().flatMap(child -> getColumnList(child).stream()).toList()); - } - - return columns; - } - - private static List processPath(String path, boolean isSemiColonAllowed) { - return processPath(path, isSemiColonAllowed, null); - } - - private static List processPath(String path, boolean isSemiColonAllowed, TokenType lastToken) { - List tiesPath = new ArrayList<>(); - - if (path.isEmpty()) { - return tiesPath; - } - - if (!isSemiColonAllowed && path.indexOf(';') > -1) { - throw TiesPathException.grammarError(String.format("Character ';' is not allowed at %d", path.indexOf(';'))); - } - - if (path.contains(BAR) || path.contains(SEMICOLON)) { - String delimiter = findDelimiter(path); - - String[] tokens = path.split(Pattern.quote(delimiter), 2); - TokenType type = delimiter.equals(BAR) ? TokenType.OR : TokenType.AND; - addPathSafe(tiesPath, tokens[0], type); - tiesPath.addAll(processPath(tokens[1], isSemiColonAllowed, type)); - } else { - addPathSafe(tiesPath, path, lastToken != null ? lastToken : TokenType.NO_TYPE); - } - return tiesPath; - } - - private static String findDelimiter(String path) { - if (path.contains(BAR) && path.contains(SEMICOLON)) { - return path.indexOf(BAR) < path.indexOf(SEMICOLON) ? SEMICOLON : BAR; - } else { - return path.contains(BAR) ? BAR : SEMICOLON; - } - } - - private static void addPathSafe(List tiesPath, String path, TokenType type) { - try { - tiesPath.add(new PathToken(type, getTiesPathQuery(path))); - } catch (ParseCancellationException e) { - throw TiesPathException.grammarError(e.getMessage()); - } catch (PathParsingException e) { - throw TiesPathException.grammarError(e.getDetails()); - } - } - - private static List parseRelationships(final String relationships) { - if (relationships == null || relationships.isEmpty()) { - return new ArrayList<>(); - } - String[] relationshipTokens = relationships.split(","); - List relationshipsList = new ArrayList<>(); - Arrays.stream(relationshipTokens).forEach(relationship -> { - String trimmed = relationship.trim(); - if (SchemaRegistry.getRelationNames().contains(trimmed)) { - relationshipsList.add(trimmed); - } else { - throw TiesPathException.invalidRelationshipName(trimmed); - } - }); - return relationshipsList; - } - - private static QueryElement buildQueryTree(String objectType, List targets, List scopes, - String domain) { - QueryElement root = new QueryElement(objectType); - RelationType relationType = SchemaRegistry.getRelationTypeByName(objectType); - if (objectType != null && relationType != null) { - if (relationType.isConnectsSameEntity()) { - root.setRelConnectingSameEntity(); - } else if (RELATION.equals(relationType.getRelationshipStorageLocation())) { - root.setManyToMany(); - } - } - - processTargets(root, targets, domain); - processScopes(root, scopes, domain); - - return root; - } - - private static void processTargets(QueryElement root, List targets, String domain) { - String prevToken = null; - String prevPrevToken = null; - - if (targets.isEmpty()) { - root.include(); - } - - for (PathToken target : targets) { - QueryElement[] currentElement = { root }; - boolean isValidHop = true; - for (int i = 0; i < target.getValue().getContainerNames().size(); ++i) { - String container = target.getValue().getContainerNames().get(i); - isValidHop = processTargetContainer(root, currentElement, container, prevToken, domain, prevPrevToken); - if (!isValidHop) { - break; - } - prevPrevToken = prevToken; - prevToken = container; - } - if (isValidHop) { - addTargetAttributes(currentElement[0], target); - } - prevToken = null; - } - - if (root.getObjectType() == null && root.getChildren().isEmpty()) { - throw TiesPathException.grammarError("No match for targetFilter condition"); - } - } - - private static boolean processTargetContainer(QueryElement root, QueryElement[] currentElement, String container, - String prevToken, String domain, String prevPrevToken) { - if (SchemaRegistry.isValidEntityName(container)) { - if (prevToken != null) { - throw TiesPathException.grammarError(String.format("Missing ';' or '|' before %s", container)); - } - if (root.getObjectType() != null && !SchemaRegistry.hasDirectHopBetween(currentElement[0].getObjectType(), - container)) { - return false; - } - if (root.getObjectType() == null && !SchemaRegistry.getEntityNamesByDomain(domain).contains(container)) { - throw TiesPathException.grammarError(String.format("%s is not part of %s domain", container, domain)); - } - currentElement[0].addChild(new QueryElement(container, true)); - currentElement[0] = currentElement[0].getChild(container); - prevToken = container; - } else if (root.getObjectType() != null && currentElement[0].getObjectType().equals(root.getObjectType()) && !root - .hasChildren()) { - root.include(); - } - - processTargetAttribute(container, prevToken, currentElement[0]); - - processTargetContainerIfItIsAttributes(root, currentElement, container, prevToken, domain); - - processTargetContainerIfItIsID(root, currentElement, container, prevToken, domain); - - processTargetContainerPrevPrevTokenNull(root, container, prevToken, prevPrevToken); - - return true; - } - - private static void processTargetContainerPrevPrevTokenNull(QueryElement root, String container, String prevToken, - String prevPrevToken) { - if (prevPrevToken == null && prevToken != null && prevToken.equals(ATTRIBUTES) && !container.equals( - ID_COLUMN_NAME) && !container.equals(ATTRIBUTES)) { - List doesNotHaveAttribute = new ArrayList<>(); - for (QueryElement child : root.getChildren()) { - processTargetAttribute(container, prevToken, child); - if (child.getAttributes().isEmpty()) { - doesNotHaveAttribute.add(child); - } - } - if (root.getObjectType() == null) { - removeChildFromRoot(doesNotHaveAttribute, root); - } - } else if (prevPrevToken == null && prevToken != null && prevToken.equals(ATTRIBUTES) && container.equals( - ID_COLUMN_NAME)) { - throw TiesPathException.idAmongAttributesError(); - } - } - - private static void removeChildFromRoot(List childrenToRemove, QueryElement root) { - for (QueryElement child : childrenToRemove) { - root.removeChild(child); - } - - } - - private static void processTargetContainerIfItIsAttributes(QueryElement root, QueryElement[] currentElement, - String container, String prevToken, String domain) { - if (container.equals(ATTRIBUTES) && root.getObjectType() == null && prevToken == null) { - for (String entity : SchemaRegistry.getEntityNamesByDomain(domain)) { - if (currentElement[0].getChild(entity) == null) { - QueryElement entityInDomain = new QueryElement(entity); - addTargetContainer(entityInDomain, prevToken); - currentElement[0].addChild(entityInDomain); - } - } - } else if (container.equals(ATTRIBUTES)) { - addTargetContainer(currentElement[0], prevToken); - } - } - - private static void processTargetContainerIfItIsID(QueryElement root, QueryElement[] currentElement, String container, - String prevToken, String domain) { - if (container.equals(ID_COLUMN_NAME) && root.getObjectType() == null && prevToken == null) { - for (String entity : SchemaRegistry.getEntityNamesByDomain(domain)) { - if (currentElement[0].getChild(entity) == null && SchemaRegistry.doesEntityContainsAttribute(entity, - container)) { - QueryElement entityInDomain = new QueryElement(entity, true); - currentElement[0].addChild(entityInDomain); - addTargetContainer(entityInDomain, prevToken); - addTargetAttribute(entityInDomain, container); - } - } - } - - } - - private static void processTargetAttribute(String container, String prevToken, QueryElement currentElement) { - if (SchemaRegistry.doesEntityContainsAttribute(currentElement.getObjectType(), container)) { - if (container.equals(ID_COLUMN_NAME) && prevToken == null) { - addTargetContainer(currentElement, null); - addTargetAttribute(currentElement, container); - - } else if (container.equals(ID_COLUMN_NAME)) { - if (SchemaRegistry.isValidEntityName(prevToken)) { - addTargetContainer(currentElement, prevToken); - addTargetAttribute(currentElement, container); - } else { - throw TiesPathException.idAmongAttributesError(); - } - } else { - if (prevToken == null) { - throw TiesPathException.grammarError(String.format("Missing 'attributes' before %s", container)); - } else if (prevToken.equals(ATTRIBUTES)) { - addTargetAttribute(currentElement, container); - - } else { - throw TiesPathException.grammarError(String.format("/%s/%s is not accepted", prevToken, container)); - } - } - } - } - - private static void addTargetContainer(QueryElement element, String prevToken) { - if (ATTRIBUTES.equals(prevToken)) { - throw TiesPathException.grammarError(String.format("Missing ';' or '|' before %s", prevToken)); - } - if (!element.hasAttributes()) { - element.setAttributes(new ArrayList<>()); - element.include(); - } - } - - private static void addTargetAttribute(QueryElement element, String container) { - if (!element.hasAttributes()) { - throw TiesPathException.grammarError(String.format("Missing 'attributes' before %s", container)); - } - element.addAttribute(container); - } - - private static void addTargetAttributes(QueryElement element, PathToken target) { - if (target.getValue().getNormalizedXpath().equals("/" + ID_COLUMN_NAME) && !target.getValue().getAttributeNames() - .isEmpty()) { - throw TiesPathException.grammarError("/" + ID_COLUMN_NAME + "/" + target.getValue().getAttributeNames().get( - 0) + " is not accepted."); - } - if (element.getObjectType() != null) { - addTargetAttributesIfObjectTypeIsNotNull(element, target); - - } else { - addTargetAttributesIfObjectTypeIsNull(element, target); - - } - } - - private static void addTargetAttributesIfObjectTypeIsNotNull(QueryElement element, PathToken target) { - for (String attribute : target.getValue().getAttributeNames()) { - if (!element.isManyToMany() && attribute.equals(ID_COLUMN_NAME)) { - throw TiesPathException.idAmongAttributesError(); - } - if (!element.isManyToMany() && !SchemaRegistry.doesEntityContainsAttribute(element.getObjectType(), - attribute) && !SchemaRegistry.getRelationNamesByEntityName(element.getObjectType()).contains(attribute - .replace("REL_ID_", "")) && !SchemaRegistry.getRelationNames().contains(element - .getObjectType()) && !SchemaRegistry.getAssociationNamesByEntityName(element - .getObjectType()).contains(attribute.replace("REL_FK_", ""))) { - throw TiesPathException.columnNameError(element.getObjectType(), attribute); - } - if (!element.hasAttributes()) { - throw TiesPathException.grammarError(String.format("Missing 'attributes' before (%s...", target.getValue() - .getAttributeNames().get(0))); - } - element.addAttribute(attribute); - } - } - - private static void addTargetAttributesIfObjectTypeIsNull(QueryElement element, PathToken target) { - Set hasNoAttribute = new HashSet<>(); - for (String attribute : target.getValue().getAttributeNames()) { - if (attribute.equals(ID_COLUMN_NAME)) { - throw TiesPathException.idAmongAttributesError(); - } - - for (QueryElement entity : element.getChildren()) { - if (SchemaRegistry.doesEntityContainsAttribute(entity.getObjectType(), attribute)) { - entity.addAttribute(attribute); - hasNoAttribute.remove(entity); - } else { - hasNoAttribute.add(entity); - } - } - } - for (QueryElement child : hasNoAttribute) { - element.removeChild(child); - } - - } - - private static void processScopes(QueryElement root, List scopes, String domain) { - String prevToken; - - for (PathToken scope : scopes) { - QueryElement[] currentElement = { root }; - prevToken = null; - boolean isValidHop = true; - for (int i = 0; i < scope.getValue().getContainerNames().size(); ++i) { - String container = scope.getValue().getContainerNames().get(i); - isValidHop = processScopeContainer(currentElement, container, prevToken, domain); - prevToken = container; - } - if ((prevToken != null && isValidHop) && (scope.getValue().hasLeafConditions() || scope.getValue() - .hasContainsFunctionCondition()) && scope.value.getNormalizedParentPath().isEmpty() && root - .getObjectType() == null) { - - checkIdExpressions(scope.getValue().getContainsFunctionConditionLeafName(), prevToken, scope.getValue() - .getLeavesData()); - - processScopesIfRootsObjectTypeIsNull(currentElement[0].getChildren(), scope, prevToken); - - } else if (isValidHop && (scope.getValue().hasLeafConditions() || scope.getValue() - .hasContainsFunctionCondition())) { - - checkConditions(currentElement[0], scope); - - if (!root.isManyToMany() && !root.isRelConnectingSameEntity() && scope.getValue() - .hasContainsFunctionCondition() && !SchemaRegistry.doesEntityContainsAttribute(currentElement[0] - .getObjectType(), scope.getValue().getContainsFunctionConditionLeafName())) { - throw TiesPathException.columnNameError(currentElement[0].getObjectType(), scope.getValue() - .getContainsFunctionConditionLeafName()); - } - - checkIdAttributes(currentElement[0], prevToken); - - String leafName = scope.getValue().getContainsFunctionConditionLeafName(); - - checkIdExpressions(leafName, prevToken, scope.getValue().getLeavesData()); - - currentElement[0].addFilter(scope.getType(), scope.getValue()); - } - } - } - - private static void checkIdAttributes(QueryElement currentElement, String prevToken) { - if (!currentElement.hasFilters() && !prevToken.equals(ID_COLUMN_NAME)) { - throw TiesPathException.grammarError("Missing 'attributes' before '[''"); - } - } - - private static void checkIdExpressions(String leafName, String prevToken, List leavesData) { - if (leavesData != null) { - List leavesDataWithId = leavesData.stream().filter(leaf -> leaf.getName().equals( - ID_COLUMN_NAME)).toList(); - if ((!leavesDataWithId.isEmpty() && !prevToken.equals(ID_COLUMN_NAME)) || ((leavesData - .size() > 1 || leavesDataWithId.size() != 1) && prevToken.equals(ID_COLUMN_NAME))) { - throw TiesPathException.grammarError("Expression is not accepted"); - } - } - - if (leafName != null && (leafName.equals(ID_COLUMN_NAME) && !prevToken.equals( - ID_COLUMN_NAME)) || leafName != null && (!leafName.equals(ID_COLUMN_NAME) && prevToken.equals( - ID_COLUMN_NAME))) { - throw TiesPathException.grammarError("Expression is not accepted"); - } - } - - private static boolean processScopeContainer(QueryElement[] currentElement, String container, String prevToken, - String domain) { - if (SchemaRegistry.isValidEntityName(container)) { - if (prevToken != null) { - throw TiesPathException.grammarError(String.format("Missing ';' or '|' before %s", container)); - } - if (currentElement[0].getObjectType() != null && !currentElement[0].isManyToMany() && !currentElement[0] - .isRelConnectingSameEntity() && !SchemaRegistry.hasDirectHopBetween(currentElement[0].getObjectType(), - container)) { - return false; - } - if (currentElement[0].getObjectType() == null && !SchemaRegistry.getEntityNamesByDomain(domain).contains( - container)) { - throw TiesPathException.grammarError(String.format("%s is not part of %s domain", container, domain)); - } - currentElement[0].addChild(new QueryElement(container)); - currentElement[0] = currentElement[0].getChild(container); - } - processScopeContainerIfContainerIsAttributesOrId(currentElement[0], container, prevToken); - - return true; - } - - private static void processScopeContainerIfContainerIsAttributesOrId(QueryElement currentElement, String container, - String prevToken) { - if ((container.equals(ATTRIBUTES) || container.equals(ID_COLUMN_NAME)) && prevToken == null && currentElement - .getObjectType() == null) { - for (QueryElement entity : currentElement.getChildren()) { - addScopeFilter(entity, container, prevToken); - } - } else if (container.equals(ATTRIBUTES) || container.equals(ID_COLUMN_NAME)) { - addScopeFilter(currentElement, container, prevToken); - } - } - - private static void addScopeFilter(QueryElement element, String container, String prevToken) { - if (container.equals(prevToken)) { - throw TiesPathException.grammarError(String.format("Missing ';' or '|' before %s", container)); - } - if (!element.hasFilters()) { - element.setFilters(new EnumMap<>(TokenType.class)); - } - } - - private static void checkConditions(QueryElement element, PathToken scope) { - if (element.getObjectType() != null) { - if (scope.getValue().hasLeafConditions()) { - for (TiesPathQuery.DataLeaf leaf : scope.getValue().getLeavesData()) { - if (!element.isManyToMany() && !element.isRelConnectingSameEntity() && !SchemaRegistry - .doesEntityContainsAttribute(element.getObjectType(), leaf.getName())) { - throw TiesPathException.columnNameError(element.getObjectType(), leaf.getName()); - } - } - } - if (!element.isManyToMany() && !element.isRelConnectingSameEntity() && scope.getValue() - .hasContainsFunctionCondition() && !SchemaRegistry.doesEntityContainsAttribute(element.getObjectType(), - scope.getValue().getContainsFunctionConditionLeafName())) { - throw TiesPathException.columnNameError(element.getObjectType(), scope.getValue() - .getContainsFunctionConditionLeafName()); - } - } - - } - - private static void processScopesIfRootsObjectTypeIsNull(List elements, PathToken scope, - String prevToken) { - processScopesIfRootsObjectTypeIsNullHasLeafCondition(elements, scope, prevToken); - processScopesIfRootsObjectTypeIsNullHasContainsCondition(elements, scope, prevToken); - } - - private static void processScopesIfRootsObjectTypeIsNullHasLeafCondition(List elements, PathToken scope, - String prevToken) { - - if (scope.getValue().hasLeafConditions()) { - int counter = 0; - boolean anyOfElementsContainsLeaf = true; - for (QueryElement element : elements) { - for (TiesPathQuery.DataLeaf leaf : scope.getValue().getLeavesData()) { - checkIdAttributes(element, prevToken); - if (!SchemaRegistry.doesEntityContainsAttribute(element.getObjectType(), leaf.getName())) { - anyOfElementsContainsLeaf = false; - break; - } - } - if (anyOfElementsContainsLeaf) { - element.addFilter(TokenType.OR, scope.getValue()); - counter++; - } - - anyOfElementsContainsLeaf = true; - } - if (counter == 0) { - throw TiesPathException.grammarError( - "None of the entities in domain has the attribute that was provided in scopeFilter"); - } - } - } - - private static void processScopesIfRootsObjectTypeIsNullHasContainsCondition(List elements, - PathToken scope, String prevToken) { - - if (scope.getValue().hasContainsFunctionCondition()) { - boolean anyOfElementsContainsLeaf = false; - for (QueryElement element : elements) { - checkIdAttributes(element, prevToken); - if (SchemaRegistry.doesEntityContainsAttribute(element.getObjectType(), scope.getValue() - .getContainsFunctionConditionLeafName())) { - element.addFilter(TokenType.OR, scope.getValue()); - anyOfElementsContainsLeaf = true; - } - } - if (!anyOfElementsContainsLeaf) { - throw TiesPathException.grammarError( - "None of the entities in domain has the attribute that was provided in scopeFilter"); - } - } - } - - @Getter - @Setter - @AllArgsConstructor - private static class PathToken { - private TokenType type; - private TiesPathQuery value; - } - - @Getter - @AllArgsConstructor - private static class TableJoinConnection { - private RelationshipDataLocation relationshipDataLocation; - private String tableName; - private List conditions; - private boolean relConnectingSameEntity; - } -} diff --git a/teiv/src/main/java/org/oran/smo/teiv/utils/query/exception/TiesPathException.java b/teiv/src/main/java/org/oran/smo/teiv/utils/query/exception/TiesPathException.java index f064de5..e27e91e 100644 --- a/teiv/src/main/java/org/oran/smo/teiv/utils/query/exception/TiesPathException.java +++ b/teiv/src/main/java/org/oran/smo/teiv/utils/query/exception/TiesPathException.java @@ -26,6 +26,7 @@ import org.springframework.http.HttpStatus; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; @Getter public class TiesPathException extends RuntimeException { @@ -80,6 +81,10 @@ public class TiesPathException extends RuntimeException { return clientException("Grammar Error", "ID is not considered to be an attribute"); } + public static TiesPathException invalidQueryError() { + return clientException("Invalid query", "The provided query in scopeFilter is invalid"); + } + public static TiesPathException entityNameError(String entity) { return clientException("Grammar Error", String.format("%s is not a valid entity", entity)); } @@ -89,6 +94,29 @@ public class TiesPathException extends RuntimeException { "%s did not match any topology objects in the given domain", topologyObject)); } + public static TiesPathException invalidInnerContainer(String innerContainer) { + return clientException("Invalid data in scopeFilter", String.format("Unable to resolve %s", innerContainer)); + } + + public static TiesPathException invalidTargetFilter(Set params) { + return clientException("Invalid targetFilter content", String.format( + "%s did not match any topology objects in the given domain", String.join(", ", params))); + } + + public static TiesPathException invalidTargetFilter() { + return clientException("Invalid targetFilter content", "Given targetFilters could not be resolved"); + } + + public static TiesPathException invalidTargetFilterScopeFilterCombination() { + return clientException("Invalid targetFilter and scopeFilter content", + "Given targetFilter and scopeFilter can not be combined"); + } + + public static TiesPathException invalidScopeFilter(String leaf) { + return clientException("Invalid scopeFilter content", String.format( + "%s did not match any topology objects in the given domain", leaf)); + } + public static TiesPathException ambiguousTopologyObject(String topologyObject) { return clientException("Invalid topology object", String.format( "%s is ambiguous, %s matches multiple topology object types", topologyObject, topologyObject)); @@ -113,8 +141,8 @@ public class TiesPathException extends RuntimeException { return clientException("Filter Error", "TopologyObjects given in scopeFilter and targetFilter are not matching"); } - private static TiesPathException clientExceptionWithDefaultResponse(final String message, final String details) { - return new TiesPathException(message, details, HttpStatus.BAD_REQUEST, defaultResponse); + public static TiesPathException invalidQueryCondition(String details) { + return clientException("Invalid query condition", details); } private TiesPathException(final String message, final String details, final HttpStatus httpStatus, diff --git a/teiv/src/main/resources/application.yaml b/teiv/src/main/resources/application.yaml index a7e609c..8bacf50 100644 --- a/teiv/src/main/resources/application.yaml +++ b/teiv/src/main/resources/application.yaml @@ -72,6 +72,9 @@ spring: caching: consumer-data-ttl-ms: 60000 +consumer-data: + batch-size: 100 + endpoints.health.sensitive: "false" info.app.name: '@name@' info.app.description: Topology Exposure and Inventory Service @@ -116,12 +119,13 @@ kafka: retry-attempts: 2147483647 retry-interval-ms: 1000 topology-ingestion: + topic: + name: topology-inventory-ingestion + partitions: 4 + replicas: 3 + retention-ms: 86400000 + retention-bytes: 104857600 consumer: - topic: - name: topology-inventory-ingestion - partitions: 4 - replicas: 3 - retention-ms: 86400000 group-id: topology-inventory-ingestion-consumer auto-offset-reset: earliest max-poll-records: 500 @@ -136,7 +140,4 @@ database: retry-policies: deadlock: retry-attempts: 10 - retry-backoff-ms: 200 - -feature_flags: - use_alternate_delete_logic: false \ No newline at end of file + retry-backoff-ms: 200 \ No newline at end of file diff --git a/teiv/src/main/resources/logback-json.xml b/teiv/src/main/resources/logback-json.xml index 6eba710..3db898e 100644 --- a/teiv/src/main/resources/logback-json.xml +++ b/teiv/src/main/resources/logback-json.xml @@ -22,17 +22,13 @@ - 0.3.0 - false - false - [ignore] - version + + version + 1.2.0 + timestamp - thread - logger - [ignore] @@ -42,8 +38,29 @@ true { - "service_id": "${SERVICE_ID:-unknown}", - "correlation_id": "%mdc{X-B3-TraceId}" + "service_id": "${SERVICE_ID:-unknown}", + "message": "%msg" + } + + + + true + + { + "facility": "%X{facility}", + "subject": "%X{subject}", + "extra_data": { + "logger": "%logger", + "thread_info": { + "thread_name": "%thread" + }, + "dst": { + "trace_id": "%mdc{traceId}" + }, + "exception": { + "stack_trace": "%xEx" + } + } } @@ -52,8 +69,10 @@ - + + + diff --git a/teiv/src/test/java/org/oran/smo/teiv/CoreApplicationTest.java b/teiv/src/test/java/org/oran/smo/teiv/CoreApplicationTest.java index ed557f5..8cc7a89 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/CoreApplicationTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/CoreApplicationTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.oran.smo.teiv.utils.TiesTestConstants.APPLICATION_JSON; import java.util.Objects; @@ -55,8 +56,6 @@ class CoreApplicationTest { @MockBean private SchemaHandler schemaHandler; - private final String ACCEPT_TYPE = "application/json"; - @Test void testMetricsAvailable() throws Exception { // spotless:off @@ -97,6 +96,9 @@ class CoreApplicationTest { Assertions.assertTrue(result.getResponse().getContentAsString().contains("ties_exposure_http_get_relationship_by_id_fail_total")); Assertions.assertTrue(result.getResponse().getContentAsString().contains("ties_exposure_http_get_relationships_by_type_fail_total")); Assertions.assertTrue(result.getResponse().getContentAsString().contains("ties_exposure_http_get_relationships_by_entity_id_fail_total")); + + Assertions.assertTrue(result.getResponse().getContentAsString().contains("ties_exposure_http_update_classifiers_fail_total")); + Assertions.assertTrue(result.getResponse().getContentAsString().contains("ties_exposure_http_update_decorators_fail_total")); // spotless:on } @@ -109,27 +111,29 @@ class CoreApplicationTest { "getTopologyEntityTypes:/domains/RAN_LOGICAL/entity-types", "getTopologyRelationshipTypes:/domains/RAN_LOGICAL/relationship-types" }, delimiter = ':') public void testPaginationRelatedEndpoints(String method, String url) throws Exception { - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("offset", "-1").accept(ACCEPT_TYPE)).andExpect(status() - .isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result.getResolvedException()) - .getMessage(), method + ".offset: must be greater than or equal to 0")); - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "0").accept(ACCEPT_TYPE)).andExpect(status() - .isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result.getResolvedException()) - .getMessage(), method + ".limit: must be greater than or equal to 1")); - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "501").accept(ACCEPT_TYPE)).andExpect(status() - .isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result.getResolvedException()) - .getMessage(), method + ".limit: must be less than or equal to 500")); + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("offset", "-1").accept(APPLICATION_JSON)).andExpect( + status().isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result + .getResolvedException()).getMessage(), method + ".offset: must be greater than or equal to 0")); + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "0").accept(APPLICATION_JSON)).andExpect( + status().isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result + .getResolvedException()).getMessage(), method + ".limit: must be greater than or equal to 1")); + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "501").accept(APPLICATION_JSON)).andExpect( + status().isBadRequest()).andExpect(result -> assertEquals(Objects.requireNonNull(result + .getResolvedException()).getMessage(), method + ".limit: must be less than or equal to 500")); - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("offset", "0").accept(ACCEPT_TYPE)).andExpect(result -> { - if (result.getResponse().getStatus() != HttpStatus.OK.value()) - assertNotEquals(ConstraintViolationException.class, Objects.requireNonNull(result.getResolvedException()) - .getClass()); - }); - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "1").accept(ACCEPT_TYPE)).andExpect(result -> { - if (result.getResponse().getStatus() != HttpStatus.OK.value()) - assertNotEquals(ConstraintViolationException.class, Objects.requireNonNull(result.getResolvedException()) - .getClass()); - }); - mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "500").accept(ACCEPT_TYPE)).andExpect( + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("offset", "0").accept(APPLICATION_JSON)).andExpect( + result -> { + if (result.getResponse().getStatus() != HttpStatus.OK.value()) + assertNotEquals(ConstraintViolationException.class, Objects.requireNonNull(result + .getResolvedException()).getClass()); + }); + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "1").accept(APPLICATION_JSON)).andExpect( + result -> { + if (result.getResponse().getStatus() != HttpStatus.OK.value()) + assertNotEquals(ConstraintViolationException.class, Objects.requireNonNull(result + .getResolvedException()).getClass()); + }); + mvc.perform(get(TiesConstants.REQUEST_MAPPING + url).param("limit", "500").accept(APPLICATION_JSON)).andExpect( result -> { if (result.getResponse().getStatus() != HttpStatus.OK.value()) assertNotEquals(ConstraintViolationException.class, Objects.requireNonNull(result diff --git a/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicatorTest.java b/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicatorTest.java index 4a3a5db..183eae8 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicatorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesExposureHealthIndicatorTest.java @@ -20,14 +20,15 @@ */ package org.oran.smo.teiv.controller.health; +import static org.mockito.Mockito.doReturn; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import org.oran.smo.teiv.availability.DependentServiceAvailabilityKafka; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.service.SchemaCleanUpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -54,28 +55,21 @@ class TiesExposureHealthIndicatorTest { @MockBean private PostgresSchemaLoader postgresSchemaLoader; + @MockBean + ModelRepository modelRepository; + @MockBean + SchemaCleanUpService schemaCleanUpService; - @AfterEach - protected void tearDown() { - healthStatus.setSchemaInitialized(false); - } + @MockBean + private SchemaHandler schemaHandler; - @Test - void upAndHealthy() throws Exception { - mvc.perform(get(readinessProbePath).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect( - content().json("{'status' : 'UP'}")); - mvc.perform(get(livenessProbePath).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect( - content().json("{'status' : 'UP'}")); - mvc.perform(get(tiesExposureProbePath).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()) - .andExpect(content().json(String.format("{'status':'UP','details':{'UP': '%s is UP and Healthy.'}}", - SERVICE_NAME))); - } + @MockBean + private DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka; @Test - void upSchemaServiceLoaded() throws Exception { - SchemaHandler schemaHandlerSpy = Mockito.spy(new SchemaHandler(postgresSchemaLoader, healthStatus)); - schemaHandlerSpy.initializeSchema(); - Assertions.assertTrue(healthStatus.isSchemaInitialized()); + void upAndHealthy() throws Exception { + healthStatus.setSchemaInitialized(true); + doReturn(true).when(dependentServiceAvailabilityKafka).checkService(); mvc.perform(get(readinessProbePath).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect( content().json("{'status' : 'UP'}")); mvc.perform(get(livenessProbePath).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect( @@ -88,6 +82,7 @@ class TiesExposureHealthIndicatorTest { @Test void downSchemaServiceNotLoaded() throws Exception { healthStatus.setSchemaInitialized(false); + doReturn(true).when(dependentServiceAvailabilityKafka).checkService(); performReadinessGroupProbesDownWithMessage(" Schema is yet to be initialized."); } diff --git a/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicatorTest.java b/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicatorTest.java index 75fbed1..312cff0 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicatorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/controller/health/TiesIngestionHealthIndicatorTest.java @@ -29,6 +29,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.service.SchemaCleanUpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -44,7 +46,7 @@ import org.oran.smo.teiv.startup.SchemaHandler; @AutoConfigureMockMvc @SpringBootTest(properties = { "spring.profiles.active=test,ingestion", "management.endpoint.health.probes.enabled=true", "management.endpoint.health.group.readiness.include=readinessState,tiesIngestion" }) -public class TiesIngestionHealthIndicatorTest { +class TiesIngestionHealthIndicatorTest { private final String readinessProbePath = "/actuator/health/readiness"; private final String livenessProbePath = "/actuator/health/liveness"; private final String tiesIngestionProbePath = "/actuator/health/tiesIngestion"; @@ -62,6 +64,10 @@ public class TiesIngestionHealthIndicatorTest { @MockBean PostgresSchemaLoader postgresSchemaLoader; + @MockBean + ModelRepository modelRepository; + @MockBean + SchemaCleanUpService schemaCleanUpService; @AfterEach protected void tearDown() { @@ -91,7 +97,8 @@ public class TiesIngestionHealthIndicatorTest { @Test void downKafkaUnavailable() throws Exception { - SchemaHandler schemaHandlerSpy = Mockito.spy(new SchemaHandler(postgresSchemaLoader, healthStatus)); + SchemaHandler schemaHandlerSpy = Mockito.spy(new SchemaHandler(postgresSchemaLoader, healthStatus, modelRepository, + schemaCleanUpService)); schemaHandlerSpy.initializeSchema(); assertTrue(healthStatus.isSchemaInitialized()); doReturn(false).when(spiedDependentServiceAvailabilityKafka).checkService(); diff --git a/teiv/src/test/java/org/oran/smo/teiv/db/TestPostgresqlContainer.java b/teiv/src/test/java/org/oran/smo/teiv/db/TestPostgresqlContainer.java index db7f18a..ff0cb66 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/db/TestPostgresqlContainer.java +++ b/teiv/src/test/java/org/oran/smo/teiv/db/TestPostgresqlContainer.java @@ -43,7 +43,12 @@ public class TestPostgresqlContainer extends PostgreSQLContainer { + + private static TestPostgresqlContainerV1 container; + + private TestPostgresqlContainerV1(DockerImageName image) { + super(image); + } + + public static TestPostgresqlContainerV1 getInstance() { + if (container == null) { + container = new TestPostgresqlContainerV1(DockerImageName.parse("postgis/postgis:13-3.4-alpine") + .asCompatibleSubstituteFor("postgres")); + container.withCopyFileToContainer(MountableFile.forClasspathResource( + "pgsqlschema/01_init-oran-smo-teiv-model-v1.sql"), "/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql"); + container.withCopyFileToContainer(MountableFile.forClasspathResource( + "pgsqlschema/00_init-oran-smo-teiv-data-v1.sql"), "/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql"); + container.withCopyFileToContainer(MountableFile.forClasspathResource( + "pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql"), + "/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql"); + container.withCopyFileToContainer(MountableFile.forClasspathResource("pgsqlschema/model.sql"), + "/pgsqlschema/model.sql"); + container.withCopyFileToContainer(MountableFile.forClasspathResource("pgsqlschema/data-v1.sql"), + "/pgsqlschema/data-v1.sql"); + container.withCopyFileToContainer(MountableFile.forClasspathResource("pgsqlschema/consumer-data-v1.sql"), + "/pgsqlschema/consumer-data-v1.sql"); + container.setCommand("postgres", "-c", "max_connections=2000"); + + container.start(); + try { + container.execInContainer("psql", "-U", "test", "-w", "-f", + "/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql", "--set=pguser=\"test\";"); + container.execInContainer("psql", "-U", "test", "-w", "-f", "/pgsqlschema/model.sql", + "--set=pguser=\"test\";"); + container.execInContainer("psql", "-U", "test", "-w", "-f", + "/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql", "--set=pguser=\"test\";"); + container.execInContainer("psql", "-U", "test", "-w", "-f", + "/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql", "--set=pguser=\"test\";"); + container.execInContainer("psql", "-U", "test", "-w", "-f", "/pgsqlschema/consumer-data-v1.sql", + "--set=pguser=\"test\";"); + } catch (UnsupportedOperationException | IOException | InterruptedException e) { + throw new RuntimeException(e.getMessage()); + } + } + return container; + } + + public static void loadSampleData() { + try { + container.execInContainer("psql", "-U", "test", "-w", "-f", "/pgsqlschema/data-v1.sql", + "--set=pguser=\"test\";"); + container.execInContainer("psql", "-U", "test", "-w", "-f", "/pgsqlschema/consumer-data-v1.sql", + "--set=pguser=\"test\";"); + } catch (UnsupportedOperationException | IOException | InterruptedException e) { + throw new RuntimeException(e.getMessage()); + } + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedNonXPathTest.java b/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedNonXPathTest.java deleted file mode 100644 index d6dea51..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedNonXPathTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.e2e; - -import org.oran.smo.teiv.api.model.OranTeivDomains; -import org.oran.smo.teiv.api.model.OranTeivDomainsItemsInner; -import org.oran.smo.teiv.api.model.OranTeivEntityTypes; -import org.oran.smo.teiv.api.model.OranTeivEntityTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; -import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; - -import org.oran.smo.teiv.db.TestPostgresqlContainer; -import org.oran.smo.teiv.exposure.data.rest.controller.DataRestController; -import org.oran.smo.teiv.schema.PostgresSchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.jooq.DSLContext; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import javax.sql.DataSource; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static org.oran.smo.teiv.utils.TiesConstants.TEIV_DOMAIN; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; - -@Slf4j -@ActiveProfiles({ "test", "exposure" }) -@SpringBootTest -public class DataControllerE2EContainerizedNonXPathTest { - - public static final String ACCEPT_TYPE = "application/yang+json"; - - @Autowired - public DataRestController underTest; - public static TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); - - @Autowired - DSLContext writeDataDslContext; - - @DynamicPropertySource - static void setProperties(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.read.jdbc-url", () -> postgreSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.read.username", () -> postgreSQLContainer.getUsername()); - registry.add("spring.datasource.read.password", () -> postgreSQLContainer.getPassword()); - - registry.add("spring.datasource.write.jdbc-url", () -> postgreSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.write.username", () -> postgreSQLContainer.getUsername()); - registry.add("spring.datasource.write.password", () -> postgreSQLContainer.getPassword()); - } - - @BeforeAll - public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { - String url = postgreSQLContainer.getJdbcUrl(); - DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); - DSLContext dslContext = DSL.using(ds, SQLDialect.POSTGRES); - PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(dslContext, new ObjectMapper()); - postgresSchemaLoader.loadSchemaRegistry(); - } - - @BeforeEach - public void deleteAll() { - writeDataDslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach( - t -> writeDataDslContext.truncate(t).cascade().execute()); - TestPostgresqlContainer.loadSampleData(); - } - - @Test - public void testGetAllDomains() { - final OranTeivDomains responseMessage = underTest.getAllDomains(ACCEPT_TYPE, 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage); - Assertions.assertEquals(9, responseMessage.getItems().size()); - - Map expectedData = new HashMap<>(); - expectedData.put("name", TEIV_DOMAIN); - expectedData.put("entityTypes", "/domains/" + TEIV_DOMAIN + "/entity-types"); - expectedData.put("relationshipTypes", "/domains/" + TEIV_DOMAIN + "/relationship-types"); - - OranTeivDomainsItemsInner actualItem = responseMessage.getItems().get(8); - - Assertions.assertEquals(expectedData.get("name"), actualItem.getName()); - Assertions.assertEquals(expectedData.get("entityTypes"), actualItem.getEntityTypes().getHref()); - Assertions.assertEquals(expectedData.get("relationshipTypes"), actualItem.getRelationshipTypes().getHref()); - - Map expectedDataCloud = new HashMap<>(); - expectedDataCloud.put("name", "CLOUD"); - expectedDataCloud.put("entityTypes", "/domains/CLOUD/entity-types"); - expectedDataCloud.put("relationshipTypes", "/domains/CLOUD/relationship-types"); - - OranTeivDomainsItemsInner actualItemCloud = responseMessage.getItems().get(0); - - Assertions.assertEquals(expectedDataCloud.get("name"), actualItemCloud.getName()); - Assertions.assertEquals(expectedDataCloud.get("entityTypes"), actualItemCloud.getEntityTypes().getHref()); - Assertions.assertEquals(expectedDataCloud.get("relationshipTypes"), actualItemCloud.getRelationshipTypes() - .getHref()); - - Map expectedDataLogicalToEquipment = new HashMap<>(); - expectedDataLogicalToEquipment.put("name", "EQUIPMENT_TO_RAN"); - expectedDataLogicalToEquipment.put("entityTypes", "/domains/EQUIPMENT_TO_RAN/entity-types"); - expectedDataLogicalToEquipment.put("relationshipTypes", "/domains/EQUIPMENT_TO_RAN/relationship-types"); - - OranTeivDomainsItemsInner actualItemLogicalToEquipment = responseMessage.getItems().get(3); - - Assertions.assertEquals(expectedDataLogicalToEquipment.get("name"), actualItemLogicalToEquipment.getName()); - Assertions.assertEquals(expectedDataLogicalToEquipment.get("entityTypes"), actualItemLogicalToEquipment - .getEntityTypes().getHref()); - Assertions.assertEquals(expectedDataLogicalToEquipment.get("relationshipTypes"), actualItemLogicalToEquipment - .getRelationshipTypes().getHref()); - } - - @Test - public void testGetTopologyEntityTypes() { - final OranTeivEntityTypes responseMessage = underTest.getTopologyEntityTypes(ACCEPT_TYPE, "EQUIPMENT_TO_RAN", 0, 20) - .getBody(); - - Assertions.assertNotNull(responseMessage); - Assertions.assertEquals(20, responseMessage.getItems().size()); - - Map expectedSite = new HashMap<>(); - expectedSite.put("name", "Site"); - expectedSite.put("entities", "/domains/EQUIPMENT_TO_RAN/entity-types/Site/entities"); - - OranTeivEntityTypesItemsInner item1 = responseMessage.getItems().stream().filter(items -> { - return "Site".equals(items.getName()); - }).findFirst().get(); - Assertions.assertEquals(expectedSite.get("name"), item1.getName()); - Assertions.assertEquals(expectedSite.get("entities"), item1.getEntities().getHref()); - - Map expectedNRCellCu = new HashMap<>(); - expectedNRCellCu.put("name", "NRCellCU"); - expectedNRCellCu.put("entities", "/domains/EQUIPMENT_TO_RAN/entity-types/NRCellCU/entities"); - - OranTeivEntityTypesItemsInner item2 = responseMessage.getItems().stream().filter(items -> { - return "NRCellCU".equals(items.getName()); - }).findFirst().get(); - Assertions.assertEquals(expectedNRCellCu.get("name"), item2.getName()); - Assertions.assertEquals(expectedNRCellCu.get("entities"), item2.getEntities().getHref()); - - Map expectedGNBCUUFunction = new HashMap<>(); - expectedGNBCUUFunction.put("name", "GNBCUUPFunction"); - expectedGNBCUUFunction.put("entities", "/domains/EQUIPMENT_TO_RAN/entity-types/GNBCUUPFunction/entities"); - - OranTeivEntityTypesItemsInner item3 = responseMessage.getItems().stream().filter(items -> { - return "GNBCUUPFunction".equals(items.getName()); - }).findFirst().get(); - Assertions.assertEquals(expectedGNBCUUFunction.get("name"), item3.getName()); - Assertions.assertEquals(expectedGNBCUUFunction.get("entities"), item3.getEntities().getHref()); - } - - @Test - public void testGetTopologyRelationshipTypes() { - final OranTeivRelationshipTypes responseMessage = underTest.getTopologyRelationshipTypes(ACCEPT_TYPE, - "EQUIPMENT_TO_RAN", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage); - Assertions.assertEquals(20, responseMessage.getItems().size()); - - Map expectedData1 = new HashMap<>(); - expectedData1.put("name", "NRCELLDU_USES_NRSECTORCARRIER"); - expectedData1.put("relationships", - "/domains/EQUIPMENT_TO_RAN/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships"); - - OranTeivRelationshipTypesItemsInner item1 = responseMessage.getItems().get(14); - Assertions.assertEquals(expectedData1.get("name"), item1.getName()); - Assertions.assertEquals(expectedData1.get("relationships"), item1.getRelationships().getHref()); - - Map expectedData2 = new HashMap<>(); - expectedData2.put("name", "ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE"); - expectedData2.put("relationships", - "/domains/EQUIPMENT_TO_RAN/relationship-types/ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE/relationships"); - - OranTeivRelationshipTypesItemsInner item2 = responseMessage.getItems().get(1); - Assertions.assertEquals(expectedData2.get("name"), item2.getName()); - Assertions.assertEquals(expectedData2.get("relationships"), item2.getRelationships().getHref()); - - Map expectedData3 = new HashMap<>(); - expectedData3.put("name", "SECTOR_GROUPS_ANTENNAMODULE"); - expectedData3.put("relationships", - "/domains/EQUIPMENT_TO_RAN/relationship-types/SECTOR_GROUPS_ANTENNAMODULE/relationships"); - - OranTeivRelationshipTypesItemsInner item3 = responseMessage.getItems().get(17); - Assertions.assertEquals(expectedData3.get("name"), item3.getName()); - Assertions.assertEquals(expectedData3.get("relationships"), item3.getRelationships().getHref()); - } - - @Test - public void testGetTopologyById() { - final Object responseMessage = underTest.getTopologyById(ACCEPT_TYPE, "RAN", "Sector", - "2F445AA5744FA3D230FD6838531F1407").getBody(); - - Assertions.assertNotNull(responseMessage); - - Map expectedResponse = new HashMap<>(); - Map innerMap = new HashMap<>(); - Map attributes = new HashMap<>(); - - attributes.put("sectorId", 1); - attributes.put("geo-location", "POINT(59.4019881 17.9419888)"); - attributes.put("sectorId", 1); - attributes.put("azimuth", 1); - - innerMap.put("attributes", attributes); - innerMap.put("id", "2F445AA5744FA3D230FD6838531F1407"); - innerMap.put("sourceIds", Collections.EMPTY_LIST); - - expectedResponse.put("o-ran-smo-teiv-ran:Sector", Collections.singletonList(innerMap)); - - Map actualResponse = (Map) responseMessage; - - Assertions.assertEquals(expectedResponse.size(), actualResponse.size()); - for (Map.Entry entry : expectedResponse.entrySet()) { - String key = entry.getKey(); - Object expectedValue = entry.getValue(); - Object actualValue = actualResponse.get(key); - if (expectedValue instanceof List && actualValue instanceof List) { - List expectedList = (List) expectedValue; - List actualList = (List) actualValue; - Assertions.assertEquals(expectedList.size(), actualList.size()); - for (int i = 0; i < expectedList.size(); i++) { - Object expectedMap = expectedList.get(i); - Object actualMap = actualList.get(i); - Assertions.assertTrue(expectedMap instanceof Map); - Assertions.assertTrue(actualMap instanceof Map); - String expectedAttributesString = ((Map) expectedMap).get("attributes").toString(); - String actualAttributesString = ((Map) actualMap).get("attributes").toString(); - Assertions.assertEquals(expectedAttributesString, actualAttributesString); - } - } else { - Assertions.assertEquals(expectedValue, actualValue); - } - } - } - - @Test - public void testGetAllRelationshipsForEntityId() { - final OranTeivRelationshipsResponseMessage responseMessage = underTest.getAllRelationshipsForEntityId(ACCEPT_TYPE, - "RAN", "Sector", "2F445AA5744FA3D230FD6838531F1407", "", "", 0, 10).getBody(); - - Assertions.assertNotNull(responseMessage); - Assertions.assertEquals(0, responseMessage.getTotalCount()); - Assertions.assertTrue(responseMessage.getItems().isEmpty()); - - final OranTeivRelationshipsResponseMessage responseMessage2 = underTest.getAllRelationshipsForEntityId(ACCEPT_TYPE, - "RAN", "GNBDUFunction", "1050570EBB1315E1AE7A9FD5E1400A00", "", "", 0, 10).getBody(); - - Assertions.assertNotNull(responseMessage2); - Assertions.assertEquals(1, responseMessage2.getTotalCount()); - - Map innerResponse = new HashMap<>(); - innerResponse.put("bSide", "1050570EBB1315E1AE7A9FD5E1400A00"); - innerResponse.put("aSide", "6F02817AFE4D53237DB235EBE5378613"); - innerResponse.put("id", - "urn:base64:TWFuYWdlZEVsZW1lbnQ6NkYwMjgxN0FGRTRENTMyMzdEQjIzNUVCRTUzNzg2MTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjEwNTA1NzBFQkIxMzE1RTFBRTdBOUZENUUxNDAwQTAw"); - Map response = new HashMap<>(); - response.put("o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", List.of(innerResponse)); - Assertions.assertEquals(response, responseMessage2.getItems().get(0)); - } - - @Test - public void testGetRelationshipById() { - final Object responseMessage = underTest.getRelationshipById(ACCEPT_TYPE, "CLOUD", - "NODECLUSTER_LOCATED_AT_CLOUDSITE", - "urn:base64:Tm9kZUNsdXN0ZXI6MDE1QzJEREJEN0FDNzIyQjM0RUQ2QTIwRURFRUI5QzM6TE9DQVRFRF9BVDpDbG91ZFNpdGU6MTZFRTE3QUU4OURGMTFCNjlFOTRCM0Y2ODI3QzJDMEU=") - .getBody(); - - Assertions.assertNotNull(responseMessage); - Assertions.assertTrue(responseMessage instanceof Map); - - Map>> responseMap = (Map>>) responseMessage; - - Assertions.assertTrue(responseMap.containsKey("o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE")); - List> relationshipList = responseMap.get( - "o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE"); - - Assertions.assertNotNull(relationshipList); - Assertions.assertFalse(relationshipList.isEmpty()); - - for (Map relationship : relationshipList) { - Assertions.assertTrue(relationship.containsKey("bSide")); - Assertions.assertTrue(relationship.containsKey("aSide")); - Assertions.assertTrue(relationship.containsKey("id")); - Assertions.assertTrue(relationship.containsKey("sourceIds")); - } - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedTest.java b/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedTest.java deleted file mode 100644 index 8a6cf1f..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/e2e/DataControllerE2EContainerizedTest.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.e2e; - -import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; -import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; -import org.oran.smo.teiv.db.TestPostgresqlContainer; -import org.oran.smo.teiv.exposure.data.rest.controller.DataRestController; -import org.oran.smo.teiv.schema.PostgresSchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.jooq.DSLContext; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; - -import javax.sql.DataSource; - -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; - -import java.util.*; - -@Slf4j -@ActiveProfiles({ "test", "exposure" }) -@SpringBootTest -public class DataControllerE2EContainerizedTest { - - public static final String ACCEPT_TYPE = "application/yang+json"; - - @Autowired - public DataRestController underTest; - public static TestPostgresqlContainer postgresSQLContainer = TestPostgresqlContainer.getInstance(); - - @Autowired - DSLContext writeDataDslContext; - - @DynamicPropertySource - static void setProperties(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.read.jdbc-url", () -> postgresSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.read.username", () -> postgresSQLContainer.getUsername()); - registry.add("spring.datasource.read.password", () -> postgresSQLContainer.getPassword()); - - registry.add("spring.datasource.write.jdbc-url", () -> postgresSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.write.username", () -> postgresSQLContainer.getUsername()); - registry.add("spring.datasource.write.password", () -> postgresSQLContainer.getPassword()); - } - - @BeforeAll - public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { - String url = postgresSQLContainer.getJdbcUrl(); - DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); - DSLContext dslContext = DSL.using(ds, SQLDialect.POSTGRES); - PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(dslContext, new ObjectMapper()); - postgresSchemaLoader.loadSchemaRegistry(); - } - - @BeforeEach - public void deleteAll() { - writeDataDslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach( - t -> writeDataDslContext.truncate(t).cascade().execute()); - TestPostgresqlContainer.loadSampleData(); - } - - @Test - public void getRelationshipsByTypeWithoutScopeFilterTest() { - final OranTeivRelationshipsResponseMessage responseMessage1 = underTest.getRelationshipsByType(ACCEPT_TYPE, "RAN", - "NRCELLDU_USES_NRSECTORCARRIER", null, "", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - Map innerResponse = new HashMap<>(); - innerResponse.put("bSide", "E49D942C16E0364E1E0788138916D70C"); - innerResponse.put("aSide", "B480427E8A0C0B8D994E437784BB382F"); - innerResponse.put("id", - "urn:base64:TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM="); - Map response = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER", List.of(innerResponse)); - Assertions.assertEquals(response, responseMessage1.getItems().get(0)); - } - - @Test - public void getRelationshipsByTypeWithScopeFilterTest() { - final OranTeivRelationshipsResponseMessage responseMessage1 = underTest.getRelationshipsByType(ACCEPT_TYPE, "RAN", - "SECTOR_GROUPS_NRCELLDU", null, "/NRCellDU/attributes[@cellLocalId=1]", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - Map innerResponse = new HashMap<>(); - innerResponse.put("bSide", "98C3A4591A37718E1330F0294E23B62A"); - innerResponse.put("aSide", "F5128C172A70C4FCD4739650B06DE9E2"); - innerResponse.put("id", - "urn:base64:U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ=="); - Map response = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU", List.of(innerResponse)); - Assertions.assertEquals(response, responseMessage1.getItems().get(0)); - } - - @Test - public void getTopologyByEntityTypeNameWithScopeFilterTest() { - final OranTeivEntitiesResponseMessage responseMessage1 = underTest.getTopologyByEntityTypeName( - - ACCEPT_TYPE, "RAN", "NRCellDU", null, "/NRCellDU/attributes[@cellLocalId=1]", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - Map innerResponse = new HashMap<>(); - innerResponse.put("id", "98C3A4591A37718E1330F0294E23B62A"); - - Map response = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:NRCellDU", List.of(innerResponse)); - Assertions.assertEquals(response, responseMessage1.getItems().get(0)); - } - - @Test - public void getTopologyByEntityTypeWithoutScopeFilterTest() { - final OranTeivEntitiesResponseMessage responseMessage1 = underTest.getTopologyByEntityTypeName( - - ACCEPT_TYPE, "RAN", "NRCellDU", null, "", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - - List ids = new ArrayList<>(); - ids.add("67A1BDA10B5AF43028D07C7BE5CB1AE2"); - ids.add("76E9F605D4F37330BF0B505E94F64F11"); - ids.add("98C3A4591A37718E1330F0294E23B62A"); - ids.add("B3B0A1939EFCA654A37005B6A7F24BD7"); - ids.add("B480427E8A0C0B8D994E437784BB382F"); - ids.add("F9546E82313AC1D5E690DCD7BE55606F"); - - List> idList = new ArrayList<>(); - for (String id : ids) { - Map idMap = new HashMap<>(); - idMap.put("id", id); - idList.add(idMap); - } - - Map response = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:NRCellDU", idList); - Assertions.assertEquals(response, responseMessage1.getItems().get(0)); - } - - @Test - public void getEntitiesByDomainWithoutScopeFilter() { - final OranTeivEntitiesResponseMessage responseMessage1 = underTest.getEntitiesByDomain(ACCEPT_TYPE, "RAN", - "/NRCellDU/attributes/nCI", "", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - - @SuppressWarnings("unchecked") List> actualList = (List>) ((Map) responseMessage1 - .getItems().get(0)).get("o-ran-smo-teiv-ran:NRCellDU"); - - List> expectedList = new ArrayList<>(); - Map entity = new HashMap<>(); - - entity.put("attributes", Map.of("nCI", 1)); - entity.put("id", "98C3A4591A37718E1330F0294E23B62A"); - expectedList.add(entity); - - entity = new HashMap<>(); - entity.put("attributes", Map.of("nCI", 2)); - entity.put("id", "F9546E82313AC1D5E690DCD7BE55606F"); - expectedList.add(entity); - - entity = new HashMap<>(); - entity.put("attributes", Map.of("nCI", 3)); - entity.put("id", "B480427E8A0C0B8D994E437784BB382F"); - expectedList.add(entity); - - entity = new HashMap<>(); - entity.put("attributes", Map.of("nCI", 91)); - entity.put("id", "76E9F605D4F37330BF0B505E94F64F11"); - expectedList.add(entity); - - entity = new HashMap<>(); - entity.put("attributes", Map.of("nCI", 92)); - entity.put("id", "67A1BDA10B5AF43028D07C7BE5CB1AE2"); - expectedList.add(entity); - - entity = new HashMap<>(); - entity.put("attributes", Map.of("nCI", 93)); - entity.put("id", "B3B0A1939EFCA654A37005B6A7F24BD7"); - expectedList.add(entity); - - Assertions.assertEquals(expectedList.size(), actualList.size()); - for (int i = 0; i < expectedList.size(); i++) { - Map actualEntity = actualList.get(i); - Map expectedEntity = expectedList.get(i); - - Map actualAttributes = (Map) actualEntity.get("attributes"); - Map expectedAttributes = (Map) expectedEntity.get("attributes"); - - Assertions.assertEquals(((Number) expectedAttributes.get("nCI")).intValue(), ((Number) actualAttributes.get( - "nCI")).intValue()); - - } - } - - @Test - public void getEntitiesByDomainWithScopeFilter() { - final String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; - final OranTeivEntitiesResponseMessage responseMessage1 = underTest.getEntitiesByDomain(ACCEPT_TYPE, "RAN", - "/NRCellDU/attributes/nCI", "/NRCellDU/attributes[@cellLocalId=1]", 0, 20).getBody(); - - Assertions.assertNotNull(responseMessage1); - Assertions.assertEquals(1, responseMessage1.getItems().size()); - - Map actualResponseMap = new HashMap<>((Map) responseMessage1.getItems().get(0)); - - Map expectedResponse = new HashMap<>(); - Map innerMap = new HashMap<>(); - Map attributes = new HashMap<>(); - attributes.put("nCI", 1); - innerMap.put("id", "98C3A4591A37718E1330F0294E23B62A"); - innerMap.put("attributes", attributes); - expectedResponse.put("o-ran-smo-teiv-ran:NRCellDU", List.of(innerMap)); - - Assertions.assertEquals(expectedResponse.toString(), actualResponseMap.toString()); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/TopologyExposureApiBase.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/TopologyExposureApiBase.java index 44360ee..345472e 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/TopologyExposureApiBase.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/TopologyExposureApiBase.java @@ -20,148 +20,72 @@ */ package org.oran.smo.teiv.exposure.api.contract; -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.exposure.utils.RequestValidator; -import java.util.List; +import javax.sql.DataSource; -import org.oran.smo.teiv.api.model.OranTeivSchema; -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.api.model.OranTeivSchemaList; -import org.oran.smo.teiv.exposure.api.contract.utils.RelationshipTestUtility; -import org.oran.smo.teiv.exposure.api.contract.utils.TopologyObjectTestUtility; -import org.oran.smo.teiv.exposure.data.api.impl.DataServiceImpl; -import org.oran.smo.teiv.exposure.data.rest.controller.DataRestController; -import org.oran.smo.teiv.exposure.exception.ApplicationExceptionHandler; -import org.oran.smo.teiv.exposure.model.api.impl.ModelSchemaServiceImpl; -import org.oran.smo.teiv.exposure.model.rest.controller.ModelSchemaRestController; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; - -import org.junit.jupiter.api.AfterAll; +import org.jooq.DSLContext; +import org.jooq.SQLDialect; +import org.jooq.impl.DSL; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; +import org.oran.smo.teiv.db.TestPostgresqlContainerV1; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.module.mockmvc.RestAssuredMockMvc; -@ExtendWith(MockitoExtension.class) +import org.oran.smo.teiv.schema.PostgresSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; +import org.oran.smo.teiv.startup.SchemaHandler; + +@AutoConfigureMockMvc +@SpringBootTest public abstract class TopologyExposureApiBase { + public static TestPostgresqlContainerV1 postgresSQLContainer = TestPostgresqlContainerV1.getInstance(); - private static final ModelSchemaServiceImpl modelSchemaService = Mockito.mock(ModelSchemaServiceImpl.class); + @MockBean + private SchemaHandler schemaHandler; - private static final DataServiceImpl dataService = Mockito.mock(DataServiceImpl.class); - private static final CustomMetrics customMetrics = Mockito.mock(CustomMetrics.class); - private static final RequestValidator requestValidator = Mockito.mock(RequestValidator.class); + @Autowired + private ApplicationContext context; - @InjectMocks - private ModelSchemaRestController modelSchemaRestController; + @Autowired + private MockMvc mockMvc; - @InjectMocks - private DataRestController dataRestController; + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.read.jdbc-url", () -> postgresSQLContainer.getJdbcUrl()); + registry.add("spring.datasource.read.username", () -> postgresSQLContainer.getUsername()); + registry.add("spring.datasource.read.password", () -> postgresSQLContainer.getPassword()); - @BeforeEach - public void setup() { - mockData(); - final StandaloneMockMvcBuilder standaloneMockMvcBuilder = MockMvcBuilders.standaloneSetup(modelSchemaRestController, - dataRestController).setControllerAdvice(new ApplicationExceptionHandler()); - RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder); - } - - public void mockData() { - RelationshipTestUtility.getMockForAllRelationshipsForObjectId(dataService); - TopologyObjectTestUtility.getMockForAllTopologyObjectById(dataService); + registry.add("spring.datasource.write.jdbc-url", () -> postgresSQLContainer.getJdbcUrl()); + registry.add("spring.datasource.write.username", () -> postgresSQLContainer.getUsername()); + registry.add("spring.datasource.write.password", () -> postgresSQLContainer.getPassword()); } @BeforeAll - public static void mockModelSchemaData() { - - OranTeivSchema schemasMetaData = new OranTeivSchema(); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/schemas/o-ran-smo-teiv-cloud-to-ran/content"); - schemasMetaData.setName("o-ran-smo-teiv-cloud-to-ran"); - schemasMetaData.setDomain("CLOUD_TO_RAN"); - schemasMetaData.setRevision("2023-06-26"); - schemasMetaData.setContent(href); - - List schemaList = List.of(schemasMetaData); - - OranTeivSchemaList schemas = new OranTeivSchemaList(); - schemas.setItems(schemaList); - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref("/schemas?offset=0&limit=100"); - schemas.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref("/schemas?offset=0&limit=100"); - schemas.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref("/schemas?offset=0&limit=100"); - schemas.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref("/schemas?offset=0&limit=100"); - schemas.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref("/schemas?offset=0&limit=100"); - schemas.setLast(hrefLast); - - OranTeivSchemaList schemaQuery = new OranTeivSchemaList(); - schemaQuery.setItems(schemaList); - OranTeivHref hrefFirst1 = new OranTeivHref(); - hrefFirst1.setHref("/schemas?domain=RAN&offset=0&limit=8"); - schemaQuery.setFirst(hrefFirst1); - OranTeivHref hrefNext1 = new OranTeivHref(); - hrefNext1.setHref("/schemas?domain=RAN&offset=0&limit=8"); - schemaQuery.setNext(hrefNext1); - OranTeivHref hrefPrev1 = new OranTeivHref(); - hrefPrev1.setHref("/schemas?domain=RAN&offset=0&limit=8"); - schemaQuery.setPrev(hrefPrev1); - OranTeivHref hrefSelf1 = new OranTeivHref(); - hrefSelf1.setHref("/schemas?domain=RAN&offset=0&limit=8"); - schemaQuery.setSelf(hrefSelf1); - OranTeivHref hrefLast1 = new OranTeivHref(); - hrefLast1.setHref("/schemas?domain=RAN&offset=0&limit=8"); - schemaQuery.setLast(hrefLast1); - - OranTeivSchemaList emptyResponse = new OranTeivSchemaList(); - emptyResponse.setItems(List.of()); - OranTeivHref hrefFirst2 = new OranTeivHref(); - hrefFirst2.setHref("/schemas?domain=LOGICAL&offset=0&limit=500"); - emptyResponse.setFirst(hrefFirst2); - OranTeivHref hrefNext2 = new OranTeivHref(); - hrefNext2.setHref("/schemas?domain=LOGICAL&offset=0&limit=500"); - emptyResponse.setNext(hrefNext2); - OranTeivHref hrefPrev2 = new OranTeivHref(); - hrefPrev2.setHref("/schemas?domain=LOGICAL&offset=0&limit=500"); - emptyResponse.setPrev(hrefPrev2); - OranTeivHref hrefSelf2 = new OranTeivHref(); - hrefSelf2.setHref("/schemas?domain=LOGICAL&offset=0&limit=500"); - emptyResponse.setSelf(hrefSelf2); - OranTeivHref hrefLast2 = new OranTeivHref(); - hrefLast2.setHref("/schemas?domain=LOGICAL&offset=0&limit=500"); - emptyResponse.setLast(hrefLast2); - - String modelSchema = "module o-ran-smo-teiv-cloud-to-ran { yang-version 1.1; }"; - - Mockito.when(modelSchemaService.getSchemas(PaginationDTO.builder().offset(0).limit(100).basePath("/schemas") - .build())).thenReturn(schemas).thenThrow(new RuntimeException()); - - Mockito.when(modelSchemaService.getSchemaByName("o-ran-smo-teiv-cloud-to-ran")).thenReturn(modelSchema).thenThrow( - new RuntimeException()); - - Mockito.when(modelSchemaService.getSchemasInDomain("RAN", PaginationDTO.builder().offset(0).limit(8).basePath( - "/schemas").addPathParameters("domain", "RAN").build())).thenReturn(schemaQuery).thenThrow( - new RuntimeException()); - - Mockito.when(modelSchemaService.getSchemasInDomain("LOGICAL", PaginationDTO.builder().offset(0).limit(500).basePath( - "/schemas").addPathParameters("domain", "LOGICAL").build())).thenReturn(emptyResponse).thenThrow( - new RuntimeException()); + public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { + String url = postgresSQLContainer.getJdbcUrl(); + DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); + DSLContext dslContext = DSL.using(ds, SQLDialect.POSTGRES); + TestPostgresqlContainerV1.loadSampleData(); + PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(dslContext, new ObjectMapper()); + postgresSchemaLoader.loadSchemaRegistry(); } - @AfterAll - public static void teardown() { - Mockito.reset(modelSchemaService); + @BeforeEach + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup((WebApplicationContext) context).addFilters().build(); + + RestAssuredMockMvc.mockMvc(mockMvc); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/RelationshipTestUtility.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/RelationshipTestUtility.java deleted file mode 100644 index e80ac4e..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/RelationshipTestUtility.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.api.contract.utils; - -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.data.api.DataService; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; - -import static org.mockito.Mockito.when; - -public class RelationshipTestUtility { - - private static final Map ITEMS = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - Map.of("id", "urn:sha512:R05CRFVGdW5jdGlvbjpTdWJOZXR3b3JrPUV1cm9wZSxTdWJOZXR3", "aSide", - "urn:3gpp:dn:ManagedElement=1,GNBDUFunction=1", "bSide", - "urn:3gpp:dn:ManagedElement=1,GNBDUFunction=1,NRCellDU=1", "decorators", Map.of("location", - "Stockholm"), "classifiers", List.of("Rural"), "sourceIds", new ArrayList<>(), "metadata", Map - .of("trustLevel", "RELIABLE")))); - private static DataService dataService; - - public static void getMockForAllRelationshipsForObjectId(DataService dataService) { - RelationshipTestUtility.dataService = dataService; - mockRanGNBDUFunctionRelationships(); - } - - private static void mockRanGNBDUFunctionRelationships() { - OranTeivRelationshipsResponseMessage gnbduMap = new OranTeivRelationshipsResponseMessage(); - - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100"); - gnbduMap.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100"); - gnbduMap.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100"); - gnbduMap.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100"); - gnbduMap.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100"); - gnbduMap.setLast(hrefLast); - - gnbduMap.setItems(List.of(ITEMS)); - - when(dataService.getAllRelationshipsForObjectId(eq("GNBDUFunction"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1"), - any())).thenReturn(gnbduMap); - - when(dataService.getAllRelationshipsForObjectId(eq("5GCell"), eq("R05CRFVGdW5jdGlvbg"), any())).thenThrow( - TiesException.unknownEntityType("5GCell", Collections.emptyList())); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/TopologyObjectTestUtility.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/TopologyObjectTestUtility.java deleted file mode 100644 index c367dfb..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/api/contract/utils/TopologyObjectTestUtility.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.api.contract.utils; - -import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.data.api.DataService; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.endsWith; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -public class TopologyObjectTestUtility { - - private static final Map ITEMS = - - Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1", "attributes", Map.of( - "gNBDUId", 1), "metadata", Map.of("trustLevel", "RELIABLE")) - - )); - - private static DataService dataService; - - public static void getMockForAllTopologyObjectById(DataService dataService) { - TopologyObjectTestUtility.dataService = dataService; - mockRanGNBDUFunctionTopologyObject(); - mockRanNRCellDUTopologyObject(); - } - - private static void mockRanGNBDUFunctionTopologyObject() { - - OranTeivEntitiesResponseMessage gnbduMap = new OranTeivEntitiesResponseMessage(); - OranTeivEntitiesResponseMessage gnbduQueryMap = new OranTeivEntitiesResponseMessage(); - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50"); - gnbduMap.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50"); - gnbduMap.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50"); - gnbduMap.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50"); - gnbduMap.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50"); - gnbduMap.setLast(hrefLast); - - gnbduMap.setItems(List.of(ITEMS)); - - OranTeivHref hrefFirstQuery = new OranTeivHref(); - hrefFirstQuery.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100"); - gnbduQueryMap.setFirst(hrefFirstQuery); - OranTeivHref hrefNextQuery = new OranTeivHref(); - hrefNextQuery.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100"); - gnbduQueryMap.setNext(hrefNextQuery); - OranTeivHref hrefPrevQuery = new OranTeivHref(); - hrefPrevQuery.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100"); - gnbduQueryMap.setPrev(hrefPrevQuery); - OranTeivHref hrefSelfQuery = new OranTeivHref(); - hrefSelfQuery.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100"); - gnbduQueryMap.setSelf(hrefSelfQuery); - OranTeivHref hrefLastQuery = new OranTeivHref(); - hrefLastQuery.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100"); - gnbduQueryMap.setLast(hrefLastQuery); - - gnbduQueryMap.setItems(List.of(ITEMS)); - - when(dataService.getTopologyById(eq("GNBDUFunction"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1"))) - .thenReturn( - - Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1", - "attributes", Map.of("gNBId", 1, "gNBDUId", 1, "gNBIdLength", 2, "dUpLMNId", Map.of( - "mcc", "110", "mnc", "210")), "decorators", Map.of("location", "Stockholm"), - "classifiers", List.of("Rural"), "sourceIds", List.of( - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1"), - "metadata", Map.of("trustLevel", "RELIABLE"))))); - - when(dataService.getTopologyById(eq("GNBDUFunction"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D2"))) - .thenReturn(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=2", "attributes", - Map.of("gNBId", 2, "gNBDUId", 2, "gNBIdLength", 2, "dUpLMNId", Map.of("mcc", "110", "mnc", - "210")), "decorators", Map.of("location", "Stockholm"), "classifiers", List.of( - "Rural"), "sourceIds", List.of( - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=2"), - "metadata", Map.of("trustLevel", "RELIABLE"))))); - - when(dataService.getTopologyById(eq("GBFunction"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1"))) - .thenThrow(TiesException.unknownEntityType("GBFunction", Collections.emptyList())); - - when(dataService.getTopologyById(eq("NRDU"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D1"))) - .thenThrow(TiesException.unknownEntityType("NRDU", Collections.emptyList())); - - when(dataService.getTopologyByType(eq("GNBDUFunction"), endsWith("%2Fattributes(gNBDUId)"), any(), any())) - .thenReturn(gnbduMap); - - when(dataService.getTopologyByType(eq("GNBDUFunction"), endsWith("%2Fattributes(gNBDUId)"), endsWith( - "%2Fattributes[@gNBDUId=1]"), any())).thenReturn(gnbduQueryMap); - - when(dataService.getTopologyByType(eq("GNBBUFunction"), any(), any(), any())).thenThrow(TiesException - .unknownEntityType("GNBBUFunction", Collections.emptyList())); - } - - private static void mockRanNRCellDUTopologyObject() { - when(dataService.getTopologyById(eq("NRCellDU"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D1"))) - .thenReturn(Map.of("o-ran-smo-teiv-ran:NRCellDU", List.of(Map.of("id", - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=1", - "attributes", Map.of("nCI", 1, "nRPCI", 35, "nRTAC", 50, "cellLocalId", 91), "decorators", - Map.of("location", "Stockholm"), "classifiers", List.of("Rural"), "sourceIds", List.of( - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=1"), - "metadata", Map.of("trustLevel", "RELIABLE"))))); - - when(dataService.getTopologyById(eq("NRCellDU"), eq( - "urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D2"))) - .thenReturn(Map.of("o-ran-smo-teiv-ran:NRCellDU", List.of(Map.of("id", - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=2", - "attributes", Map.of("nCI", 5, "nRPCI", 35, "nRTAC", 50, "cellLocalId", 95), "decorators", - Map.of("location", "Stockholm"), "classifiers", List.of("Rural"), "sourceIds", List.of( - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=2"), - "metadata", Map.of("trustLevel", "RELIABLE"))))); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImplTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImplTest.java deleted file mode 100644 index 709c121..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/DataServiceImplTest.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.data.api.impl; - -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.mapper.MapperUtility; -import org.oran.smo.teiv.exposure.spi.mapper.PaginationMetaData; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.schema.MockSchemaLoader; - -import org.oran.smo.teiv.api.model.OranTeivDomains; -import org.oran.smo.teiv.api.model.OranTeivDomainsItemsInner; -import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; -import org.oran.smo.teiv.api.model.OranTeivEntityTypes; -import org.oran.smo.teiv.api.model.OranTeivEntityTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import static org.oran.smo.teiv.schema.SchemaRegistry.*; -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.oran.smo.teiv.utils.TiesConstants.ITEMS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class DataServiceImplTest { - - private static DataPersistanceService mockedDataPersistanceService; - private static DataServiceImpl underTest; - private static final String REL_ID_PREFIX = "urn:base64:"; - private static MockHttpServletRequest request = new MockHttpServletRequest(); - - @BeforeAll - static void setUp() throws SchemaLoaderException { - - RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); - mockedDataPersistanceService = mock(DataPersistanceService.class); - SchemaLoader mockedSchemaLoader = new MockSchemaLoader(); - mockedSchemaLoader.loadSchemaRegistry(); - underTest = new DataServiceImpl(mockedDataPersistanceService, new MapperUtility()); - mockGetTopologyById(); - mockGetRelationshipById(); - mockGetRelationshipByType(); - mockGetAllRelationships(); - mockGetTopologyByType(); - MockGetTopologyByTargetFilter(); - } - - @Test - void testGetTopologyById() { - Assertions.assertEquals(generateResponse("GNBDUFunction", "5A548EA9D166341776CA0695837E55D8"), underTest - .getTopologyById("GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")); - Assertions.assertEquals(generateResponse("NRCellDU", "98C3A4591A37718E1330F0294E23B62A"), underTest.getTopologyById( - "NRCellDU", "98C3A4591A37718E1330F0294E23B62A")); - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getTopologyById("NRCellDU", "NOT_EXISTING")); - } - - @Test - void testGetTopologyByType() { - OranTeivEntitiesResponseMessage expectedResponse1 = new OranTeivEntitiesResponseMessage(); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath("/domains/RAN/entity-types/GNBDUFunction/entities") - .offset(0).limit(2).addQueryParameters("scopeFilter", - "/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]") - .addQueryParameters("targetFilter", "/attributes/fdn;/attributes/id").build(); - paginationDTO1.setTotalSize(2); - - expectedResponse1.setItems(List.of(Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=111", "id", - "5BAE4346C241237AA8C74AE1259EF203"), Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=112", - "id", "6B55F987ED838C0FA58DC11AB19CD1D3"))); - - OranTeivHref hrefFirst1 = new OranTeivHref(); - hrefFirst1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=2&scopeFilter=/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]&targetFilter=/attributes/fdn;/attributes/id"); - expectedResponse1.setFirst(hrefFirst1); - OranTeivHref hrefNext1 = new OranTeivHref(); - hrefNext1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=2&scopeFilter=/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]&targetFilter=/attributes/fdn;/attributes/id"); - expectedResponse1.setNext(hrefNext1); - OranTeivHref hrefPrev1 = new OranTeivHref(); - hrefPrev1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=2&scopeFilter=/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]&targetFilter=/attributes/fdn;/attributes/id"); - expectedResponse1.setPrev(hrefPrev1); - OranTeivHref hrefSelf1 = new OranTeivHref(); - hrefSelf1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=2&scopeFilter=/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]&targetFilter=/attributes/fdn;/attributes/id"); - expectedResponse1.setSelf(hrefSelf1); - OranTeivHref hrefLast1 = new OranTeivHref(); - hrefLast1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=2&scopeFilter=/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]&targetFilter=/attributes/fdn;/attributes/id"); - expectedResponse1.setLast(hrefLast1); - expectedResponse1.setTotalCount(2); - - Assertions.assertEquals(expectedResponse1, underTest.getTopologyByType("GNBDUFunction", - "/attributes/fdn;/attributes/id", - "/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]", paginationDTO1)); - } - - @Test - void testGetEntitiesByDomain() { - OranTeivEntitiesResponseMessage expectedResult = new OranTeivEntitiesResponseMessage(); - - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/RAN/entities").offset(0).limit(1) - .addQueryParameters("targetFilter", "/GNBDUFunction/id").build(); - paginationDTO.setTotalSize(1); - - expectedResult.setItems(List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "1050570EBB1315E1AE7A9FD5E1400A00"))))); - - OranTeivHref hrefFirst1 = new OranTeivHref(); - hrefFirst1.setHref("/domains/RAN/entities?offset=0&limit=1&targetFilter=/GNBDUFunction/id"); - expectedResult.setFirst(hrefFirst1); - OranTeivHref hrefNext1 = new OranTeivHref(); - hrefNext1.setHref("/domains/RAN/entities?offset=0&limit=1&targetFilter=/GNBDUFunction/id"); - expectedResult.setNext(hrefNext1); - OranTeivHref hrefPrev1 = new OranTeivHref(); - hrefPrev1.setHref("/domains/RAN/entities?offset=0&limit=1&targetFilter=/GNBDUFunction/id"); - expectedResult.setPrev(hrefPrev1); - OranTeivHref hrefSelf1 = new OranTeivHref(); - hrefSelf1.setHref("/domains/RAN/entities?offset=0&limit=1&targetFilter=/GNBDUFunction/id"); - expectedResult.setSelf(hrefSelf1); - OranTeivHref hrefLast1 = new OranTeivHref(); - hrefLast1.setHref("/domains/RAN/entities?offset=0&limit=1&targetFilter=/GNBDUFunction/id"); - expectedResult.setLast(hrefLast1); - expectedResult.setTotalCount(1); - - Assertions.assertEquals(expectedResult, underTest.getEntitiesByDomain("RAN", "/GNBDUFunction/id", null, - paginationDTO)); - - } - - @Test - void testGetRelationshipById() { - String id = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ=="; - String notExistingId = "NOT_EXISTING"; - Map response = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", id, - Collections.EMPTY_LIST))); - - Assertions.assertEquals(response, underTest.getRelationshipById("GNBDUFUNCTION_PROVIDES_NRCELLDU", id)); - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getRelationshipById( - "GNBDUFUNCTION_PROVIDES_NRCELLDU", notExistingId)); - } - - @Test - void testGetRelationshipsByType() { - OranTeivRelationshipsResponseMessage response = new OranTeivRelationshipsResponseMessage(); - OranTeivRelationshipsResponseMessage response2 = new OranTeivRelationshipsResponseMessage(); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath( - "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships").offset(0).limit(5).build(); - - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships").offset(0) - .limit(5).build(); - - response.setItems(List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "BCA882C87D49687E731F9B3872EFDBD3", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkxOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzE=", - Collections.EMPTY_LIST))))); - - response2.setItems(List.of(Map.of("o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", List.of( - generateResponse("A05C67D47D117C2DC5BDF5E00AE70", "2256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJE=", - Collections.EMPTY_LIST))))); - - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setFirst(hrefFirst); - OranTeivHref hrefFirst2 = new OranTeivHref(); - hrefFirst2.setHref( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships?offset=0&limit=5"); - response2.setFirst(hrefFirst2); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setNext(hrefNext); - OranTeivHref hrefNext2 = new OranTeivHref(); - hrefNext2.setHref( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships?offset=0&limit=5"); - response2.setNext(hrefNext2); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setPrev(hrefPrev); - OranTeivHref hrefPrev2 = new OranTeivHref(); - hrefPrev2.setHref( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships?offset=0&limit=5"); - response2.setPrev(hrefPrev2); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setSelf(hrefSelf); - OranTeivHref hrefSelf2 = new OranTeivHref(); - hrefSelf2.setHref( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships?offset=0&limit=5"); - response2.setSelf(hrefSelf2); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setLast(hrefLast); - OranTeivHref hrefLast2 = new OranTeivHref(); - hrefLast2.setHref( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships?offset=0&limit=5"); - response2.setLast(hrefLast2); - - response.setTotalCount(1); - response2.setTotalCount(1); - - Assertions.assertEquals(response, underTest.getRelationshipsByType("GNBDUFUNCTION_PROVIDES_NRCELLDU", null, - paginationDTO)); - - Assertions.assertEquals(response2, underTest.getRelationshipsByType("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", null, - paginationDTO2)); - } - - @Test - void testAllRelationshipsForObjectId() { - OranTeivRelationshipsResponseMessage response1 = new OranTeivRelationshipsResponseMessage(); - OranTeivRelationshipsResponseMessage response2 = new OranTeivRelationshipsResponseMessage(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships").offset(0).limit( - 100).build(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships").offset(0).limit( - 100).build(); - - List mapList = new ArrayList<>(); - List items1 = new ArrayList<>(); - List items2 = new ArrayList<>(); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "BCA882C87D49687E731F9B3872EFDBD3", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6RVV0cmFuQ2VsbDpCQ0E4ODJDODdENDk2ODdFNzMxRjlCMzg3MkVGREJEMw==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "3256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MQ==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVESYSTEM", List.of( - generateResponse("0525930249302B9649FC8F201EC4F7FC", "2256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MR==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY", List.of(generateResponse( - "3256120E73ADD4026A43A971DCE5C151", "3223120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MS==", - Collections.EMPTY_LIST)))); - - items1.add(mapList.get(0)); - items1.add(mapList.get(1)); - items1.add(mapList.get(2)); - - items2.add(mapList.get(1)); - items2.add(mapList.get(3)); - - response1.setItems(items1); - response2.setItems(items2); - - OranTeivHref hrefFirst1 = new OranTeivHref(); - hrefFirst1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships?offset=0&limit=100"); - response1.setFirst(hrefFirst1); - OranTeivHref hrefNext1 = new OranTeivHref(); - hrefNext1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships?offset=0&limit=100"); - response1.setNext(hrefNext1); - OranTeivHref hrefPrev1 = new OranTeivHref(); - hrefPrev1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships?offset=0&limit=100"); - response1.setPrev(hrefPrev1); - OranTeivHref hrefSelf1 = new OranTeivHref(); - hrefSelf1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships?offset=0&limit=100"); - response1.setSelf(hrefSelf1); - OranTeivHref hrefLast1 = new OranTeivHref(); - hrefLast1.setHref( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships?offset=0&limit=100"); - response1.setLast(hrefLast1); - response1.setTotalCount(3); - - OranTeivHref hrefFirst2 = new OranTeivHref(); - hrefFirst2.setHref( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships?offset=0&limit=100"); - response2.setFirst(hrefFirst2); - OranTeivHref hrefNext2 = new OranTeivHref(); - hrefNext2.setHref( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships?offset=0&limit=100"); - response2.setNext(hrefNext2); - OranTeivHref hrefPrev2 = new OranTeivHref(); - hrefPrev2.setHref( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships?offset=0&limit=100"); - response2.setPrev(hrefPrev2); - OranTeivHref hrefSelf2 = new OranTeivHref(); - hrefSelf2.setHref( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships?offset=0&limit=100"); - response2.setSelf(hrefSelf2); - OranTeivHref hrefLast2 = new OranTeivHref(); - hrefLast2.setHref( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships?offset=0&limit=100"); - response2.setLast(hrefLast2); - response2.setTotalCount(1); - - Assertions.assertEquals(response1, underTest.getAllRelationshipsForObjectId("GNBDUFunction", - "0525930249302B9649FC8F201EC4F7FC", paginationDTO1)); - Assertions.assertEquals(response2, underTest.getAllRelationshipsForObjectId("NRSectorCarrier", - "3256120E73ADD4026A43A971DCE5C151", paginationDTO2)); - } - - @Test - void testGetTopologyRelationshipTypes() { - OranTeivRelationshipTypes expectedResponse = new OranTeivRelationshipTypes(); - List items = new ArrayList<>(); - OranTeivRelationshipTypesItemsInner item1 = new OranTeivRelationshipTypesItemsInner(); - OranTeivRelationshipTypesItemsInner item2 = new OranTeivRelationshipTypesItemsInner(); - OranTeivRelationshipTypesItemsInner item3 = new OranTeivRelationshipTypesItemsInner(); - OranTeivRelationshipTypesItemsInner item4 = new OranTeivRelationshipTypesItemsInner(); - OranTeivHref relationships1 = new OranTeivHref(); - OranTeivHref relationships2 = new OranTeivHref(); - OranTeivHref relationships3 = new OranTeivHref(); - OranTeivHref relationships4 = new OranTeivHref(); - - item1.setName("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - relationships1.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships"); - item1.setRelationships(relationships1); - - item2.setName("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); - relationships2.setHref("/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER/relationships"); - - item2.setRelationships(relationships2); - - item3.setName("NRCELLDU_USES_NRSECTORCARRIER"); - relationships3.setHref("/domains/RAN/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships"); - item3.setRelationships(relationships3); - - item4.setName("NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - relationships4.setHref("/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships"); - item4.setRelationships(relationships4); - - items.add(item1); - items.add(item2); - items.add(item3); - items.add(item4); - - expectedResponse.setItems(items); - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref("/domains/RAN/relationship-types?offset=0&limit=5"); - expectedResponse.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref("/domains/RAN/relationship-types?offset=0&limit=5"); - expectedResponse.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref("/domains/RAN/relationship-types?offset=0&limit=5"); - expectedResponse.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref("/domains/RAN/relationship-types?offset=0&limit=5"); - expectedResponse.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref("/domains/RAN/relationship-types?offset=0&limit=5"); - expectedResponse.setLast(hrefLast); - expectedResponse.setTotalCount(4); - - PaginationDTO paginationDTO3 = PaginationDTO.builder().basePath("/domains/RAN/relationship-types").offset(0).limit( - 5).build(); - - Assertions.assertEquals(expectedResponse, underTest.getTopologyRelationshipTypes("RAN", paginationDTO3)); - } - - @Test - void testGetTopologyEntityTypes() { - OranTeivEntityTypes expectedResponse = new OranTeivEntityTypes(); - List items = new ArrayList<>(); - - OranTeivEntityTypesItemsInner item1 = new OranTeivEntityTypesItemsInner(); - OranTeivEntityTypesItemsInner item2 = new OranTeivEntityTypesItemsInner(); - - item1.setName("AntennaCapability"); - OranTeivHref entities1 = new OranTeivHref(); - entities1.setHref("/domains/EQUIPMENT_TO_RAN/entity-types/AntennaCapability/entities"); - item1.setEntities(entities1); - - item2.setName("AntennaModule"); - OranTeivHref entities2 = new OranTeivHref(); - entities2.setHref("/domains/EQUIPMENT_TO_RAN/entity-types/AntennaModule/entities"); - item2.setEntities(entities2); - - items.add(item1); - items.add(item2); - expectedResponse.setItems(items); - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref("/domains/EQUIPMENT_TO_RAN/entity-types?offset=0&limit=2"); - expectedResponse.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref("/domains/EQUIPMENT_TO_RAN/entity-types?offset=2&limit=2"); - expectedResponse.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref("/domains/EQUIPMENT_TO_RAN/entity-types?offset=0&limit=2"); - expectedResponse.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref("/domains/EQUIPMENT_TO_RAN/entity-types?offset=0&limit=2"); - expectedResponse.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref("/domains/EQUIPMENT_TO_RAN/entity-types?offset=6&limit=2"); - expectedResponse.setLast(hrefLast); - expectedResponse.setTotalCount(8); - - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/EQUIPMENT_TO_RAN/entity-types").offset(0) - .limit(2).build(); - - Assertions.assertEquals(expectedResponse, underTest.getTopologyEntityTypes("EQUIPMENT_TO_RAN", paginationDTO)); - } - - @Test - void testGetDomainTypes() { - OranTeivDomains expectedResponse = new OranTeivDomains(); - OranTeivDomainsItemsInner item1 = new OranTeivDomainsItemsInner(); - OranTeivDomainsItemsInner item2 = new OranTeivDomainsItemsInner(); - - item1.setName("CLOUD"); - OranTeivHref entityType1 = new OranTeivHref(); - OranTeivHref relationshipType1 = new OranTeivHref(); - entityType1.setHref("/domains/CLOUD/entity-types"); - relationshipType1.setHref("/domains/CLOUD/relationship-types"); - item1.setEntityTypes(entityType1); - item1.setRelationshipTypes(relationshipType1); - - item2.setName("CLOUD_TO_RAN"); - OranTeivHref entityType2 = new OranTeivHref(); - OranTeivHref relationshipType2 = new OranTeivHref(); - entityType2.setHref("/domains/CLOUD_TO_RAN/entity-types"); - relationshipType2.setHref("/domains/CLOUD_TO_RAN/relationship-types"); - item2.setEntityTypes(entityType2); - item2.setRelationshipTypes(relationshipType2); - - List items = new ArrayList<>(); - items.add(item1); - items.add(item2); - expectedResponse.setItems(items); - - OranTeivHref hrefFirst = new OranTeivHref(); - hrefFirst.setHref("/domains?offset=0&limit=2"); - expectedResponse.setFirst(hrefFirst); - OranTeivHref hrefNext = new OranTeivHref(); - hrefNext.setHref("/domains?offset=2&limit=2"); - expectedResponse.setNext(hrefNext); - OranTeivHref hrefPrev = new OranTeivHref(); - hrefPrev.setHref("/domains?offset=0&limit=2"); - expectedResponse.setPrev(hrefPrev); - OranTeivHref hrefSelf = new OranTeivHref(); - hrefSelf.setHref("/domains?offset=0&limit=2"); - expectedResponse.setSelf(hrefSelf); - OranTeivHref hrefLast = new OranTeivHref(); - hrefLast.setHref("/domains?offset=6&limit=2"); - expectedResponse.setLast(hrefLast); - expectedResponse.setTotalCount(2); - - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains").offset(0).limit(2).build(); - paginationDTO.setTotalSize(8); - - Assertions.assertEquals(expectedResponse, underTest.getDomainTypes(paginationDTO)); - } - - private static void mockGetTopologyById() { - EntityType entity1 = getEntityTypeByName("GNBDUFunction"); - EntityType entity2 = getEntityTypeByName("NRCellDU"); - - when(mockedDataPersistanceService.getTopology(entity1, "5A548EA9D166341776CA0695837E55D8")).thenReturn( - generateResponse("GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")); - when(mockedDataPersistanceService.getTopology(entity2, "98C3A4591A37718E1330F0294E23B62A")).thenReturn( - generateResponse("NRCellDU", "98C3A4591A37718E1330F0294E23B62A")); - when(mockedDataPersistanceService.getTopology(entity2, "NOT_EXISTING")).thenThrow(TiesException.class); - } - - private static void mockGetTopologyByType() { - Map mockedResponse1 = new HashMap<>(); - PaginationMetaData pmd1 = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath("/domains/RAN/entity-types/GNBDUFunction/entities") - .offset(0).limit(2).addQueryParameters("targetFilter", "/attributes/fdn;/attributes/id").addQueryParameters( - "scopeFilter", - "/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]").build(); - paginationDTO1.setTotalSize(2); - mockedResponse1.putAll(pmd1.getObjectList(paginationDTO1)); - - mockedResponse1.put("items", List.of(Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=111", "id", - "5BAE4346C241237AA8C74AE1259EF203"), Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=112", - "id", "6B55F987ED838C0FA58DC11AB19CD1D3"))); - mockedResponse1.putAll(pmd1.getObjectList(paginationDTO1)); - - when(mockedDataPersistanceService.getTopologyByType("GNBDUFunction", "/attributes/fdn;/attributes/id", - "/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]", paginationDTO1)) - .thenReturn(mockedResponse1); - } - - private static void MockGetTopologyByTargetFilter() { - Map mockedResponse = new HashMap<>(); - Map query = new HashMap<>(); - - query.put("targetFilter", "/GNBDUFunction/id"); - - PaginationMetaData pmd1 = new PaginationMetaData(); - - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/RAN/entities").offset(0).limit(1) - .addQueryParameters("targetFilter", "/GNBDUFunction/id").build(); - - paginationDTO.setTotalSize(1); - mockedResponse.putAll(pmd1.getObjectList(paginationDTO)); - mockedResponse.put("query", query); - - mockedResponse.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "1050570EBB1315E1AE7A9FD5E1400A00"))))); - - when(mockedDataPersistanceService.getEntitiesByDomain("RAN", "/GNBDUFunction/id", null, paginationDTO)).thenReturn( - mockedResponse); - - } - - private static void mockGetRelationshipById() { - String id = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ=="; - String wrongId = "NOT_EXISTING"; - String relationshipName = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; - Map response = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", id, - Collections.EMPTY_LIST))); - - when(mockedDataPersistanceService.getRelationshipWithSpecifiedId(id, SchemaRegistry.getRelationTypeByName( - relationshipName))).thenReturn(response); - when(mockedDataPersistanceService.getRelationshipWithSpecifiedId(wrongId, SchemaRegistry.getRelationTypeByName( - relationshipName))).thenThrow(TiesException.class); - } - - private static void mockGetRelationshipByType() { - Map mockedResponse = new HashMap<>(); - Map items = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "BCA882C87D49687E731F9B3872EFDBD3", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkxOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzE=", - Collections.EMPTY_LIST))); - RelationType relationType = getRelationTypeByName("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - - PaginationMetaData pmd1 = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath( - "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships").offset(0).limit(5).build(); - paginationDTO1.setTotalSize(1); - mockedResponse.putAll(pmd1.getObjectList(paginationDTO1)); - mockedResponse.put(ITEMS, List.of(items)); - - when(mockedDataPersistanceService.getRelationshipsByType(relationType, null, PaginationDTO.builder().basePath( - "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships").offset(0).limit(5) - .build())).thenReturn(mockedResponse); - - Map mockedResponse2 = new HashMap<>(); - Map items2 = Map.of("o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", List.of( - generateResponse("A05C67D47D117C2DC5BDF5E00AE70", "2256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJE=", - Collections.EMPTY_LIST))); - RelationType relationType2 = getRelationTypeByName("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - - PaginationMetaData pmd2 = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships").offset(0) - .limit(5).build(); - paginationDTO2.setTotalSize(1); - mockedResponse2.putAll(pmd2.getObjectList(paginationDTO2)); - mockedResponse2.put(ITEMS, List.of(items2)); - - when(mockedDataPersistanceService.getRelationshipsByType(relationType2, null, PaginationDTO.builder().basePath( - "/domains/EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships").offset(0) - .limit(5).build())).thenReturn(mockedResponse2); - } - - private static void mockGetAllRelationships() { - final EntityType gnbduFunction = getEntityTypeByName("GNBDUFunction"); - final EntityType nrSectorCarrier = getEntityTypeByName("NRSectorCarrier"); - Map mockedResponse1 = new HashMap<>(); - Map mockedResponse2 = new HashMap<>(); - List mapList = new ArrayList<>(); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "BCA882C87D49687E731F9B3872EFDBD3", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6RVV0cmFuQ2VsbDpCQ0E4ODJDODdENDk2ODdFNzMxRjlCMzg3MkVGREJEMw==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", List.of(generateResponse( - "0525930249302B9649FC8F201EC4F7FC", "3256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MQ==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVESYSTEM", List.of( - generateResponse("0525930249302B9649FC8F201EC4F7FC", "2256120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MR==", - Collections.EMPTY_LIST)))); - mapList.add(Map.of("o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY", List.of(generateResponse( - "3256120E73ADD4026A43A971DCE5C151", "3223120E73ADD4026A43A971DCE5C151", - REL_ID_PREFIX + "RU5vZGVCRnVuY3Rpb246MDUyNTkzMDI0OTMwMkI5NjQ5RkM4RjIwMUVDNEY3RkM6UFJPVklERVM6TFRFU2VjdG9yQ2FycmllcjozMjU2MTIwRTczQURENDAyNkE0M0E5NzFEQ0U1QzE1MS==", - Collections.EMPTY_LIST)))); - - PaginationMetaData pmd1 = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships").offset(0).limit( - 100).build(); - paginationDTO1.setTotalSize(3); - mockedResponse1.putAll(pmd1.getObjectList(paginationDTO1)); - mockedResponse1.put(ITEMS, List.of(mapList.get(0), mapList.get(1), mapList.get(2))); - - PaginationMetaData pmd2 = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships").offset(0).limit( - 100).build(); - paginationDTO2.setTotalSize(1); - mockedResponse2.putAll(pmd2.getObjectList(paginationDTO2)); - mockedResponse2.put(ITEMS, List.of(mapList.get(1), mapList.get(3))); - - when(mockedDataPersistanceService.getAllRelationships(gnbduFunction, getRelationTypesByEntityName("GNBDUFunction"), - "0525930249302B9649FC8F201EC4F7FC", PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/GNBDUFunction/0525930249302B9649FC8F201EC4F7FC/relationships").offset(0) - .limit(100).build())).thenReturn(mockedResponse1); - when(mockedDataPersistanceService.getAllRelationships(nrSectorCarrier, getRelationTypesByEntityName( - "NRSectorCarrier"), "3256120E73ADD4026A43A971DCE5C151", PaginationDTO.builder().basePath( - "/domains/RAN/entity-types/NRSectorCarrier/3256120E73ADD4026A43A971DCE5C151/relationships").offset( - 0).limit(100).build())).thenReturn(mockedResponse2); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/ExposureMetricsTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/ExposureMetricsTest.java index 7c8904f..2f809d7 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/ExposureMetricsTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/data/api/impl/ExposureMetricsTest.java @@ -20,122 +20,161 @@ */ package org.oran.smo.teiv.exposure.data.api.impl; -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.data.rest.controller.DataRestController; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.exposure.utils.RequestValidator; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.function.Supplier; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.oran.smo.teiv.utils.TiesTestConstants.APPLICATION_JSON; + +import java.util.Collections; +import java.util.function.Supplier; + +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +import jakarta.servlet.http.HttpServletRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.CustomMetrics; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.audit.LoggerHandler; +import org.oran.smo.teiv.exposure.data.api.DataService; +import org.oran.smo.teiv.exposure.data.rest.controller.DataController; +import org.oran.smo.teiv.exposure.classifiers.api.ClassifiersService; +import org.oran.smo.teiv.exposure.classifiers.rest.controller.ClassifiersRestController; +import org.oran.smo.teiv.exposure.decorators.api.DecoratorsService; +import org.oran.smo.teiv.exposure.decorators.rest.controller.DecoratorsRestController; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.oran.smo.teiv.exposure.utils.RequestValidator; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; -public class ExposureMetricsTest { +class ExposureMetricsTest { - private DataServiceImpl mockedDataService; + private DataService mockedDataService; + private ClassifiersService mockedClassifiersService; + private DecoratorsService mockedDecoratorsService; private RequestValidator mockedRequestValidator; private CustomMetrics underTest; - private DataRestController dataRestController; - - private final static String ACCEPT_TYPE = "application/json"; - private final static String DOMAIN_NAME = "RAN_LOGICAL"; - private final static String ENTITY_ID = "5A548EA9D166341776CA0695837E55D8"; - private final static String ENTITY_NAME = "GNBDUFunction"; - private final static String RELATION_TYPE = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; - private final static PaginationDTO paginationDto = PaginationDTO.builder().basePath("").offset(0).limit(1).build(); + private DataController dataController; + private ClassifiersRestController classifiersRestController; + private DecoratorsRestController decoratorsRestController; + private static final String DOMAIN_NAME = "RAN"; + private static final String ENTITY_ID = "5A548EA9D166341776CA0695837E55D8"; + private static final String ENTITY_NAME = "GNBDUFunction"; + private static final String RELATION_TYPE = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; @BeforeEach void setUp() throws SchemaLoaderException { SchemaLoader mockedSchemaLoader = new MockSchemaLoader(); mockedSchemaLoader.loadSchemaRegistry(); mockedRequestValidator = mock(RequestValidator.class); - mockedDataService = mock(DataServiceImpl.class); + mockedDataService = mock(DataService.class); + mockedClassifiersService = mock(ClassifiersService.class); + mockedDecoratorsService = mock(DecoratorsService.class); underTest = new CustomMetrics(new SimpleMeterRegistry()); - dataRestController = new DataRestController(mockedRequestValidator, mockedDataService, underTest); + dataController = new DataController(mockedRequestValidator, mockedDataService, underTest); + classifiersRestController = new ClassifiersRestController(mockedClassifiersService, underTest, mock( + LoggerHandler.class), mock(HttpServletRequest.class)); + decoratorsRestController = new DecoratorsRestController(mockedDecoratorsService, underTest, mock( + LoggerHandler.class), mock(HttpServletRequest.class)); } @Test void testGetRelationshipsByEntityIdFailMetrics() { - when(mockedDataService.getAllRelationshipsForObjectId(eq(ENTITY_NAME), eq(ENTITY_ID), any(PaginationDTO.class))) - .thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getAllRelationshipsForEntityId(ACCEPT_TYPE, DOMAIN_NAME, ENTITY_NAME, + when(mockedDataService.getAllRelationshipsForObjectId(eq(DOMAIN_NAME), eq(ENTITY_NAME), eq(ENTITY_ID), anyString(), + anyString(), any(RequestDetails.class))).thenThrow(TiesException.class); + assertMetrics(() -> dataController.getAllRelationshipsForEntityId(APPLICATION_JSON, DOMAIN_NAME, ENTITY_NAME, ENTITY_ID, "", "", 0, 1), underTest.getNumUnsuccessfullyExposedRelationshipsByEntityId()::count); } @Test void testGetEntityByIdFailMetrics() { - when(mockedDataService.getTopologyById(ENTITY_NAME, ENTITY_ID)).thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getTopologyById(ACCEPT_TYPE, DOMAIN_NAME, ENTITY_NAME, ENTITY_ID), underTest + when(mockedDataService.getEntityById(ENTITY_NAME, ENTITY_ID)).thenThrow(TiesException.class); + assertMetrics(() -> dataController.getTopologyById(APPLICATION_JSON, DOMAIN_NAME, ENTITY_NAME, ENTITY_ID), underTest .getNumUnsuccessfullyExposedEntityById()::count); } @Test void testGetEntitiesByTypeFailMetrics() { - when(mockedDataService.getTopologyByType(eq(ENTITY_NAME), anyString(), anyString(), any(PaginationDTO.class))) - .thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getTopologyByEntityTypeName(ACCEPT_TYPE, DOMAIN_NAME, ENTITY_NAME, "", "", 0, - 1), underTest.getNumUnsuccessfullyExposedEntitiesByType()::count); + when(mockedDataService.getTopologyByType(anyString(), eq(ENTITY_NAME), anyString(), anyString(), any( + RequestDetails.class))).thenThrow(TiesException.class); + assertMetrics(() -> dataController.getTopologyByEntityTypeName(APPLICATION_JSON, DOMAIN_NAME, ENTITY_NAME, "", "", + 0, 1), underTest.getNumUnsuccessfullyExposedEntitiesByType()::count); } @Test void testGetEntitiesByDomainFailMetrics() { - when(mockedDataService.getEntitiesByDomain(eq(DOMAIN_NAME), anyString(), anyString(), any(PaginationDTO.class))) + when(mockedDataService.getEntitiesByDomain(eq(DOMAIN_NAME), anyString(), anyString(), any(RequestDetails.class))) .thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getEntitiesByDomain(ACCEPT_TYPE, DOMAIN_NAME, "", "", 0, 1), underTest + assertMetrics(() -> dataController.getEntitiesByDomain(APPLICATION_JSON, DOMAIN_NAME, "", "", 0, 1), underTest .getNumUnsuccessfullyExposedEntitiesByDomain()::count); } @Test void testGetRelationshipByIdFailMetrics() { when(mockedDataService.getRelationshipById(RELATION_TYPE, ENTITY_ID)).thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getRelationshipById(ACCEPT_TYPE, DOMAIN_NAME, RELATION_TYPE, ENTITY_ID), + assertMetrics(() -> dataController.getRelationshipById(APPLICATION_JSON, DOMAIN_NAME, RELATION_TYPE, ENTITY_ID), underTest.getNumUnsuccessfullyExposedRelationshipById()::count); } @Test void testGetRelationshipsByTypeFailMetrics() { - when(mockedDataService.getRelationshipsByType(eq(RELATION_TYPE), anyString(), any(PaginationDTO.class))).thenThrow( - TiesException.class); - assertMetrics(() -> dataRestController.getRelationshipsByType(ACCEPT_TYPE, DOMAIN_NAME, RELATION_TYPE, "", "", 0, + when(mockedDataService.getRelationshipsByType(anyString(), eq(RELATION_TYPE), anyString(), anyString(), any( + RequestDetails.class))).thenThrow(TiesException.class); + assertMetrics(() -> dataController.getRelationshipsByType(APPLICATION_JSON, DOMAIN_NAME, RELATION_TYPE, "", "", 0, 1), underTest.getNumUnsuccessfullyExposedRelationshipsByType()::count); } @Test void testGetRelationshipTypesFailMetrics() { - when(mockedDataService.getTopologyRelationshipTypes(eq(DOMAIN_NAME), any(PaginationDTO.class))).thenThrow( + when(mockedDataService.getTopologyRelationshipTypes(eq(DOMAIN_NAME), any(RequestDetails.class))).thenThrow( TiesException.class); - assertMetrics(() -> dataRestController.getTopologyRelationshipTypes(ACCEPT_TYPE, DOMAIN_NAME, 0, 1), underTest + assertMetrics(() -> dataController.getTopologyRelationshipTypes(APPLICATION_JSON, DOMAIN_NAME, 0, 1), underTest .getNumUnsuccessfullyExposedRelationshipTypes()::count); } @Test void testGetDomainTypesFailMetrics() { - when(mockedDataService.getDomainTypes(any(PaginationDTO.class))).thenThrow(TiesException.class); - assertMetrics(() -> dataRestController.getAllDomains(ACCEPT_TYPE, 0, 1), underTest + when(mockedDataService.getDomainTypes(any(RequestDetails.class))).thenThrow(TiesException.class); + assertMetrics(() -> dataController.getAllDomains(APPLICATION_JSON, 0, 1), underTest .getNumUnsuccessfullyExposedDomainTypes()::count); } @Test void testGetEntityTypesFailMetrics() { - when(mockedDataService.getTopologyEntityTypes(eq(DOMAIN_NAME), any(PaginationDTO.class))).thenThrow( + when(mockedDataService.getTopologyEntityTypes(eq(DOMAIN_NAME), any(RequestDetails.class))).thenThrow( TiesException.class); - assertMetrics(() -> dataRestController.getTopologyEntityTypes(ACCEPT_TYPE, DOMAIN_NAME, 0, 1), underTest + assertMetrics(() -> dataController.getTopologyEntityTypes(APPLICATION_JSON, DOMAIN_NAME, 0, 1), underTest .getNumUnsuccessfullyExposedEntityTypes()::count); } - private void assertMetrics(Supplier dataServiceMethod, Supplier failerSupplier) { - Assertions.assertThrowsExactly(TiesException.class, dataServiceMethod::get); + @Test + void testUpdateClassifiersFailMetrics() { + doThrow(TiesException.invalidClassifiersException(Collections.emptyList())).when(mockedClassifiersService).update( + any(OranTeivClassifier.class)); + assertMetrics(() -> classifiersRestController.updateClassifier(APPLICATION_JSON, APPLICATION_JSON, + OranTeivClassifier.builder().operation(OranTeivClassifier.OperationEnum.MERGE).build()), underTest + .getNumUnsuccessfullyUpdatedClassifiers()::count); + } + + @Test + void testUpdateDecoratorsFailMetrics() { + doThrow(TiesException.invalidClassifiersException(Collections.emptyList())).when(mockedDecoratorsService).update( + any(OranTeivDecorator.class)); + assertMetrics(() -> decoratorsRestController.updateDecorator(APPLICATION_JSON, APPLICATION_JSON, OranTeivDecorator + .builder().operation(OranTeivDecorator.OperationEnum.MERGE).build()), underTest + .getNumUnsuccessfullyUpdatedDecorators()::count); + } + + private void assertMetrics(Supplier controllerMethod, Supplier failerSupplier) { + Assertions.assertThrowsExactly(TiesException.class, controllerMethod::get); Assertions.assertEquals(1.0, failerSupplier.get()); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestControllerTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestControllerTest.java deleted file mode 100644 index d72e1f6..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/data/rest/controller/DataRestControllerTest.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.data.rest.controller; - -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.api.model.OranTeivDomains; -import org.oran.smo.teiv.api.model.OranTeivHref; -import org.oran.smo.teiv.api.model.OranTeivEntityTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivEntityTypes; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypesItemsInner; -import org.oran.smo.teiv.api.model.OranTeivRelationshipsResponseMessage; -import org.oran.smo.teiv.api.model.OranTeivRelationshipTypes; -import org.oran.smo.teiv.api.model.OranTeivDomainsItemsInner; -import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.data.api.impl.DataServiceImpl; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.exposure.utils.RequestValidator; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.http.ResponseEntity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -class DataRestControllerTest { - private static DataServiceImpl dataService; - private static DataRestController underTest; - private static RequestValidator requestValidator; - private static CustomMetrics customMetrics; - private final String ACCEPT_TYPE = "application/json"; - private static final String EIID_PREFIX = "urn:base64:"; - - @BeforeAll - static void setUp() { - dataService = mock(DataServiceImpl.class); - requestValidator = mock(RequestValidator.class); - customMetrics = mock(CustomMetrics.class); - underTest = new DataRestController(requestValidator, dataService, customMetrics); - mockTopologyById(); - mockGetTopologyRelationshipTypes(); - mockTopologyEntityTypes(); - mockGetRelationshipById(); - mockGetRelationshipByType(); - mockGetAllRelationshipsForEntityId(); - mockGetDomainTypes(); - mockGetTopologyEntityTypes(); - mockTopologyByType(); - } - - @BeforeEach - void clearInvocations() { - Mockito.clearInvocations(requestValidator); - } - - @Test - void testGetTopologyById() { - assertEquals(ResponseEntity.ok(generateResponse("GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")), underTest - .getTopologyById(ACCEPT_TYPE, "RAN_LOGICAL", "GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")); - assertEquals(ResponseEntity.ok(generateResponse("NRCellDU", "98C3A4591A37718E1330F0294E23B62A")), underTest - .getTopologyById(ACCEPT_TYPE, "RAN_LOGICAL", "NRCellDU", "98C3A4591A37718E1330F0294E23B62A")); - assertThrows(TiesException.class, () -> underTest.getTopologyById(ACCEPT_TYPE, "RAN_LOGICAL", "NRCellDU", - "NOT_EXISTING")); - - verify(requestValidator, Mockito.times(3)).validateDomain("RAN_LOGICAL"); - verify(requestValidator, Mockito.times(1)).validateEntityType("GNBDUFunction"); - verify(requestValidator, Mockito.times(2)).validateEntityType("NRCellDU"); - verify(requestValidator, Mockito.times(1)).validateEntityTypeInDomain("GNBDUFunction", "RAN_LOGICAL"); - verify(requestValidator, Mockito.times(2)).validateEntityTypeInDomain("NRCellDU", "RAN_LOGICAL"); - } - - @Test - void testGetTopologyEntityTypes() { - OranTeivEntityTypesItemsInner element1 = new OranTeivEntityTypesItemsInner(); - element1.setName("Site"); - OranTeivEntityTypesItemsInner element2 = new OranTeivEntityTypesItemsInner(); - element1.setName("AntennaModule"); - OranTeivEntityTypesItemsInner element3 = new OranTeivEntityTypesItemsInner(); - element1.setName("PhysicalNetworkAppliance"); - - List entityTypes = new ArrayList<>(); - entityTypes.add(element1); - entityTypes.add(element2); - entityTypes.add(element3); - OranTeivEntityTypes response = new OranTeivEntityTypes(); - response.setItems(entityTypes); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains/RAN_EQUIPMENT/entity-types?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyEntityTypes(ACCEPT_TYPE, "RAN_EQUIPMENT", - 0, 5)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyEntityTypes("*/*", "RAN_EQUIPMENT", 0, - 5)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyEntityTypes( - "application/json, application/problem+json", "RAN_EQUIPMENT", 0, 5)); - - verify(requestValidator, Mockito.times(3)).validateDomain("RAN_EQUIPMENT"); - } - - @Test - void testGetTopologyRelationshipTypes() { - OranTeivRelationshipTypesItemsInner element1 = new OranTeivRelationshipTypesItemsInner(); - element1.setName("NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - OranTeivRelationshipTypesItemsInner element2 = new OranTeivRelationshipTypesItemsInner(); - element2.setName("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - OranTeivRelationshipTypesItemsInner element3 = new OranTeivRelationshipTypesItemsInner(); - element3.setName("GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - OranTeivRelationshipTypesItemsInner element4 = new OranTeivRelationshipTypesItemsInner(); - element4.setName("EUTRANCELL_USES_LTESECTORCARRIER"); - OranTeivRelationshipTypesItemsInner element5 = new OranTeivRelationshipTypesItemsInner(); - element5.setName("MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); - - List relationshipTypes = new ArrayList<>(); - relationshipTypes.add(element1); - relationshipTypes.add(element2); - relationshipTypes.add(element3); - relationshipTypes.add(element4); - relationshipTypes.add(element5); - - OranTeivRelationshipTypes response = new OranTeivRelationshipTypes(); - response.setItems(relationshipTypes); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains/RAN_LOGICAL/relationship-types?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyRelationshipTypes(ACCEPT_TYPE, - "RAN_LOGICAL", 0, 5)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyRelationshipTypes("*/*", "RAN_LOGICAL", 0, - 5)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyRelationshipTypes( - "application/json, application/problem+json", "RAN_LOGICAL", 0, 5)); - } - - @Test - void testGetDomainTypes() { - OranTeivDomainsItemsInner element1 = new OranTeivDomainsItemsInner(); - element1.setName("RAN_LOGICAL_TO_EQUIPMENT"); - OranTeivDomainsItemsInner element2 = new OranTeivDomainsItemsInner(); - element2.setName("RAN_LOGICAL"); - OranTeivDomainsItemsInner element3 = new OranTeivDomainsItemsInner(); - element3.setName("RAN_EQUIPMENT"); - - List domains = new ArrayList<>(); - domains.add(element1); - domains.add(element2); - domains.add(element3); - - OranTeivDomains response = new OranTeivDomains(); - response.setItems(domains); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getAllDomains(ACCEPT_TYPE, 0, 3)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getAllDomains("*/*", 0, 3)); - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getAllDomains( - "application/json, application/problem+json", 0, 3)); - - } - - @Test - void testGetRelationshipById() { - Map response = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ==", - Collections.emptyList()))); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getRelationshipById(ACCEPT_TYPE, "RAN_LOGICAL", - "GNBDUFUNCTION_PROVIDES_NRCELLDU", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ==")); - - verify(requestValidator, Mockito.times(1)).validateDomain("RAN_LOGICAL"); - verify(requestValidator, Mockito.times(1)).validateRelationshipType("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - verify(requestValidator, Mockito.times(1)).validateRelationshipTypeInDomain("GNBDUFUNCTION_PROVIDES_NRCELLDU", - "RAN_LOGICAL"); - } - - @Test - void testGetAllRelationshipsForEntityId() { - List mapList = new ArrayList<>(); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "D3215E08570BE58339C7463626B50E37", "B480427E8A0C0B8D994E437784BB382F", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.emptyList())))); - mapList.add(Map.of("o-ran-smo-teiv-equipment-to-ran:SECTOR_GROUPS_NRCELLDU", List.of(generateResponse( - "F5128C172A70C4FCD4739650B06DE9E2", "B480427E8A0C0B8D994E437784BB382F", - EIID_PREFIX + "U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.emptyList())))); - mapList.add(Map.of("o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER", List.of(generateResponse( - "B480427E8A0C0B8D994E437784BB382F", "E49D942C16E0364E1E0788138916D70C", - EIID_PREFIX + "TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM=", - Collections.emptyList())))); - - OranTeivRelationshipsResponseMessage response = new OranTeivRelationshipsResponseMessage(); - - response.setItems(mapList); - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/entity-types/NRCellDU/entities/B480427E8A0C0B8D994E437784BB382F/relationships?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getAllRelationshipsForEntityId(ACCEPT_TYPE, - "RAN_LOGICAL", "NRCellDU", "B480427E8A0C0B8D994E437784BB382F", "", "", 0, 5)); - - verify(requestValidator, Mockito.times(1)).validateDomain("RAN_LOGICAL"); - verify(requestValidator, Mockito.times(1)).validateEntityType("NRCellDU"); - verify(requestValidator, Mockito.times(1)).validateEntityTypeInDomain("NRCellDU", "RAN_LOGICAL"); - } - - @Test - void testGetRelationshipsByType() { - underTest.getRelationshipsByType(ACCEPT_TYPE, "RAN_LOGICAL", "GNBDUFUNCTION_PROVIDES_NRCELLDU", null, null, 0, 5); - - verify(requestValidator, Mockito.times(1)).validateDomain("RAN_LOGICAL"); - verify(requestValidator, Mockito.times(1)).validateRelationshipType("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - verify(requestValidator, Mockito.times(1)).validateRelationshipTypeInDomain("GNBDUFUNCTION_PROVIDES_NRCELLDU", - "RAN_LOGICAL"); - - OranTeivRelationshipsResponseMessage response = new OranTeivRelationshipsResponseMessage(); - - response.setItems(List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "91", "1", EIID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkxOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzE=", - Collections.emptyList()), generateResponse("92", "2", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkyOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzI=", - Collections.emptyList()))))); - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getRelationshipsByType(ACCEPT_TYPE, "RAN_LOGICAL", - "GNBDUFUNCTION_PROVIDES_NRCELLDU", null, null, 0, 5)); - } - - @Test - void testGetTopologyByTargetFilter() { - underTest.getEntitiesByDomain(ACCEPT_TYPE, "RAN_LOGICAL", null, null, 0, 2); - - verify(requestValidator, Mockito.times(1)).validateDomain("RAN_LOGICAL"); - } - - @Test - void testGetTopologyByType() { - - OranTeivEntitiesResponseMessage response = new OranTeivEntitiesResponseMessage(); - Map query = new HashMap<>(); - - query.put("scopeFilter", "/attributes[contains (@fnd, \"/SubNetwork=Ireland/\")]"); - - response.setItems(List.of(Map.of("GNBDUFunction", List.of(Map.of("id", "5FE67725576EDA7937752E7965164C2E"), Map.of( - "id", "9BCD297B8258F67908477D895636ED65"), Map.of("id", "8E249BCFAEC86C03D9ADD27FA9748254"))))); - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/entity-types/GNBDUFunction/entities?scopeFilter=/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]&offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - Assertions.assertEquals(ResponseEntity.ok(response), underTest.getTopologyByEntityTypeName(ACCEPT_TYPE, - "RAN_LOGICAL", "GNBDUFunction", "", "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]", 0, 3)); - - verify(requestValidator, Mockito.times(1)).validateDomain("RAN_LOGICAL"); - verify(requestValidator, Mockito.times(1)).validateEntityType("GNBDUFunction"); - verify(requestValidator, Mockito.times(1)).validateEntityTypeInDomain("GNBDUFunction", "RAN_LOGICAL"); - - assertThrows(TiesException.class, () -> underTest.getTopologyByEntityTypeName(ACCEPT_TYPE, "RAN_LOGICAL", - "CloudSite", "", "/attributes[contains (@fdn, \"/SubNetwork Ireland/\")]", 0, 3)); - assertThrows(TiesException.class, () -> underTest.getTopologyByEntityTypeName(ACCEPT_TYPE, "RAN_LOGICAL", - "GNBDUFunction2", "", "/attributes[contains (@fdn, \"/SubNetwork Ireland/\")]", 0, 3)); - assertThrows(TiesPathException.class, () -> underTest.getTopologyByEntityTypeName(ACCEPT_TYPE, "RAN_LOGICAL", - "GNBDUFunction", "", "/attributes[contains ( fdn, \"/SubNetwork Ireland/\")]", 0, 3)); - - } - - private static void mockTopologyById() { - when(dataService.getTopologyById("GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")).thenReturn(generateResponse( - "GNBDUFunction", "5A548EA9D166341776CA0695837E55D8")); - when(dataService.getTopologyById("NRCellDU", "98C3A4591A37718E1330F0294E23B62A")).thenReturn(generateResponse( - "NRCellDU", "98C3A4591A37718E1330F0294E23B62A")); - when(dataService.getTopologyById("NRCellDU", "NOT_EXISTING")).thenThrow(TiesException.class); - } - - private static void mockTopologyEntityTypes() { - OranTeivEntityTypesItemsInner element1 = new OranTeivEntityTypesItemsInner(); - element1.setName("Site"); - OranTeivEntityTypesItemsInner element2 = new OranTeivEntityTypesItemsInner(); - element1.setName("AntennaModule"); - OranTeivEntityTypesItemsInner element3 = new OranTeivEntityTypesItemsInner(); - element1.setName("PhysicalNetworkAppliance"); - - List entityTypes = new ArrayList<>(); - entityTypes.add(element1); - entityTypes.add(element2); - entityTypes.add(element3); - OranTeivEntityTypes response = new OranTeivEntityTypes(); - response.setItems(entityTypes); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains/RAN_EQUIPMENT/entity-types?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - when(dataService.getTopologyEntityTypes("RAN_EQUIPMENT", PaginationDTO.builder().offset(0).limit(5).build())) - .thenReturn(response); - } - - private static void mockGetRelationshipById() { - Map response = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ==", - Collections.emptyList()))); - - when(dataService.getRelationshipById("GNBDUFUNCTION_PROVIDES_NRCELLDU", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ==")) - .thenReturn(response); - } - - private static void mockGetRelationshipByType() { - PaginationDTO paginationDTO = PaginationDTO.builder().offset(0).limit(5).addPathParameters("relationshipType", - "GNBDUFUNCTION_PROVIDES_NRCELLDU").addPathParameters("domain", "RAN_LOGICAL").addQueryParameters( - "scopeFilter", null).basePath( - "/domains/RAN_LOGICAL/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships") - .build(); - - OranTeivRelationshipsResponseMessage response = new OranTeivRelationshipsResponseMessage(); - response.setItems(List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "91", "1", EIID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkxOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzE=", - Collections.emptyList()), generateResponse("92", "2", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpHTkJEVUZ1bmN0aW9uLzkyOlBST1ZJREVTOk5SQ2VsbERVOk5SQ2VsbERVLzI=", - Collections.emptyList()))))); - - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - when(dataService.getRelationshipsByType("GNBDUFUNCTION_PROVIDES_NRCELLDU", null, paginationDTO)).thenReturn( - response); - } - - private static void mockGetAllRelationshipsForEntityId() { - OranTeivRelationshipsResponseMessage response = new OranTeivRelationshipsResponseMessage(); - - List mapList = new ArrayList<>(); - mapList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "D3215E08570BE58339C7463626B50E37", "B480427E8A0C0B8D994E437784BB382F", - EIID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.emptyList())))); - mapList.add(Map.of("o-ran-smo-teiv-equipment-to-ran:SECTOR_GROUPS_NRCELLDU", List.of(generateResponse( - "F5128C172A70C4FCD4739650B06DE9E2", "B480427E8A0C0B8D994E437784BB382F", - EIID_PREFIX + "U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.emptyList())))); - mapList.add(Map.of("o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER", List.of(generateResponse( - "B480427E8A0C0B8D994E437784BB382F", "E49D942C16E0364E1E0788138916D70C", - EIID_PREFIX + "TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM=", - Collections.emptyList())))); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().addPathParameters("domain", "RAN_LOGICAL").addPathParameters( - "entityType", "NRCellDU").addPathParameters("id", "B480427E8A0C0B8D994E437784BB382F").basePath(String - .format("/domains/%s/entity-types/%s/entities/%s/relationships", "RAN_LOGICAL", "NRCellDU", - "B480427E8A0C0B8D994E437784BB382F")).offset(0).limit(5).build(); - - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/entity-types/NRCellDU/entities/B480427E8A0C0B8D994E437784BB382F/relationships?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - response.setItems(mapList); - when(dataService.getAllRelationshipsForObjectId("NRCellDU", "B480427E8A0C0B8D994E437784BB382F", paginationDTO1)) - .thenReturn(response); - } - - private static void mockGetDomainTypes() { - OranTeivDomainsItemsInner element1 = new OranTeivDomainsItemsInner(); - element1.setName("RAN_LOGICAL_TO_EQUIPMENT"); - OranTeivDomainsItemsInner element2 = new OranTeivDomainsItemsInner(); - element2.setName("RAN_LOGICAL"); - OranTeivDomainsItemsInner element3 = new OranTeivDomainsItemsInner(); - element3.setName("RAN_EQUIPMENT"); - - List domains = new ArrayList<>(); - domains.add(element1); - domains.add(element2); - domains.add(element3); - - OranTeivDomains response = new OranTeivDomains(); - response.setItems(domains); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - when(dataService.getDomainTypes(PaginationDTO.builder().offset(0).basePath("/domains").limit(3).build())) - .thenReturn(response); - } - - private static void mockGetTopologyEntityTypes() { - OranTeivEntityTypesItemsInner element1 = new OranTeivEntityTypesItemsInner(); - element1.setName("Site"); - OranTeivEntityTypesItemsInner element2 = new OranTeivEntityTypesItemsInner(); - element1.setName("AntennaModule"); - OranTeivEntityTypesItemsInner element3 = new OranTeivEntityTypesItemsInner(); - element1.setName("PhysicalNetworkAppliance"); - - List entityTypes = new ArrayList<>(); - entityTypes.add(element1); - entityTypes.add(element2); - entityTypes.add(element3); - OranTeivEntityTypes response = new OranTeivEntityTypes(); - response.setItems(entityTypes); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains/RAN_EQUIPMENT/entity-types?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath("/domains/RAN_EQUIPMENT/entity-types") - .addPathParameters("domain", "RAN_EQUIPMENT").offset(0).limit(5).build(); - - when(dataService.getTopologyEntityTypes("RAN_EQUIPMENT", paginationDTO1)).thenReturn(response); - } - - private static void mockGetTopologyRelationshipTypes() { - OranTeivRelationshipTypesItemsInner element1 = new OranTeivRelationshipTypesItemsInner(); - element1.setName("NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - OranTeivRelationshipTypesItemsInner element2 = new OranTeivRelationshipTypesItemsInner(); - element2.setName("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - OranTeivRelationshipTypesItemsInner element3 = new OranTeivRelationshipTypesItemsInner(); - element3.setName("GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - OranTeivRelationshipTypesItemsInner element4 = new OranTeivRelationshipTypesItemsInner(); - element4.setName("EUTRANCELL_USES_LTESECTORCARRIER"); - OranTeivRelationshipTypesItemsInner element5 = new OranTeivRelationshipTypesItemsInner(); - element5.setName("MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); - - List relationshipTypes = new ArrayList<>(); - relationshipTypes.add(element1); - relationshipTypes.add(element2); - relationshipTypes.add(element3); - relationshipTypes.add(element4); - relationshipTypes.add(element5); - - OranTeivRelationshipTypes response = new OranTeivRelationshipTypes(); - response.setItems(relationshipTypes); - - OranTeivHref href = new OranTeivHref(); - href.setHref("/domains/RAN_LOGICAL/relationship-types?offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().basePath("/domains/RAN_LOGICAL/relationship-types").offset(0) - .limit(5).addPathParameters("domain", "RAN_LOGICAL").build(); - - when(dataService.getTopologyRelationshipTypes("RAN_LOGICAL", paginationDTO1)).thenReturn(response); - } - - private static void mockTopologyByType() { - OranTeivEntitiesResponseMessage response = new OranTeivEntitiesResponseMessage(); - Map query = new HashMap<>(); - - query.put("scopeFilter", "/attributes[contains (@fnd, \"/SubNetwork=Ireland/\")]"); - - PaginationDTO paginationDTO = PaginationDTO.builder().offset(0).limit(3).addPathParameters("domain", "RAN_LOGICAL") - .addQueryParameters("targetFilter", "").addQueryParameters("scopeFilter", - "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]").basePath( - "/domains/RAN_LOGICAL/entity-types/GNBDUFunction/entities").build(); - - response.setItems(List.of(Map.of("GNBDUFunction", List.of(Map.of("id", "5FE67725576EDA7937752E7965164C2E"), Map.of( - "id", "9BCD297B8258F67908477D895636ED65"), Map.of("id", "8E249BCFAEC86C03D9ADD27FA9748254"))))); - OranTeivHref href = new OranTeivHref(); - href.setHref( - "/domains/RAN_LOGICAL/entity-types/GNBDUFunction/entities?scopeFilter=/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]&offset=0&limit=5"); - response.setSelf(href); - response.setFirst(href); - response.setPrev(href); - response.setNext(href); - response.setLast(href); - - when(dataService.getTopologyByType("GNBDUFunction", "", "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]", - paginationDTO)).thenReturn(response); - - doThrow(TiesException.class).when(requestValidator).validateEntityTypeInDomain(eq("CloudSite"), eq("RAN_LOGICAL")); - doThrow(TiesException.class).when(requestValidator).validateEntityTypeInDomain(eq("GNBDUFunction2"), eq( - "RAN_LOGICAL")); - - when(dataService.getTopologyByType("GNBDUFunction", "", "/attributes[contains ( fdn, \"/SubNetwork Ireland/\")]", - PaginationDTO.builder().offset(0).limit(3).addQueryParameters("targetFilter", "").addQueryParameters( - "scopeFilter", "/attributes[contains ( fdn, \"/SubNetwork Ireland/\")]").basePath( - "/domains/RAN_LOGICAL/entity-types/GNBDUFunction/entities").addPathParameters("domain", - "RAN_LOGICAL").build())).thenThrow(TiesPathException.grammarError("'@' missing")); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistenceServiceImplGETRequestsContainerizedTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistenceServiceImplGETRequestsContainerizedTest.java deleted file mode 100644 index 504974d..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataPersistenceServiceImplGETRequestsContainerizedTest.java +++ /dev/null @@ -1,1190 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.impl; - -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.ITEMS; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; -import static org.oran.smo.teiv.utils.exposure.PaginationVerifierTestUtil.verifyResponse; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.sql.DataSource; - -import org.oran.smo.teiv.schema.DataType; -import org.jooq.DSLContext; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Configuration; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.oran.smo.teiv.db.TestPostgresqlContainer; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.spi.mapper.MapperUtility; -import org.oran.smo.teiv.exposure.spi.mapper.PaginationMetaData; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.PostgresSchemaLoader; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.startup.SchemaHandler; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; -import java.util.HashSet; - -@Configuration -@SpringBootTest -class DataPersistenceServiceImplGETRequestsContainerizedTest { - public static TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); - private static DataPersistanceServiceImpl underTest; - private static MapperUtility mapperUtility; - private static DSLContext dslContext; - private static DSLContext writeDataDslContext; - private static final String REL_ID_PREFIX = "urn:base64:"; - - @MockBean - private SchemaHandler schemaHandler; - - @BeforeAll - public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { - String url = postgreSQLContainer.getJdbcUrl(); - DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); - dslContext = DSL.using(ds, SQLDialect.POSTGRES); - writeDataDslContext = DSL.using(ds, SQLDialect.POSTGRES); - mapperUtility = new MapperUtility(); - underTest = new DataPersistanceServiceImpl(dslContext, writeDataDslContext, mapperUtility); - PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(dslContext, new ObjectMapper()); - postgresSchemaLoader.loadSchemaRegistry(); - TestPostgresqlContainer.loadSampleData(); - } - - @BeforeEach - public void deleteAll() { - writeDataDslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach( - t -> writeDataDslContext.truncate(t).cascade().execute()); - TestPostgresqlContainer.loadSampleData(); - } - - @Test - void testGetTopology() { - Map> response = new HashMap<>(); - Map responseData = new HashMap<>(); - Map attributesMap = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:GNBDUFunction", List.of(responseData)); - attributesMap.put("gNBDUId", null); - attributesMap.put("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16"); - attributesMap.put("dUpLMNId", Map.of("mcc", "456", "mnc", "82")); - attributesMap.put("gNBId", 16L); - attributesMap.put("gNBIdLength", 2L); - attributesMap.put("cmId", null); - responseData.put("attributes", attributesMap); - responseData.put("id", "5A548EA9D166341776CA0695837E55D8"); - responseData.put("sourceIds", List.of( - "urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary" + "/GNBDUFunction=16", - "urn:cmHandle:/395221E080CCF0FD1924103B15873814")); - - Assertions.assertEquals(response, underTest.getTopology(SchemaRegistry.getEntityTypeByName("GNBDUFunction"), - "5A548EA9D166341776CA0695837E55D8")); - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getTopology(SchemaRegistry.getEntityTypeByName( - "GNBDUFunction"), "-1")); - - response.clear(); - responseData.clear(); - attributesMap.clear(); - - response.put("o-ran-smo-teiv-ran:AntennaCapability", List.of(responseData)); - attributesMap.put("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaCapability=1"); - attributesMap.put("eUtranFqBands", List.of("123", "4564", "789")); - attributesMap.put("geranFqBands", List.of("123", "456", "789")); - attributesMap.put("nRFqBands", List.of("123", "456", "789")); - attributesMap.put("cmId", null); - responseData.put("attributes", attributesMap); - responseData.put("id", "5835F77BE9D4E102316BD59195F6370B"); - responseData.put("sourceIds", Collections.EMPTY_LIST); - - Assertions.assertEquals(response, underTest.getTopology(SchemaRegistry.getEntityTypeByName("AntennaCapability"), - "5835F77BE9D4E102316BD59195F6370B")); - } - - @Test - void testGetAllRelationships_manyToOneAndOneToMany() { - List>> mapsList = new ArrayList<>(); - Map response = new HashMap<>(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/NRCellDU/B480427E8A0C0B8D994E437784BB382F/relationships").addPathParameters("eiid", - "B480427E8A0C0B8D994E437784BB382F").addPathParameters("domain", "RAN").addPathParameters( - "entityType", "NRCellDU").build(); - - paginationDTO1.setTotalSize(3); - response.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/NRCellDU/NON_EXISTING/relationships").addPathParameters("eiid", "NON_EXISTING") - .addPathParameters("domain", "RAN").addPathParameters("entityType", "NRCellDU").build(); - - mapsList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "D3215E08570BE58339C7463626B50E37", "B480427E8A0C0B8D994E437784BB382F", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==")))); - - mapsList.add(Map.of("o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU", List.of(generateResponse( - "F5128C172A70C4FCD4739650B06DE9E2", "B480427E8A0C0B8D994E437784BB382F", - REL_ID_PREFIX + "U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==")))); - - mapsList.add(Map.of("o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER", List.of(generateResponse( - "B480427E8A0C0B8D994E437784BB382F", "E49D942C16E0364E1E0788138916D70C", - REL_ID_PREFIX + "TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM=")))); - - response.put(ITEMS, mapsList); - - verifyResponse(response, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName("NRCellDU"), - SchemaRegistry.getRelationTypesByEntityName("NRCellDU"), "B480427E8A0C0B8D994E437784BB382F", - paginationDTO1)); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(SchemaRegistry - .getEntityTypeByName("NRCellDU"), SchemaRegistry.getRelationTypesByEntityName("NRCellDU"), "NON_EXISTING", - paginationDTO2)); - } - - @Test - void testGetAllRelationships_manyToMany() { - Map response = new HashMap<>(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/GNBCUUPFunction/BFEEAC2CE60273CB0A78319CC201A7FE/relationships").addPathParameters( - "eiid", "BFEEAC2CE60273CB0A78319CC201A7FE").addPathParameters("domain", "RAN").addPathParameters( - "entityType", "GNBCUUPFunction").build(); - paginationDTO1.setTotalSize(2); - response.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/NRCellDU/NON_EXISTING/relationships").addPathParameters("eiid", "NON_EXISTING") - .addPathParameters("domain", "RAN").addPathParameters("entityType", "NRCellDU").build(); - - List>> mapsList = new ArrayList<>(); - - mapsList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", List.of( - generateResponse("BFEEAC2CE60273CB0A78319CC201A7FE", "AD42D90497E93D276215DF6D3B899E17", - REL_ID_PREFIX + "R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc=")))); - - mapsList.add(Map.of("o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", List.of(generateResponse( - "E64371CD4D12ED0CED200DD3A7591784", "BFEEAC2CE60273CB0A78319CC201A7FE", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU=")))); - - response.put(ITEMS, mapsList); - - verifyResponse(response, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName("GNBCUUPFunction"), - SchemaRegistry.getRelationTypesByEntityName("GNBCUUPFunction"), "BFEEAC2CE60273CB0A78319CC201A7FE", - paginationDTO1)); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(SchemaRegistry - .getEntityTypeByName("GNBCUUPFunction"), SchemaRegistry.getRelationTypesByEntityName("GNBCUUPFunction"), - "NON_EXISTING", paginationDTO2)); - } - - @Test - void testGetAllRelationshipsManyToMany_filteredByRelationship() { - List>> mapsList = new ArrayList<>(); - Map response = new HashMap<>(); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/GNBCUUPFunction/BFEEAC2CE60273CB0A78319CC201A7FE/relationships").addPathParameters( - "eiid", "BFEEAC2CE60273CB0A78319CC201A7FE").addPathParameters("domain", "RAN").addPathParameters( - "entityType", "GNBCUUPFunction").build(); - paginationDTO1.setTotalSize(1); - paginationDTO1.setQueryParameters(Map.of("relationshipType", "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION")); - - response.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - mapsList.add(Map.of("o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", List.of(generateResponse( - "E64371CD4D12ED0CED200DD3A7591784", "BFEEAC2CE60273CB0A78319CC201A7FE", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU=")))); - mapsList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", List.of( - generateResponse("BFEEAC2CE60273CB0A78319CC201A7FE", "AD42D90497E93D276215DF6D3B899E17", - REL_ID_PREFIX + "R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc=")))); - - response.put(ITEMS, List.of(mapsList.get(0))); - verifyResponse(response, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName("GNBCUUPFunction"), List - .of(SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION")), - "BFEEAC2CE60273CB0A78319CC201A7FE", paginationDTO1)); - - response.replace(ITEMS, List.of(mapsList.get(0)), List.of(mapsList.get(1))); - paginationDTO1.setQueryParameters(Map.of("relationshipType", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")); - response.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - verifyResponse(response, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName("GNBCUUPFunction"), List - .of(SchemaRegistry.getRelationTypeByName("GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")), - "BFEEAC2CE60273CB0A78319CC201A7FE", paginationDTO1)); - - paginationDTO1.setQueryParameters(Map.of("relationshipType", "NON_EXISTING")); - response.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(SchemaRegistry - .getEntityTypeByName("GNBCUUPFunction"), List.of(SchemaRegistry.getRelationTypeByName( - "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")), "NON_EXISTING", paginationDTO1)); - } - - @Test - void testGetAllRelationshipsConnectingSameEntity_filteredByRelationship() { - String idConnectingSameEntity = REL_ID_PREFIX + "QW50ZW5uYU1vZHVsZToyNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg=="; - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN_EQUIPMENT/entities/AntennaModule/278A05C67D47D117C2DC5BDF5E00AE70/relationships") - .addPathParameters("eiid", "278A05C67D47D117C2DC5BDF5E00AE70").addPathParameters("domain", "RAN_EQUIPMENT") - .addPathParameters("entityType", "AntennaModule").build(); - paginationDTO1.setTotalSize(1); - paginationDTO1.setQueryParameters(Map.of("relationshipType", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE")); - - Map response = new HashMap<>(new PaginationMetaData().getObjectList(paginationDTO1)); - Map> mapsList = Map.of("o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", List - .of(generateResponse("278A05C67D47D117C2DC5BDF5E00AE70", "279A05C67D47D117C2DC5BDF5E00AE70", - idConnectingSameEntity))); - response.put(ITEMS, List.of(mapsList)); - - RelationType relSameEntity = SchemaRegistry.getRelationTypeByName("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - EntityType entity = SchemaRegistry.getEntityTypeByName("AntennaModule"); - - Assertions.assertNotNull(relSameEntity); - Assertions.assertNotNull(entity); - - verifyResponse(response, underTest.getAllRelationships(entity, List.of(relSameEntity), - "278A05C67D47D117C2DC5BDF5E00AE70", paginationDTO1)); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(entity, List.of( - relSameEntity), "NON_EXISTING", paginationDTO1)); - } - - @Test - void testGetRelationshipWithSpecifiedId() { - String idOneToMany = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ=="; - Map> relationshipOneToMany = Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List - .of(generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", idOneToMany, - Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipOneToMany, underTest.getRelationshipWithSpecifiedId(idOneToMany, SchemaRegistry - .getRelationTypeByName("GNBDUFUNCTION_PROVIDES_NRCELLDU"))); - - String idManyToOne = REL_ID_PREFIX + "Tm9kZUNsdXN0ZXI6MDE1QzJEREJEN0FDNzIyQjM0RUQ2QTIwRURFRUI5QzM6TE9DQVRFRF9BVDpDbG91ZFNpdGU6MTZFRTE3QUU4OURGMTFCNjlFOTRCM0Y2ODI3QzJDMEU="; - Map> relationshipManyToOne = Map.of("o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE", - List.of(generateResponse("015C2DDBD7AC722B34ED6A20EDEEB9C3", "16EE17AE89DF11B69E94B3F6827C2C0E", - idManyToOne, Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipManyToOne, underTest.getRelationshipWithSpecifiedId(idManyToOne, SchemaRegistry - .getRelationTypeByName("NODECLUSTER_LOCATED_AT_CLOUDSITE"))); - - String idManyToMany = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE"; - Map> relationshipManyToMany = Map.of( - "o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", List.of(generateResponse( - "4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", idManyToMany, - Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipManyToMany, underTest.getRelationshipWithSpecifiedId(idManyToMany, - SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"))); - - String idConnectingSameEntity = REL_ID_PREFIX + "QW50ZW5uYU1vZHVsZToyNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg=="; - Map> relationshipConnectingSameEntity = Map.of( - "o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", List.of(generateResponse( - "278A05C67D47D117C2DC5BDF5E00AE70", "279A05C67D47D117C2DC5BDF5E00AE70", idConnectingSameEntity, - Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipConnectingSameEntity, underTest.getRelationshipWithSpecifiedId( - idConnectingSameEntity, SchemaRegistry.getRelationTypeByName("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"))); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getRelationshipWithSpecifiedId("NOT_EXISTING", - SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_PROVIDES_NRCELLDU"))); - } - - @Test - void testGetRelationshipsByType() { - Map oneToManyResult = new HashMap<>(); - Map manyToOneResult = new HashMap<>(); - Map manyToManyResult = new HashMap<>(); - - Map oneToManyQueryMap = new HashMap<>(); - oneToManyQueryMap.put("query", Map.of("scopeFilter", "/attributes[@cellLocalId=2]")); - oneToManyResult.putAll(oneToManyQueryMap); - - oneToManyResult.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "F9546E82313AC1D5E690DCD7BE55606F", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpGOTU0NkU4MjMxM0FDMUQ1RTY5MERDRDdCRTU1NjA2Rg=="))))); - - PaginationMetaData metadataOneToMany = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/attributes[@cellLocalId=2]").build(); - paginationDTO1.setTotalSize(1); - oneToManyResult.putAll(metadataOneToMany.getObjectList(paginationDTO1)); - - Map manyToOneQueryMap = new HashMap<>(); - manyToOneQueryMap.put("query", Map.of("scopeFilter", "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]")); - manyToOneResult.putAll(manyToOneQueryMap); - - manyToOneResult.put("items", List.of(Map.of("o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE", - List.of(generateResponse("719BD5C7CD8A939D76A83DA95DA45C01", "1C02E96B2AAE036C7AE404BC38C308E0", - REL_ID_PREFIX + "Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA="))))); - - PaginationMetaData metadataManyToOne = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]").build(); - paginationDTO2.setTotalSize(1); - manyToOneResult.putAll(metadataManyToOne.getObjectList(paginationDTO2)); - - Map manyToManyQueryMap = new HashMap<>(); - manyToManyQueryMap.put("query", Map.of("scopeFilter", - "/CloudNativeApplication/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"]")); - manyToManyResult.putAll(manyToManyQueryMap); - - manyToManyResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", List.of(generateResponse( - "4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE"))))); - - PaginationMetaData metadataManyToMany = new PaginationMetaData(); - PaginationDTO paginationDTO3 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/CloudNativeApplication/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"]").build(); - paginationDTO3.setTotalSize(1); - manyToManyResult.putAll(metadataManyToMany.getObjectList(paginationDTO3)); - - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_PROVIDES_NRCELLDU"); - RelationType manyToOne = SchemaRegistry.getRelationTypeByName("CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE"); - RelationType manyToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - - verifyResponse(oneToManyResult, underTest.getRelationshipsByType(oneToMany, "/attributes[@cellLocalId=2]", - PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", "/attributes[@cellLocalId=2]") - .build())); - - verifyResponse(manyToOneResult, underTest.getRelationshipsByType(manyToOne, - "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]", PaginationDTO.builder().offset(0).limit(5) - .addQueryParameters("scopeFilter", "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]").build())); - - verifyResponse(manyToManyResult, underTest.getRelationshipsByType(manyToMany, - "/CloudNativeApplication/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"]", PaginationDTO.builder().offset(0) - .limit(5).addQueryParameters("scopeFilter", - "/CloudNativeApplication/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"]").build())); - - assertThatThrownBy(() -> underTest.getRelationshipsByType(oneToMany, "/attributes[@celllocalid=2]", PaginationDTO - .builder().offset(0).limit(5).build())).isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(oneToMany, null, PaginationDTO.builder() - .offset(0).limit(5).build())); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(oneToMany, - "/GNBDUFunction/attributes[contains (@fdn, \"GNBDUFunction=16\")]", PaginationDTO.builder().offset(0).limit( - 5).build())); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(manyToMany, - "/CloudNativeApplication/attributes[@name=\"Example Cloud App/10\"] | /GNBDUFunction/id[@id=\"5A548EA9D166341776CA0695837E55D8\"]", - PaginationDTO.builder().offset(0).limit(5).build())); - } - - @Test - void testGetRelationshipsByType_relConnectingSameEntity() { - - Map resultOneScopeFilter = new HashMap<>(); - Map resultTwoScopeFilter = new HashMap<>(); - RelationType relationshipConnectingSameEntity = SchemaRegistry.getRelationTypeByName( - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - String idConnectingSameEntity = REL_ID_PREFIX + "QW50ZW5uYU1vZHVsZToyNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg=="; - PaginationMetaData metadataRelConnectingSameEntity = new PaginationMetaData(); - - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]").build(); - paginationDTO1.setTotalSize(1); - resultOneScopeFilter.putAll(metadataRelConnectingSameEntity.getObjectList(paginationDTO1)); - - Map queryMapOneScope = new HashMap<>(); - queryMapOneScope.put("query", Map.of("scopeFilter", "/AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]")); - resultOneScopeFilter.putAll(queryMapOneScope); - - resultOneScopeFilter.put("items", List.of(Map.of("o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", - List.of(generateResponse("278A05C67D47D117C2DC5BDF5E00AE70", "279A05C67D47D117C2DC5BDF5E00AE70", - idConnectingSameEntity))))); - - verifyResponse(resultOneScopeFilter, underTest.getRelationshipsByType(relationshipConnectingSameEntity, - "/AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]", PaginationDTO.builder().offset(0).limit(5) - .addQueryParameters("scopeFilter", "/AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]") - .build())); - - Map queryMapTwoScopes = new HashMap<>(); - queryMapTwoScopes.put("query", Map.of("scopeFilter", - "/AntennaModule/id[@id=\"278A05C67D47D117C2DC5BDF5E00AE70\"] | /AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]")); - resultTwoScopeFilter.putAll(queryMapTwoScopes); - - resultTwoScopeFilter.put("items", List.of(Map.of("o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", - List.of(generateResponse("278A05C67D47D117C2DC5BDF5E00AE70", "279A05C67D47D117C2DC5BDF5E00AE70", - idConnectingSameEntity))))); - - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/AntennaModule/id[@id=\"278A05C67D47D117C2DC5BDF5E00AE70\"] | /AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]") - .build(); - paginationDTO2.setTotalSize(1); - resultTwoScopeFilter.putAll(metadataRelConnectingSameEntity.getObjectList(paginationDTO2)); - - verifyResponse(resultTwoScopeFilter, underTest.getRelationshipsByType(relationshipConnectingSameEntity, - "/AntennaModule/id[@id=\"278A05C67D47D117C2DC5BDF5E00AE70\"]| /AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]", - PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/AntennaModule/id[@id=\"278A05C67D47D117C2DC5BDF5E00AE70\"] | /AntennaModule/id[@id=\"279A05C67D47D117C2DC5BDF5E00AE70\"]") - .build())); - - } - - @Test - void testGetTopologyByType() { - Map result = new HashMap<>(); - Map queryMap = new HashMap<>(); - - queryMap.put("query", Map.of("targetFilter", "/attributes(fdn)", "scopeFilter", - "/attributes[contains(@fdn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']")); - - result.putAll(queryMap); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/RAN/entities/GNBDUFunction").offset(0) - .limit(2).addQueryParameters("targetFilter", "/attributes(fdn)").addQueryParameters("scopeFilter", - "/attributes[contains(@fdn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']").build(); - paginationDTO.setTotalSize(2); - result.putAll(new PaginationMetaData().getObjectList(paginationDTO)); - - result.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of(ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=13"), "id", - "25E690E22BDA90B9C4FEE1F083CBA597"), Map.of(ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=14"), - "id", "5A3085C3400C3096E2ED2321452766B1"))))); - - verifyResponse(result, underTest.getTopologyByType("GNBDUFunction", "/attributes(fdn)", - "/attributes[contains(@fdn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']", PaginationDTO.builder() - .offset(0).limit(2).basePath("/domains/RAN/entities/GNBDUFunction").addQueryParameters( - "targetFilter", "/attributes(fdn)").addQueryParameters("scopeFilter", - "/attributes[contains(@fdn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']") - .build())); - - Assertions.assertThrows(TiesPathException.class, () -> underTest.getTopologyByType("GNBDUFunction", - "/attributes(fdn)", "/attributes[contains(@fdn, \"1000493\")] ; /attributes[@gNBId=4000259]", PaginationDTO - .builder().offset(0).limit(2).build())); - } - - @Test - void testGetEntitiesByDomain() { - Map reference1 = new HashMap<>(); - Map query = new HashMap<>(); - - query.put("targetFilter", "/attributes(azimuth)"); - query.put("scopeFilter", "/attributes[@azimuth=3]"); - - PaginationMetaData pmd1 = new PaginationMetaData(); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", "/attributes(azimuth)").addQueryParameters("scopeFilter", - "/attributes[@azimuth=3]").build(); - paginationDTO.setTotalSize(1); - reference1.putAll(pmd1.getObjectList(paginationDTO)); - reference1.put("query", query); - - BigDecimal azimuth = new BigDecimal(3); - reference1.put("items", List.of(Map.of("o-ran-smo-teiv-ran:Sector", List.of(Map.of("id", - "ADB1BAAC878C0BEEFE3175C60F44BB1D", ATTRIBUTES, Map.of("azimuth", azimuth)))))); - verifyResponse(reference1, underTest.getEntitiesByDomain("RAN", "/attributes(azimuth)", "/attributes[@azimuth=3]", - paginationDTO)); - - Map reference2 = new HashMap<>(); - Map query2 = new HashMap<>(); - - query2.put("targetFilter", "/id"); - query2.put("scopeFilter", "/id[contains(@id,\"F1407\")]"); - - PaginationMetaData pmd2 = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath("/domains/RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", "/id").addQueryParameters("scopeFilter", "/id[contains(@id,\"F1407\")]") - .build(); - paginationDTO2.setTotalSize(1); - pmd2.getObjectList(paginationDTO2); - - reference2.put("query", query2); - PaginationDTO paginationDTO3 = PaginationDTO.builder().basePath("/domains/RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", "/id").addQueryParameters("scopeFilter", "/id[contains(@id,\"F1407\")]") - .build(); - paginationDTO3.setTotalSize(1); - reference2.putAll(pmd2.getObjectList(paginationDTO3)); - - reference2.put("items", List.of(Map.of("o-ran-smo-teiv-ran:Sector", List.of(Map.of("id", - "2F445AA5744FA3D230FD6838531F1407"))))); - - verifyResponse(reference2, underTest.getEntitiesByDomain("RAN", "/id", "/id[contains(@id,\"F1407\")]", - paginationDTO2)); - - Map reference3 = new HashMap<>(); - Map query3 = new HashMap<>(); - - query3.put("targetFilter", "/GNBDUFunction/attributes/fdn"); - query3.put("scopeFilter", "/GNBDUFunction/attributes[contains(@fdn,\"GNBDUFunction=10\")]"); - - PaginationMetaData pmd3 = new PaginationMetaData(); - - reference3.put("query", query3); - PaginationDTO paginationDTO4 = PaginationDTO.builder().basePath("/domains/RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", "/GNBDUFunction/attributes/fdn").addQueryParameters("scopeFilter", - "/GNBDUFunction/attributes[contains(@fdn,\"GNBDUFunction=10\")]").build(); - paginationDTO4.setTotalSize(1); - reference3.putAll(pmd3.getObjectList(paginationDTO4)); - - reference3.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "1050570EBB1315E1AE7A9FD5E1400A00", ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=10")))))); - - verifyResponse(reference3, underTest.getEntitiesByDomain("RAN", "/GNBDUFunction/attributes/fdn", - "/GNBDUFunction/attributes[contains(@fdn,\"GNBDUFunction=10\")]", paginationDTO4)); - - Object result = underTest.getEntitiesByDomain("OAM_TO_RAN", "/id", "", PaginationDTO.builder().offset(0).limit(500) - .build()); - Assertions.assertEquals(10, ((Map) ((List) ((HashMap) result).get("items")).get(0)).size()); - Assertions.assertTrue(((Map) ((List) ((HashMap) result).get("items")).get(0)).containsKey( - "o-ran-smo-teiv-oam:ManagedElement")); - - Assertions.assertTrue(((Map) ((List) ((HashMap) result).get("items")).get(0)).containsKey( - "o-ran-smo-teiv-ran:GNBDUFunction")); - } - - @Test - void testGetTopologyWithLongNames() { - Map> response = new HashMap<>(); - Map responseData = new HashMap<>(); - Map attributesMap = new HashMap<>(); - response.put("o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", List.of( - responseData)); - attributesMap.put("gNBDUId", null); - attributesMap.put("fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16"); - attributesMap.put("dUpLMNId", Map.of("mcc", "456", "mnc", "82")); - attributesMap.put("gNBId", 16L); - attributesMap.put("gNBIdLength", 2L); - attributesMap.put("cmId", null); - responseData.put("attributes", attributesMap); - responseData.put("id", "5A548EA9D166341776CA0695837E55D8"); - responseData.put("sourceIds", Collections.EMPTY_LIST); - - Assertions.assertEquals(response, underTest.getTopology(SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), "5A548EA9D166341776CA0695837E55D8")); - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getTopology(SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), "-1")); - } - - @Test - void testGetAllRelationshipsWithLongNames_manyToOne_oneToMany_manyToMany() { - Map response = new HashMap<>(); - List>> mapsList = new ArrayList<>(); - - PaginationDTO paginationDTO = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/4CFF136200A2DE36205A13559C55DB2A/relationships") - .addPathParameters("eiid", "4CFF136200A2DE36205A13559C55DB2A").addPathParameters("domain", "RAN") - .addPathParameters("entityType", "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn") - .build(); - paginationDTO.setTotalSize(6); - response.putAll(new PaginationMetaData().getObjectList(paginationDTO)); - - mapsList.add(Map.of("o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN", - List.of(generateResponse("8D51EFC759166044DACBCA63C4EDFC51", "4CFF136200A2DE36205A13559C55DB2A", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6OEQ1MUVGQzc1OTE2NjA0NERBQ0JDQTYzQzRFREZDNTE6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjRDRkYxMzYyMDBBMkRFMzYyMDVBMTM1NTlDNTVEQjJB")))); - - mapsList.add(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU", List.of( - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "76E9F605D4F37330BF0B505E94F64F11", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTo3NkU5RjYwNUQ0RjM3MzMwQkYwQjUwNUU5NEY2NEYxMQ=="), - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "67A1BDA10B5AF43028D07C7BE5CB1AE2", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTo2N0ExQkRBMTBCNUFGNDMwMjhEMDdDN0JFNUNCMUFFMg=="), - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "B3B0A1939EFCA654A37005B6A7F24BD7", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTpCM0IwQTE5MzlFRkNBNjU0QTM3MDA1QjZBN0YyNEJENw=="), - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "F26F279E91D0941DB4F646E707EA403A", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTpGMjZGMjc5RTkxRDA5NDFEQjRGNjQ2RTcwN0VBNDAzQQ==")))); - - mapsList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", - List.of(generateResponse("4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE")))); - - response.put(ITEMS, mapsList); - - verifyResponse(response, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), SchemaRegistry - .getRelationTypesByEntityName("GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), - "4CFF136200A2DE36205A13559C55DB2A", paginationDTO)); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(SchemaRegistry - .getEntityTypeByName("GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), SchemaRegistry - .getRelationTypesByEntityName("GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), - "NON_EXISTING", paginationDTO)); - } - - @Test - void testGetAllRelationshipsWithLongNames_filteredByRelationship() { - List>> mapsList = new ArrayList<>(); - - //One_To_One - Map expectedResponse1 = new HashMap<>(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN_OAM/entities/ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt/45EF31D8A1FD624D7276390A1215BFC3/relationships") - .addPathParameters("eiid", "45EF31D8A1FD624D7276390A1215BFC3").addPathParameters("domain", "RAN") - .addPathParameters("entityType", "ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt") - .build(); - paginationDTO1.setTotalSize(1); - paginationDTO1.setQueryParameters(Map.of("relationshipType", - "MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM")); - expectedResponse1.putAll(new PaginationMetaData().getObjectList(paginationDTO1)); - mapsList.add(Map.of("o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM", - List.of(generateResponse("45EF31D8A1FD624D7276390A1215BFC3", "C4E311A55666726FD9FE25CA572AFAF9", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6NDVFRjMxRDhBMUZENjI0RDcyNzYzOTBBMTIxNUJGQzM6REVQTE9ZRURfQVM6Q2xvdWROYXRpdmVTeXN0ZW06QzRFMzExQTU1NjY2NzI2RkQ5RkUyNUNBNTcyQUZBRjk=")))); - expectedResponse1.put(ITEMS, List.of(mapsList.get(0))); - verifyResponse(expectedResponse1, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName( - "ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt"), List.of(SchemaRegistry - .getRelationTypeByName("MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM")), - "45EF31D8A1FD624D7276390A1215BFC3", paginationDTO1)); - - //One_To_Many - Map expectedResponse2 = new HashMap<>(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/45EF31D8A1FD624D7276390A1215BFC3/relationships") - .addPathParameters("eiid", "45EF31D8A1FD624D7276390A1215BFC3").addPathParameters("domain", "RAN") - .addPathParameters("entityType", "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn") - .build(); - paginationDTO2.setTotalSize(1); - paginationDTO2.setQueryParameters(Map.of("relationshipType", - "MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN")); - expectedResponse2.putAll(new PaginationMetaData().getObjectList(paginationDTO2)); - mapsList.add(Map.of("o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN", - List.of(generateResponse("8D51EFC759166044DACBCA63C4EDFC51", "4CFF136200A2DE36205A13559C55DB2A", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6OEQ1MUVGQzc1OTE2NjA0NERBQ0JDQTYzQzRFREZDNTE6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjRDRkYxMzYyMDBBMkRFMzYyMDVBMTM1NTlDNTVEQjJB")))); - expectedResponse2.put(ITEMS, List.of(mapsList.get(1))); - verifyResponse(expectedResponse2, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), List.of(SchemaRegistry - .getRelationTypeByName("MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN")), - "4CFF136200A2DE36205A13559C55DB2A", paginationDTO2)); - - //Many_To_One - Map expectedResponse3 = new HashMap<>(); - PaginationDTO paginationDTO3 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN_CLOUD/entities/Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/719BD5C7CD8A939D76A83DA95DA45C01/relationships") - .addPathParameters("eiid", "719BD5C7CD8A939D76A83DA95DA45C01").addPathParameters("domain", "RAN_CLOUD") - .addPathParameters("entityType", "Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - .build(); - paginationDTO3.setTotalSize(1); - paginationDTO3.setQueryParameters(Map.of("relationshipType", - "CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE")); - expectedResponse3.putAll(new PaginationMetaData().getObjectList(paginationDTO3)); - mapsList.add(Map.of("o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE", List - .of(generateResponse("719BD5C7CD8A939D76A83DA95DA45C01", "1C02E96B2AAE036C7AE404BC38C308E0", - REL_ID_PREFIX + "Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA=")))); - expectedResponse3.put(ITEMS, List.of(mapsList.get(2))); - verifyResponse(expectedResponse3, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName( - "Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), List.of(SchemaRegistry - .getRelationTypeByName("CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE")), - "1C02E96B2AAE036C7AE404BC38C308E0", paginationDTO3)); - - //Many_To_Many - Map expectedResponse4 = new HashMap<>(); - PaginationDTO paginationDTO4 = PaginationDTO.builder().offset(0).limit(100).basePath( - "/domains/RAN/entities/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/4CFF136200A2DE36205A13559C55DB2A/relationships") - .addPathParameters("eiid", "4CFF136200A2DE36205A13559C55DB2A").addPathParameters("domain", "CLOUD_TO_RAN") - .addPathParameters("entityType", "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn") - .build(); - paginationDTO4.setTotalSize(1); - paginationDTO4.setQueryParameters(Map.of("relationshipType", - "GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN")); - expectedResponse4.putAll(new PaginationMetaData().getObjectList(paginationDTO4)); - mapsList.add(Map.of("o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", - List.of(generateResponse("4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE")))); - expectedResponse4.put(ITEMS, List.of(mapsList.get(3))); - verifyResponse(expectedResponse4, underTest.getAllRelationships(SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), List.of(SchemaRegistry - .getRelationTypeByName("GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN")), - "4CFF136200A2DE36205A13559C55DB2A", paginationDTO4)); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getAllRelationships(SchemaRegistry - .getEntityTypeByName("GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"), List.of( - SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN")), "NON_EXISTING", - paginationDTO4)); - } - - @Test - void testGetRelationshipWithSpecifiedIdWithLongNames() { - String idOneToOne = REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6NDVFRjMxRDhBMUZENjI0RDcyNzYzOTBBMTIxNUJGQzM6REVQTE9ZRURfQVM6Q2xvdWROYXRpdmVTeXN0ZW06QzRFMzExQTU1NjY2NzI2RkQ5RkUyNUNBNTcyQUZBRjk="; - Map> relationshipOneToOne = Map.of( - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM", List.of( - generateResponse("45EF31D8A1FD624D7276390A1215BFC3", "C4E311A55666726FD9FE25CA572AFAF9", idOneToOne, - Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipOneToOne, underTest.getRelationshipWithSpecifiedId(idOneToOne, SchemaRegistry - .getRelationTypeByName("MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM"))); - - String idOneToMany = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ=="; - Map> relationshipOneToMany = Map.of( - "o-ran-smo-teiv-ran:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "98C3A4591A37718E1330F0294E23B62A", - idOneToMany, Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipOneToMany, underTest.getRelationshipWithSpecifiedId(idOneToMany, SchemaRegistry - .getRelationTypeByName("GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU"))); - - String idManyToOne = REL_ID_PREFIX + "Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA="; - Map> relationshipManyToOne = Map.of( - "o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE", List.of( - generateResponse("719BD5C7CD8A939D76A83DA95DA45C01", "1C02E96B2AAE036C7AE404BC38C308E0", - idManyToOne, Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipManyToOne, underTest.getRelationshipWithSpecifiedId(idManyToOne, SchemaRegistry - .getRelationTypeByName("CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE"))); - - String idManyToMany = REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE"; - Map> relationshipManyToMany = Map.of( - "o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", List.of( - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", - idManyToMany, Collections.EMPTY_LIST))); - - Assertions.assertEquals(relationshipManyToMany, underTest.getRelationshipWithSpecifiedId(idManyToMany, - SchemaRegistry.getRelationTypeByName("GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN"))); - - Assertions.assertThrowsExactly(TiesException.class, () -> underTest.getRelationshipWithSpecifiedId("NOT_EXISTING", - SchemaRegistry.getRelationTypeByName("GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU"))); - } - - @Test - void testGetRelationshipsByTypeWithLongNames() { - Map oneToOneResult = new HashMap<>(); - Map oneToManyResult = new HashMap<>(); - Map manyToOneResult = new HashMap<>(); - Map manyToManyResult = new HashMap<>(); - - oneToOneResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM", List.of( - generateResponse("45EF31D8A1FD624D7276390A1215BFC3", "C4E311A55666726FD9FE25CA572AFAF9", - REL_ID_PREFIX + "TWFuYWdlZEVsZW1lbnQ6NDVFRjMxRDhBMUZENjI0RDcyNzYzOTBBMTIxNUJGQzM6REVQTE9ZRURfQVM6Q2xvdWROYXRpdmVTeXN0ZW06QzRFMzExQTU1NjY2NzI2RkQ5RkUyNUNBNTcyQUZBRjk="))))); - PaginationMetaData metadataOneToOne = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(5).build(); - paginationDTO1.setTotalSize(1); - oneToOneResult.putAll(metadataOneToOne.getObjectList(paginationDTO1)); - - oneToManyResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-ran:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU", List.of( - generateResponse("D3215E08570BE58339C7463626B50E37", "F9546E82313AC1D5E690DCD7BE55606F", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpGOTU0NkU4MjMxM0FDMUQ1RTY5MERDRDdCRTU1NjA2Rg=="))))); - PaginationMetaData metadataOneToMany = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/attributes[@cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd=2]").build(); - paginationDTO2.setTotalSize(1); - oneToManyResult.putAll(metadataOneToMany.getObjectList(paginationDTO2)); - - manyToOneResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE", List.of( - generateResponse("719BD5C7CD8A939D76A83DA95DA45C01", "1C02E96B2AAE036C7AE404BC38C308E0", - REL_ID_PREFIX + "Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA="))))); - PaginationMetaData metadataManyToOne = new PaginationMetaData(); - PaginationDTO paginationDTO3 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]").build(); - paginationDTO3.setTotalSize(1); - manyToOneResult.putAll(metadataManyToOne.getObjectList(paginationDTO3)); - - manyToManyResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", List.of( - generateResponse("4CFF136200A2DE36205A13559C55DB2A", "C549905CF3CC890CE5746C5E10ACF00D", - REL_ID_PREFIX + "R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE"))))); - PaginationMetaData metadataManyToMany = new PaginationMetaData(); - PaginationDTO paginationDTO4 = PaginationDTO.builder().offset(0).limit(5).addQueryParameters("scopeFilter", - "/CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"] | /GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/id[@id=\"4CFF136200A2DE36205A13559C55DB2A\"]") - .build(); - paginationDTO4.setTotalSize(1); - manyToManyResult.putAll(metadataManyToMany.getObjectList(paginationDTO4)); - - RelationType oneToOne = SchemaRegistry.getRelationTypeByName( - "MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU"); - RelationType manyToOne = SchemaRegistry.getRelationTypeByName( - "CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE"); - RelationType manyToMany = SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN"); - - verifyResponse(oneToOneResult, underTest.getRelationshipsByType(oneToOne, null, paginationDTO1)); - verifyResponse(oneToManyResult, underTest.getRelationshipsByType(oneToMany, - "/attributes[@cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd=2]", paginationDTO2)); - verifyResponse(manyToOneResult, underTest.getRelationshipsByType(manyToOne, - "/id[@id=\"719BD5C7CD8A939D76A83DA95DA45C01\"]", paginationDTO3)); - verifyResponse(manyToManyResult, underTest.getRelationshipsByType(manyToMany, - "/CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/id[@id=\"C549905CF3CC890CE5746C5E10ACF00D\"] | /GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/id[@id=\"4CFF136200A2DE36205A13559C55DB2A\"]", - paginationDTO4)); - - assertThatThrownBy(() -> underTest.getRelationshipsByType(oneToMany, "/attributes[@celllocalid=2]", PaginationDTO - .builder().offset(0).limit(5).build())).isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(oneToMany, null, PaginationDTO.builder() - .offset(0).limit(5).build())); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(oneToMany, - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn, \"GNBDUFunction=16\")]", - PaginationDTO.builder().offset(0).limit(5).build())); - Assertions.assertDoesNotThrow(() -> underTest.getRelationshipsByType(manyToMany, - "/CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes[@name=\"Example Cloud App/10\"] | /GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/id[@id=\"5A548EA9D166341776CA0695837E55D8\"]", - PaginationDTO.builder().offset(0).limit(5).build())); - } - - @Test - void testGetRelationshipsByTypeWithLongNames_relConnectingSameEntity() { - Map sameEntityOneToOneResult = new HashMap<>(); - Map sameEntityOneToManyResult = new HashMap<>(); - - // Rel connectingSameEntity ONE_TO_ONE - RelationType relSameEntityOneToOne = SchemaRegistry.getRelationTypeByName( - "ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE"); - sameEntityOneToOneResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE", List.of( - generateResponse("478A05C67D47D117C2DC5BDF5E00AE70", "479A05C67D47D117C2DC5BDF5E00AE70", - REL_ID_PREFIX + "QW50ZW5uYU1vZHVsZTo0NzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpERVBMT1lFRF9CWTpBbnRlbm5hTW9kdWxlOjQ3OUEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg=="))))); - PaginationMetaData metadataOneToMany = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().offset(0).limit(5).build(); - paginationDTO2.setTotalSize(1); - sameEntityOneToOneResult.putAll(metadataOneToMany.getObjectList(paginationDTO2)); - - verifyResponse(sameEntityOneToOneResult, underTest.getRelationshipsByType(relSameEntityOneToOne, null, PaginationDTO - .builder().offset(0).limit(5).build())); - - // Rel connectingSameEntity ONE_TO_MANY - RelationType relSameEntityOneToMany = SchemaRegistry.getRelationTypeByName( - "ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE"); - sameEntityOneToManyResult.put("items", List.of(Map.of( - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE", List.of( - generateResponse("378A05C67D47D117C2DC5BDF5E00AE70", "379A05C67D47D117C2DC5BDF5E00AE70", - REL_ID_PREFIX + "QW50ZW5uYU1vZHVsZTozNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjM3OUEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg=="))))); - PaginationMetaData metadataOneToOne = new PaginationMetaData(); - PaginationDTO paginationDTO1 = PaginationDTO.builder().offset(0).limit(5).build(); - paginationDTO1.setTotalSize(1); - sameEntityOneToManyResult.putAll(metadataOneToOne.getObjectList(paginationDTO1)); - - verifyResponse(sameEntityOneToManyResult, underTest.getRelationshipsByType(relSameEntityOneToMany, null, - PaginationDTO.builder().offset(0).limit(5).build())); - } - - @Test - void testGetTopologyByTypeWithLongNames() { - Map result = new HashMap<>(); - Map queryMap = new HashMap<>(); - - queryMap.put("query", Map.of("targetFilter", - "/attributes(fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn)", "scopeFilter", - "/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']")); - - result.putAll(queryMap); - - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/RAN/entities/GNBDUFunction").offset(0) - .limit(2).addQueryParameters("targetFilter", - "/attributes(fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn)").addQueryParameters( - "scopeFilter", - "/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']") - .build(); - paginationDTO.setTotalSize(2); - result.putAll(new PaginationMetaData().getObjectList(paginationDTO)); - - result.put("items", List.of(Map.of( - "o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", List.of(Map.of( - ATTRIBUTES, Map.of("fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=13"), - "id", "25E690E22BDA90B9C4FEE1F083CBA597"), Map.of(ATTRIBUTES, Map.of( - "fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=14"), - "id", "5A3085C3400C3096E2ED2321452766B1"))))); - - verifyResponse(result, underTest.getTopologyByType( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "/attributes(fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn)", - "/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn, \"13\")] | /id[@id='5A3085C3400C3096E2ED2321452766B1']", - paginationDTO)); - Assertions.assertThrows(TiesPathException.class, () -> underTest.getTopologyByType( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "/attributes(fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn)", - "/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn, \"1000493\")] ; /attributes[@gNBId=4000259]", - PaginationDTO.builder().offset(0).limit(2).build())); - } - - @Test - void testGetEntitiesByDomainWithLongNames() { - Map reference1 = new HashMap<>(); - Map query = new LinkedHashMap<>(); - - query.put("scopeFilter", "/attributes[@cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd=3]"); - query.put("targetFilter", "/attributes(cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd)"); - - PaginationMetaData pmd1 = new PaginationMetaData(); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/domains/EQUIPMENT_TO_RAN").offset(0).limit(5) - .build(); - paginationDTO.setQueryParameters(query); - paginationDTO.setTotalSize(1); - reference1.putAll(pmd1.getObjectList(paginationDTO)); - - reference1.put("query", query); - - reference1.put("items", List.of(Map.of( - "o-ran-smo-teiv-ran:NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU", List.of(Map.of("id", - "B480427E8A0C0B8D994E437784BB382F", ATTRIBUTES, Map.of( - "cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd", "3")))))); - - Map reference2 = new HashMap<>(); - Map query2 = new HashMap<>(); - - query2.put("targetFilter", "/id"); - query2.put("scopeFilter", "/id[contains(@id,\"EA403A\")]"); - - PaginationMetaData pmd2 = new PaginationMetaData(); - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath("/domains/EQUIPMENT_TO_RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", "/id").addQueryParameters("scopeFilter", - "/id[contains(@id,\"EA403A\")]").build(); - paginationDTO2.setTotalSize(1); - reference1.putAll(pmd2.getObjectList(paginationDTO2)); - - reference2.put("query", query2); - - reference2.put("items", List.of(Map.of( - "o-ran-smo-teiv-ran:NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU", List.of(Map.of("id", - "F26F279E91D0941DB4F646E707EA403A"))))); - - verifyResponse(reference2, underTest.getEntitiesByDomain("EQUIPMENT_TO_RAN", "/id", "/id[contains(@id,\"EA403A\")]", - paginationDTO2)); - - Map reference3 = new HashMap<>(); - Map query3 = new HashMap<>(); - - query3.put("targetFilter", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes/fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"); - query3.put("scopeFilter", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn,\"GNBDUFunction=10\")]"); - - PaginationMetaData pmd3 = new PaginationMetaData(); - PaginationDTO paginationDTO3 = PaginationDTO.builder().basePath("/domains/EQUIPMENT_TO_RAN").offset(0).limit(5) - .addQueryParameters("targetFilter", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes/fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn") - .addQueryParameters("scopeFilter", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn,\"GNBDUFunction=10\")]") - .build(); - paginationDTO3.setTotalSize(1); - reference1.putAll(pmd3.getObjectList(paginationDTO3)); - - reference3.put("query", query3); - - reference3.put("items", List.of(Map.of( - "o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", List.of(Map.of("id", - "1050570EBB1315E1AE7A9FD5E1400A00", ATTRIBUTES, Map.of( - "fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=10")))))); - - verifyResponse(reference3, underTest.getEntitiesByDomain("RAN", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes/fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "/GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn/attributes[contains(@fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn,\"GNBDUFunction=10\")]", - paginationDTO3)); - - Object result = underTest.getEntitiesByDomain("OAM_TO_RAN", "/id", "", PaginationDTO.builder().offset(0).limit(500) - .build()); - Assertions.assertEquals(10, ((Map) ((List) ((HashMap) result).get("items")).get(0)).size()); - Assertions.assertTrue(((Map) ((List) ((HashMap) result).get("items")).get(0)).containsKey( - "o-ran-smo-teiv-oam:ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt")); - - Assertions.assertTrue(((Map) ((List) ((HashMap) result).get("items")).get(0)).containsKey( - "o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn")); - } - - @Test - void testAvailableClassifiers() { - Assertions.assertEquals(Set.of("gnbdu-function-model:Rural", "gnbcucp-gnbcuup-model:Weekend"), underTest - .loadClassifiers()); - } - - @Test - void testAvailableDecorators() { - Assertions.assertEquals(Map.of("gnbdu-function-model:location", DataType.PRIMITIVE, - "gnbcucp-gnbcuup-model:metadata", DataType.CONTAINER), underTest.loadDecorators()); - } - - @Test - void testGetSchemasByDomain() { - Set> expected = new HashSet<>(); - for (StoredSchema schema : getSchemasList()) { - if (schema.getDomain() == null || !schema.getDomain().equals("RAN_OAM_TO_CLOUD")) { - continue; - } - Map exp = new HashMap<>(); - exp.put("domain", Collections.singletonList(schema.getDomain())); - exp.put("name", schema.getName()); - exp.put("revision", schema.getRevision()); - exp.put("content", Collections.singletonMap("href", "/schemas/" + schema.getName() + "/content")); - expected.add(exp); - } - - Assertions.assertEquals(expected, new HashSet<>((List) underTest.getSchemas("RAN_OAM_TO_CLOUD", PaginationDTO - .builder().offset(0).limit(15).build()).get("items"))); - } - - @Test - void testGetSchemasWithPartialDomain() { - Set> expected = new HashSet<>(); - for (StoredSchema schema : getSchemasList()) { - if (schema.getDomain() == null || !schema.getDomain().matches("RAN_.*O.*")) { - continue; - } - Map exp = new HashMap<>(); - exp.put("domain", Collections.singletonList(schema.getDomain())); - exp.put("name", schema.getName()); - exp.put("revision", schema.getRevision()); - exp.put("content", Collections.singletonMap("href", "/schemas/" + schema.getName() + "/content")); - expected.add(exp); - } - - Assertions.assertEquals(expected, new HashSet<>((List) underTest.getSchemas("RAN_.*O.*", PaginationDTO.builder() - .offset(0).limit(15).build()).get("items"))); - } - - @Test - void testGetSchema() { - StoredSchema expected = null; - for (StoredSchema schema : getSchemasList()) { - if (schema.getName().equals("o-ran-smo-teiv-oam")) { - expected = schema; - break; - } - } - - StoredSchema actual = underTest.getSchema("o-ran-smo-teiv-oam"); - Assertions.assertTrue(actual.getContent().contains("o-ran-smo-teiv-oam")); - - actual.setContent("yang model o-ran-smo-teiv-oam {}"); - Assertions.assertEquals(expected, actual); - - Assertions.assertNull(underTest.getSchema("o-ran-smo-teiv-invalid")); - } - - @Test - void testSchemaCRUD() { - Assertions.assertNull(underTest.getSchema("newSchema")); - - StoredSchema expected = new StoredSchema(); - expected.setName("newSchema"); - expected.setNamespace("new-namespace"); - expected.setDomain("NEW_DOMAIN"); - expected.setIncludedModules(new ArrayList<>()); - expected.setContent("yang content {} \n\n \t\t\t;"); - expected.setOwnerAppId("additional"); - expected.setStatus("IN_USAGE"); - - underTest.postSchema("newSchema", "new-namespace", "NEW_DOMAIN", new ArrayList<>(), "yang content {} \n\n \t\t\t;", - "additional"); - - Assertions.assertEquals(expected, underTest.getSchema("newSchema")); - - underTest.setSchemaToDeleting("newSchema"); - - expected.setStatus("DELETING"); - Assertions.assertEquals(expected, underTest.getSchema("newSchema")); - - underTest.deleteSchema("newSchema"); - - Assertions.assertNull(underTest.getSchema("newSchema")); - } - - private List getSchemasList() { - final List schemas = new ArrayList<>(); - - StoredSchema ranLogicalToCloud = new StoredSchema(); - ranLogicalToCloud.setName("o-ran-smo-teiv-cloud-to-ran"); - ranLogicalToCloud.setNamespace("urn:o-ran:smo-teiv-cloud-to-ran"); - ranLogicalToCloud.setDomain("CLOUD_TO_RAN"); - ranLogicalToCloud.setRevision("2023-10-24"); - - StoredSchema ranEquipment = new StoredSchema(); - ranEquipment.setName("o-ran-smo-teiv-equipment"); - ranEquipment.setNamespace("urn:o-ran:smo-teiv-equipment"); - ranEquipment.setDomain("EQUIPMENT"); - ranEquipment.setRevision("2023-06-26"); - - StoredSchema ranOamToCloud = new StoredSchema(); - ranOamToCloud.setName("o-ran-smo-teiv-oam-to-cloud"); - ranOamToCloud.setNamespace("urn:o-ran:smo-teiv-oam-to-cloud"); - ranOamToCloud.setDomain("OAM_TO_CLOUD"); - ranOamToCloud.setRevision("2023-10-24"); - - StoredSchema ranOamToLogical = new StoredSchema(); - ranOamToLogical.setName("o-ran-smo-teiv-oam-to-ran"); - ranOamToLogical.setNamespace("urn:o-ran:smo-teiv-oam-to-ran"); - ranOamToLogical.setDomain("OAM_TO_RAN"); - ranOamToLogical.setRevision("2023-10-24"); - - StoredSchema ranCloud = new StoredSchema(); - ranCloud.setName("o-ran-smo-teiv-cloud"); - ranCloud.setNamespace("urn:o-ran:smo-teiv-cloud"); - ranCloud.setDomain("CLOUD"); - ranCloud.setRevision("2023-06-26"); - - StoredSchema ranOam = new StoredSchema(); - ranOam.setName("o-ran-smo-teiv-oam"); - ranOam.setNamespace("urn:o-ran:smo-teiv-oam"); - ranOam.setDomain("OAM"); - ranOam.setRevision("2024-05-02"); - ranOam.setIncludedModules(new ArrayList<>()); - ranOam.setOwnerAppId("BUILT_IN_MODULE"); - ranOam.setStatus("IN_USAGE"); - ranOam.setContent("yang model o-ran-smo-teiv-oam {}"); - - StoredSchema yangTypes = new StoredSchema(); - yangTypes.setName("o-ran-smo-teiv-common-yang-types"); - yangTypes.setRevision("2023-07-04"); - - StoredSchema ranLogicalToEquipment = new StoredSchema(); - ranLogicalToEquipment.setName("o-ran-smo-teiv-equipment-to-ran"); - ranLogicalToEquipment.setDomain("EQUIPMENT_TO_RAN"); - ranLogicalToEquipment.setRevision("2023-10-24"); - - StoredSchema gnbcucpGnbcuupModel = new StoredSchema(); - gnbcucpGnbcuupModel.setName("gnbcucp-gnbcuup-model"); - - StoredSchema yangExtensions = new StoredSchema(); - yangExtensions.setName("o-ran-smo-teiv-common-yang-extensions"); - yangExtensions.setRevision("2023-07-04"); - - StoredSchema ranLogical = new StoredSchema(); - ranLogical.setName("o-ran-smo-teiv-ran"); - ranLogical.setDomain("RAN"); - ranLogical.setRevision("2023-11-03"); - - StoredSchema gnbduFunctionModel = new StoredSchema(); - gnbduFunctionModel.setName("gnbdu-function-model"); - - schemas.add(ranLogicalToCloud); - schemas.add(ranEquipment); - schemas.add(ranOamToCloud); - schemas.add(ranOamToLogical); - schemas.add(ranCloud); - schemas.add(ranOam); - schemas.add(yangTypes); - schemas.add(ranLogicalToEquipment); - schemas.add(gnbcucpGnbcuupModel); - schemas.add(yangExtensions); - schemas.add(ranLogical); - schemas.add(gnbduFunctionModel); - - return schemas; - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImplGETRequestsContainerizedTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImplGETRequestsContainerizedTest.java new file mode 100644 index 0000000..b88ca1c --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/impl/DataRepositoryImplGETRequestsContainerizedTest.java @@ -0,0 +1,180 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.spi.impl; + +import static org.oran.smo.teiv.utils.TiesConstants.MODULE_REFERENCE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_CONSUMER_DATA; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_MODEL; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import javax.sql.DataSource; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.jetbrains.annotations.NotNull; +import org.jooq.DSLContext; +import org.jooq.Record1; +import org.jooq.SQLDialect; +import org.jooq.impl.DSL; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Configuration; + +import org.oran.smo.teiv.db.TestPostgresqlContainer; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.exposure.spi.Module; +import org.oran.smo.teiv.exposure.spi.ModuleStatus; +import org.oran.smo.teiv.exposure.tiespath.refiner.BasePathRefinement; +import org.oran.smo.teiv.schema.PostgresSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; +import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.startup.SchemaHandler; + +@Configuration +@SpringBootTest +class DataRepositoryImplGETRequestsContainerizedTest { + public static TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); + private static DataRepositoryImpl underTest; + private static ModelRepository modelRepository; + private static BasePathRefinement basePathRefinement; + private static DSLContext readWriteDataDslContext; + private static DSLContext readDataDslContext; + private static DSLContext writeDataDslContext; + + @MockBean + private SchemaHandler schemaHandler; + + @BeforeAll + public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { + String url = postgreSQLContainer.getJdbcUrl(); + DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); + readDataDslContext = DSL.using(ds, SQLDialect.POSTGRES); + writeDataDslContext = DSL.using(ds, SQLDialect.POSTGRES); + underTest = new DataRepositoryImpl(basePathRefinement, readDataDslContext); + modelRepository = new ModelRepositoryImpl(readDataDslContext, readWriteDataDslContext, writeDataDslContext); + PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(readDataDslContext, new ObjectMapper()); + postgresSchemaLoader.loadSchemaRegistry(); + TestPostgresqlContainer.loadSampleData(); + } + + @BeforeEach + public void deleteAll() { + writeDataDslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach( + t -> writeDataDslContext.truncate(t).cascade().execute()); + TestPostgresqlContainer.loadSampleData(); + } + + //TODO: Make this test class generic for all repositories + @Test + void testSchemaCRUD() { + final String moduleName = "newSchema"; + Optional schemaByName = modelRepository.getConsumerModuleByName(moduleName); + Assertions.assertFalse(schemaByName.isPresent()); + + Module schema = Module.builder().name(moduleName).namespace("new-namespace").domain("NEW_DOMAIN").content( + "yang content {} \n\n \t\t\t;").ownerAppId("APP").status(ModuleStatus.IN_USAGE).build(); + + modelRepository.createModule(schema); + + schemaByName = modelRepository.getConsumerModuleByName(moduleName); + Assertions.assertTrue(schemaByName.isPresent()); + + modelRepository.doesModuleExists(TIES_MODEL, moduleName); + modelRepository.doesModuleExists(TIES_CONSUMER_DATA, moduleName); + + modelRepository.updateModuleStatus(moduleName, ModuleStatus.DELETING); + + final @NotNull Record1 status = readDataDslContext.select(field("status")).from(table(String.format( + TIES_CONSUMER_DATA, MODULE_REFERENCE))).where(field("name").eq(moduleName)).fetchAny(); + + Assertions.assertEquals(ModuleStatus.DELETING.name(), status.get("status")); + + modelRepository.deleteModuleByName(moduleName); + + schemaByName = modelRepository.getConsumerModuleByName(moduleName); + Assertions.assertFalse(schemaByName.isPresent()); + } + + @Test + void getClassifiersForSchema() { + assertThat(List.of("test-app-module:Indoor", "test-app-module:Outdoor", "test-app-module:Rural", + "test-app-module:Weekday", "test-app-module:Weekend")).hasSameElementsAs(underTest.getClassifiersForSchema( + "test-app-module")); + } + + @Test + void getDecoratorsForSchema() { + assertThat(List.of("test-app-module:textdata", "test-app-module:intdata")).hasSameElementsAs(underTest + .getDecoratorsForSchema("test-app-module")); + } + + @Test + void getRelationshipIdsForDecoratorDeletionTest() { + Assertions.assertEquals(Collections.singletonList( + "urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc="), + underTest.getRelationshipIdsForDecoratorDeletion(SchemaRegistry.getRelationTypeByName( + "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"), Set.of("gnbcucp-gnbcuup-model:metadata"))); + + Assertions.assertEquals(Collections.singletonList( + "urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU="), + underTest.getRelationshipIdsForDecoratorDeletion(SchemaRegistry.getRelationTypeByName( + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"), Set.of("gnbcucp-gnbcuup-model:metadata"))); + } + + @Test + void getRelationshipIdsForClassifierDeletionTest() { + Assertions.assertEquals(Collections.singletonList( + "urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc="), + underTest.getRelationshipIdsForClassifierDeletion(SchemaRegistry.getRelationTypeByName( + "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"), Set.of("gnbcucp-gnbcuup-model:Weekend"))); + + Assertions.assertEquals(Collections.singletonList( + "urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU="), + underTest.getRelationshipIdsForClassifierDeletion(SchemaRegistry.getRelationTypeByName( + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"), Set.of("gnbcucp-gnbcuup-model:Weekend"))); + } + + @Test + void getEntityIdsForDecoratorDeletionTest() { + Assertions.assertEquals(Collections.singletonList("E49D942C16E0364E1E0788138916D70C"), underTest + .getEntityIdsForDecoratorDeletion(SchemaRegistry.getEntityTypeByName("NRSectorCarrier"), Set.of( + "gnbcucp-gnbcuup-model:metadata"))); + } + + @Test + void getEntityIdsForClassifierDeletionTest() { + Assertions.assertEquals(Collections.singletonList("E49D942C16E0364E1E0788138916D70C"), underTest + .getEntityIdsForClassifierDeletion(SchemaRegistry.getEntityTypeByName("NRSectorCarrier"), Set.of( + "gnbcucp-gnbcuup-model:Weekend"))); + } + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapperTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapperTest.java deleted file mode 100644 index 5b63746..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/ComplexMapperTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.MockSchemaLoader; - -import org.jooq.Record; -import org.jooq.Result; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.jooq.impl.DSL.field; - -class ComplexMapperTest { - private static ComplexMapper complexMapper; - - @BeforeAll - static void setUp() throws SchemaLoaderException { - MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); - mockSchemaLoader.loadSchemaRegistry(); - complexMapper = new ComplexMapper(); - } - - @Test - void testMap() { - final Result records = DSL.using(SQLDialect.POSTGRES).newResult(); - - final String gNBDUName = String.format(TIES_DATA, "GNBDUFunction"); - final String nRCellDUName = String.format(TIES_DATA, "NRCellDU"); - - records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field(gNBDUName + ".id"), field(gNBDUName + ".fdn"), field( - nRCellDUName + ".id")).values("9BCD297B8258F67908477D895636ED65", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91", - null)); - records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field(gNBDUName + ".id"), field(gNBDUName + ".fdn"), field( - nRCellDUName + ".id")).values(null, null, "98C3A4591A37718E1330F0294E23B62A")); - - Map result = new HashMap<>(); - - result.put("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of(ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91"), "id", - "9BCD297B8258F67908477D895636ED65"))); - - result.put("o-ran-smo-teiv-ran:NRCellDU", List.of(Map.of("id", "98C3A4591A37718E1330F0294E23B62A"))); - - Assertions.assertEquals(result, complexMapper.map(records)); - } - -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapperTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapperTest.java index 1971be4..7e66074 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapperTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/EntityMapperTest.java @@ -20,11 +20,10 @@ */ package org.oran.smo.teiv.exposure.spi.mapper; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import org.oran.smo.teiv.schema.Module; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; +import static org.jooq.impl.DSL.field; + +import java.util.List; +import java.util.Map; import org.jooq.Record; import org.jooq.Result; @@ -34,44 +33,41 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.jooq.impl.DSL.field; +import org.oran.smo.teiv.api.model.OranTeivEntitiesResponseMessage; +import org.oran.smo.teiv.exposure.utils.RequestDetails; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; class EntityMapperTest { - private static EntityMapper entityMapper; + + EntityMapper entityMapper = new EntityMapper(); @BeforeAll static void setUp() throws SchemaLoaderException { - EntityType entityType = EntityType.builder().name("GNBDUFunction").module(Module.builder().name( - "o-ran-smo-teiv-ran").build()).build(); - entityMapper = new EntityMapper(entityType); - SchemaLoader mockSchemaLoader = new MockSchemaLoader(); + MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); mockSchemaLoader.loadSchemaRegistry(); } @Test void testMap() { - final Result record = DSL.using(SQLDialect.POSTGRES).newResult(); - Map result = new HashMap<>(); - - record.add(DSL.using(SQLDialect.POSTGRES).newRecord(field("dUpLMNId"), field("fdn"), field("gNBDUId"), field( - "gNBId"), field("cmId"), field("gNBIdLength"), field("id"), field("CD_sourceIds")).values(Map.of("mcc", - "456", "mnc", "82"), - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=95", 95, - 95, "null", 2, "5970A12E0AF8B0FBE0B49290FE847F9B", List.of( - "urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=95", - "urn:cmHandle:/395221E080CCF0FD1924103B15873814"))); + final Result records = DSL.using(SQLDialect.POSTGRES).newResult(); + records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field("o-ran-smo-teiv-ran:GNBDUFunction.id"), field( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), field("o-ran-smo-teiv-ran:NRCellDU.id"), field("count")) + .values("9BCD297B8258F67908477D895636ED65", 1, null, null)); + records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field("o-ran-smo-teiv-ran:GNBDUFunction.id"), field( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), field("o-ran-smo-teiv-ran:NRCellDU.id"), field("count")) + .values(null, null, "98C3A4591A37718E1330F0294E23B62A", null)); + records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field("o-ran-smo-teiv-ran:GNBDUFunction.id"), field( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), field("o-ran-smo-teiv-ran:NRCellDU.id"), field("count")) + .values(null, null, null, 2)); - result.put("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of(ATTRIBUTES, Map.of("dUpLMNId", Map.of("mcc", "456", - "mnc", "82"), "fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=95", "gNBDUId", - 95, "gNBId", 95, "cmId", "null", "gNBIdLength", 2), "id", "5970A12E0AF8B0FBE0B49290FE847F9B", "sourceIds", - List.of("urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=95", - "urn:cmHandle:/395221E080CCF0FD1924103B15873814")))); + OranTeivEntitiesResponseMessage result = entityMapper.mapEntities(records, RequestDetails.builder().basePath( + "/test").offset(0).limit(100).build()); - Assertions.assertEquals(result, entityMapper.map(record)); + Assertions.assertEquals(2, result.getTotalCount()); + Assertions.assertEquals(List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", + "9BCD297B8258F67908477D895636ED65", "attributes", Map.of("gNBId", 1)))), Map.of( + "o-ran-smo-teiv-ran:NRCellDU", List.of(Map.of("id", "98C3A4591A37718E1330F0294E23B62A")))), result + .getItems()); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtilityTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtilityTest.java deleted file mode 100644 index 26b908b..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/MapperUtilityTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.oran.smo.teiv.utils.TiesConstants.ATTRIBUTES; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.jooq.impl.DSL.field; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.jooq.Record; -import org.jooq.Result; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.oran.smo.teiv.utils.exposure.PaginationVerifierTestUtil.verifyResponse; -import static org.jooq.impl.DSL.field; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.schema.MockSchemaLoader; - -class MapperUtilityTest { - private MapperUtility underTest; - private static PaginationMetaData paginationMetaData; - - @BeforeEach - void setUp() throws SchemaLoaderException { - underTest = new MapperUtility(); - SchemaLoader mockSchemaLoader = new MockSchemaLoader(); - mockSchemaLoader.loadSchemaRegistry(); - paginationMetaData = new PaginationMetaData(); - } - - @Test - void testMapEntity() { - final Result result = DSL.using(SQLDialect.POSTGRES).newResult(); - result.add(DSL.using(SQLDialect.POSTGRES).newRecord(field("gNBDUId"), field("fdn"), field("dUpLMNId"), field( - "gNBId"), field("id"), field("gNBIdLength")).values(null, "GNBDUFunction/6653097A7B47B082BA96245354BB5BE7", - Map.of("mcc", 456, "mnc", 82), "6653097A7B47B082BA96245354BB5BE7", - "GNBDUFunction:6653097A7B47B082BA96245354BB5BE7", 2)); - Assertions.assertEquals(generateResponse("GNBDUFunction", "6653097A7B47B082BA96245354BB5BE7"), underTest.mapEntity( - SchemaRegistry.getEntityTypeByName("GNBDUFunction"), result)); - } - - @Test - void testMapAllRelationships() { - final Result result = DSL.using(SQLDialect.POSTGRES).newResult(); - result.add(DSL.using(SQLDialect.POSTGRES).newRecord(field( - "ties_data.\"NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( - "ties_data.\"NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( - "ties_data.\"NRCellDU\".\"id\""), field( - "ties_data.\"NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"")) - .values("urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", Collections.EMPTY_LIST)); - - Assertions.assertEquals(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", - "urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.EMPTY_LIST))), underTest.mapRelationships(result, SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTION_PROVIDES_NRCELLDU"))); - } - - @Test - void testMapRelationship() { - final Record record = DSL.using(SQLDialect.POSTGRES).newRecord(field( - "ties_data.\"NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( - "ties_data.\"NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( - "ties_data.\"NRCellDU\".\"id\""), field( - "ties_data.\"NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"")) - .values("urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", Collections.EMPTY_LIST); - - final Result result = DSL.using(SQLDialect.POSTGRES).newResult(); - result.add(record); - - Assertions.assertEquals(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", - "urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - Collections.EMPTY_LIST))), underTest.mapRelationship(result, SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTION_PROVIDES_NRCELLDU"))); - } - - @Test - void testMapComplexQuery() { - final Result records = DSL.using(SQLDialect.POSTGRES).newResult(); - - final String gNBDUName = String.format(TIES_DATA, "GNBDUFunction"); - final String nRCellDUName = String.format(TIES_DATA, "NRCellDU"); - - records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field(gNBDUName + ".id"), field(gNBDUName + ".fdn"), field( - nRCellDUName + ".id")).values("9BCD297B8258F67908477D895636ED65", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91", - null)); - records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field(gNBDUName + ".id"), field(gNBDUName + ".fdn"), field( - nRCellDUName + ".id")).values(null, null, "98C3A4591A37718E1330F0294E23B62A")); - - Map result = new HashMap<>(); - - result.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of(ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91"), "id", - "9BCD297B8258F67908477D895636ED65")), "o-ran-smo-teiv-ran:NRCellDU", List.of(Map.of("id", - "98C3A4591A37718E1330F0294E23B62A"))))); - - try (MockedStatic requestContextHolderMockedStatic = Mockito.mockStatic( - RequestContextHolder.class)) { - requestContextHolderMockedStatic.when(RequestContextHolder::currentRequestAttributes).thenReturn( - new ServletRequestAttributes(new MockHttpServletRequest())); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/pathTo/endPoint").offset(0).limit(5).build(); - paginationDTO.setTotalSize(2); - result.putAll(paginationMetaData.getObjectList(paginationDTO)); - verifyResponse(result, underTest.mapComplexQuery(records, paginationDTO)); - } - } - - @Test - void testMapComplexQuery_SingleEntity() { - final Result records = DSL.using(SQLDialect.POSTGRES).newResult(); - - final String gNBDUName = String.format(TIES_DATA, "GNBDUFunction"); - - records.add(DSL.using(SQLDialect.POSTGRES).newRecord(field(gNBDUName + ".id"), field(gNBDUName + ".fdn")).values( - "9BCD297B8258F67908477D895636ED65", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91")); - - Map reference = new HashMap<>(); - - reference.put("items", List.of(Map.of("o-ran-smo-teiv-ran:GNBDUFunction", List.of(Map.of("id", - "9BCD297B8258F67908477D895636ED65", ATTRIBUTES, Map.of("fdn", - "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=91")))))); - - try (MockedStatic requestContextHolderMockedStatic = Mockito.mockStatic( - RequestContextHolder.class)) { - requestContextHolderMockedStatic.when(RequestContextHolder::currentRequestAttributes).thenReturn( - new ServletRequestAttributes(new MockHttpServletRequest())); - PageMetaData pageMetaDataSelf = new PageMetaData(PaginationDTO.builder().offset(0).limit(5).build()); - reference.put("self", pageMetaDataSelf); - PaginationMetaData pmd = new PaginationMetaData(); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/pathTo/endPoint").offset(0).limit(5).build(); - paginationDTO.setTotalSize(0); - reference.putAll(pmd.getObjectList(paginationDTO)); - verifyResponse(reference, underTest.mapComplexQuery(records, paginationDTO)); - - } - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaDataTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaDataTest.java deleted file mode 100644 index 3dccacc..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/PaginationMetaDataTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import java.util.HashMap; -import java.util.Map; - -import static org.oran.smo.teiv.utils.exposure.PaginationVerifierTestUtil.verifyResponse; - -public class PaginationMetaDataTest { - - @Test - void testIsItFirst() { - - Map result = new HashMap<>(); - try (MockedStatic requestContextHolderMockedStatic = Mockito.mockStatic( - RequestContextHolder.class)) { - requestContextHolderMockedStatic.when(RequestContextHolder::currentRequestAttributes).thenReturn( - new ServletRequestAttributes(new MockHttpServletRequest())); - - PaginationMetaData paginationMetaData1 = new PaginationMetaData(); - PageMetaData pageMetaDataSelf = new PageMetaData(0, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataNext = new PageMetaData(5, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataLast = new PageMetaData(50, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataPrev = new PageMetaData(0, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataFirst = new PageMetaData(0, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - - result.put("self", pageMetaDataSelf); - result.put("first", pageMetaDataFirst); - result.put("prev", pageMetaDataPrev); - result.put("next", pageMetaDataNext); - result.put("last", pageMetaDataLast); - - final PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/pathTo/endPoint").offset(0).limit(5) - .build(); - paginationDTO.setTotalSize(55); - verifyResponse(result, paginationMetaData1.getObjectList(paginationDTO)); - } - } - - @Test - void testIsItLast() { - - Map result = new HashMap<>(); - try (MockedStatic requestContextHolderMockedStatic = Mockito.mockStatic( - RequestContextHolder.class)) { - requestContextHolderMockedStatic.when(RequestContextHolder::currentRequestAttributes).thenReturn( - new ServletRequestAttributes(new MockHttpServletRequest())); - - PaginationMetaData paginationMetaData1 = new PaginationMetaData(); - PageMetaData pageMetaDataSelf = new PageMetaData(60, 10, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataNext = new PageMetaData(60, 10, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataLast = new PageMetaData(60, 10, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataPrev = new PageMetaData(50, 10, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataFirst = new PageMetaData(0, 10, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - - result.put("self", pageMetaDataSelf); - result.put("next", pageMetaDataNext); - result.put("last", pageMetaDataLast); - result.put("prev", pageMetaDataPrev); - result.put("first", pageMetaDataFirst); - - final PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/pathTo/endPoint").offset(60).limit(10) - .build(); - paginationDTO.setTotalSize(70); - verifyResponse(result, paginationMetaData1.getObjectList(paginationDTO)); - } - } - - @Test - void testMiddleTable() { - - Map result = new HashMap<>(); - try (MockedStatic requestContextHolderMockedStatic = Mockito.mockStatic( - RequestContextHolder.class)) { - requestContextHolderMockedStatic.when(RequestContextHolder::currentRequestAttributes).thenReturn( - new ServletRequestAttributes(new MockHttpServletRequest())); - - PaginationMetaData paginationMetaData1 = new PaginationMetaData(); - PageMetaData pageMetaDataSelf = new PageMetaData(10, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataPrev = new PageMetaData(5, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataNext = new PageMetaData(15, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataFirst = new PageMetaData(0, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - PageMetaData pageMetaDataLast = new PageMetaData(65, 5, PaginationDTO.builder().basePath("/pathTo/endPoint") - .build()); - - result.put("self", pageMetaDataSelf); - result.put("prev", pageMetaDataPrev); - result.put("next", pageMetaDataNext); - result.put("first", pageMetaDataFirst); - result.put("last", pageMetaDataLast); - - final PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/pathTo/endPoint").offset(10).limit(5) - .build(); - paginationDTO.setTotalSize(70); - verifyResponse(result, paginationMetaData1.getObjectList(paginationDTO)); - } - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapperTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapperTest.java index e8424f3..9e1ea94 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapperTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipMapperTest.java @@ -20,27 +20,25 @@ */ package org.oran.smo.teiv.exposure.spi.mapper; -import org.oran.smo.teiv.schema.Association; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.Module; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.MockSchemaLoader; import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; +import static org.jooq.impl.DSL.field; + +import java.util.List; +import java.util.Map; import org.jooq.Record; -import org.jooq.Result; import org.jooq.SQLDialect; import org.jooq.impl.DSL; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Map; - -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.jooq.impl.DSL.field; +import org.oran.smo.teiv.exposure.spi.Module; +import org.oran.smo.teiv.schema.Association; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.SchemaLoaderException; class RelationshipMapperTest { private static RelationshipMapper relationshipMapper; @@ -53,35 +51,19 @@ class RelationshipMapperTest { relationType = RelationType.builder().name("GNBDUFUNCTION_PROVIDES_NRCELLDU").aSideAssociation(Association.builder() .name("provided-nrCellDu").build()).aSide(EntityType.builder().name("GNBDUFUNCTION").build()) .bSideAssociation(Association.builder().name("provided-by-gnbduFunction").build()).bSide(EntityType - .builder().name("NRCellDU").build()).relationshipStorageLocation(B_SIDE).module(Module.builder() - .name("o-ran-smo-teiv-ran").build()).build(); - relationshipMapper = new RelationshipMapper(relationType); - } - - @Test - void testMap() { - final Result record = DSL.using(SQLDialect.POSTGRES).newResult(); - record.add(DSL.using(SQLDialect.POSTGRES).newRecord(field( - "ties_data.\"NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( - "ties_data.\"NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( - "ties_data.\"NRCellDU\".\"id\""), field( - "ties_data.\"NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"")) - .values("urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", List.of("sid1", "sid2"))); - - Assertions.assertEquals(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", - "urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - List.of("sid1", "sid2")))), relationshipMapper.map(record)); + .builder().name("NRCellDU").build()).relationshipStorageLocation(B_SIDE).tableName( + "o-ran-smo-teiv-ran_NRCellDU").module(Module.builder().name("o-ran-smo-teiv-ran").build()) + .build(); + relationshipMapper = new RelationshipMapper(); } @Test void testCreateProperties() { Record record = DSL.using(SQLDialect.POSTGRES).newRecord(field( - "ties_data.\"NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( - "ties_data.\"NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( - "ties_data.\"NRCellDU\".\"id\""), field( - "ties_data.\"NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"")) + "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( + "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( + "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"id\""), field( + "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"")) .values("urn:base64:R05CRFVGdW5jdGlvbjo2QTBENUFBMjhGNzcwQzk5NDFCNzRFQkU1NzYxMUFFMTpQUk9WSURFUzpOUkNlbGxEVTowMDAxNjFCMDE0QzMyMDEwNkE5RDZCMTQxN0Y4RUIwQQ==", "6A0D5AA28F770C9941B74EBE57611AE1", "000161B014C320106A9D6B1417F8EB0A", List.of("sid1", "sid2")); diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapperTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapperTest.java deleted file mode 100644 index f13100a..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/spi/mapper/RelationshipsMapperTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.exposure.spi.mapper; - -import org.oran.smo.teiv.schema.Association; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.Module; -import org.oran.smo.teiv.schema.RelationType; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; - -import org.jooq.Record; -import org.jooq.Result; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.Map; - -import static org.oran.smo.teiv.utils.ResponseGenerator.generateResponse; -import static org.jooq.impl.DSL.field; - -class RelationshipsMapperTest { - private static RelationshipsMapper relationshipsMapper; - - @BeforeAll - static void setUp() throws SchemaLoaderException { - MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); - mockSchemaLoader.loadSchemaRegistry(); - RelationType relationType = RelationType.builder().name("GNBDUFUNCTION_PROVIDES_NRCELLDU").aSideAssociation( - Association.builder().name("provided-nrCellDu").build()).aSide(EntityType.builder().name("GNBDUFUNCTION") - .build()).bSideAssociation(Association.builder().name("provided-by-gnbduFunction").build()).bSide( - EntityType.builder().name("NRCellDU").build()).relationshipStorageLocation(B_SIDE).module( - Module.builder().name("o-ran-smo-teiv-ran").build()).build(); - relationshipsMapper = new RelationshipsMapper(relationType); - } - - @Test - void testMap() { - final Result record = DSL.using(SQLDialect.POSTGRES).newResult(); - record.add(DSL.using(SQLDialect.POSTGRES).newRecord(field( - "ties_data.\"NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\""), field( - "ties_data.\"NRCellDU\".\"REL_FK_provided-by-gnbduFunction\""), field( - "ties_data.\"NRCellDU\".\"id\"")).values( - "urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg==", - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F")); - - Assertions.assertEquals(Map.of("o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU", List.of(generateResponse( - "9BCD297B8258F67908477D895636ED65", "B480427E8A0C0B8D994E437784BB382F", - "urn:base64:R05CRFVGdW5jdGlvbjo5QkNEMjk3QjgyNThGNjc5MDg0NzdEODk1NjM2RUQ2NTpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg=="))), - relationshipsMapper.map(record)); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/DtoToJooqTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/DtoToJooqTest.java new file mode 100644 index 0000000..456d244 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/DtoToJooqTest.java @@ -0,0 +1,1214 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.innerlanguage; + +import static org.oran.smo.teiv.utils.TiesConstants.ITEM; +import static org.jooq.impl.DSL.condition; +import static org.jooq.impl.DSL.field; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import org.oran.smo.teiv.utils.query.exception.TiesPathException; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jooq.Condition; +import org.jooq.Field; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.schema.DataType; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; + +class DtoToJooqTest { + + private static final String GNBCUCP_FUNCTION = "GNBCUCPFunction"; + private static final String GNBDU_FUNCTION = "GNBDUFunction"; + private static final String ANTENNA_CAPABILITY = "AntennaCapability"; + private static final String ANTENNA_MODULE = "AntennaModule"; + private static final String MANAGED_ELEMENT = "ManagedElement"; + private static final String NR_CELL_DU = "NRCellDU"; + + @BeforeAll + static void setUp() throws SchemaLoaderException { + MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); + mockSchemaLoader.loadSchemaRegistry(); + } + + @Test + void testConditions_relationIsNotNull() { + ScopeObject scopeObject1 = ScopeObject.builder(MANAGED_ELEMENT).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.RELATION).innerContainer(List.of("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION")) + .queryFunction(QueryFunction.NOT_NULL).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.RELATION).innerContainer(List.of("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION")) + .queryFunction(QueryFunction.NOT_NULL).build(); + + LogicalBlock lb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock lb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock olb1 = new OrLogicalBlock(); + olb1.setChildren(List.of(lb1, lb2)); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION\" is not null\n" + + " or ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION\" is not null\n") + .toString(), olb1.getCondition().toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_primitive() { + ScopeObject scopeObject1 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("nRPCI").queryFunction(QueryFunction.EQ).parameter("ABC789").dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("nRPCI").queryFunction(QueryFunction.CONTAINS).parameter("ABC789").dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject3 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("nRPCI").queryFunction(QueryFunction.NOT_NULL).dataType(DataType.PRIMITIVE) + .build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + AndOrLogicalBlock alb2 = new OrLogicalBlock(); + alb2.setChildren(List.of(alb1, slb3)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"nRPCI\" = 'ABC789'\n" + + " or ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"nRPCI\" like (('%' || replace(\n" + + " replace(\n" + + " replace('ABC789', '!', '!!'),\n" + + " '%',\n" + + " '!%'\n" + + " ),\n" + + " '_',\n" + + " '!_'\n" + + " )) || '%') escape '!'\n" + + " or ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"nRPCI\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_bigint() { + ScopeObject scopeObject1 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("1").dataType( + DataType.BIGINT).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("2").dataType( + DataType.BIGINT).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb1.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"gNBId\" = 1\n" + + " or ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"gNBId\" = 2\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_decimal() { + ScopeObject scopeObject1 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("decimalColumn").queryFunction(QueryFunction.EQ).parameter("2.5").dataType( + DataType.DECIMAL).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("decimalColumn").queryFunction(QueryFunction.EQ).parameter("15.25").dataType( + DataType.DECIMAL).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb1.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"decimalColumn\" = 2.5\n" + + " or ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"decimalColumn\" = 15.25\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_geography() { + ScopeObject valid1 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "point(39.4019881 67.9419888)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject valid2 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881 67.9419888)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidContains = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.CONTAINS).parameter( + "POINT(39.4019881 67.9419888)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidCoordinate0 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881 67.9419888 123.9878)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidCoordinate1 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidCoordinate2 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881 INVALID)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidCoordinate3 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881 67.9419888 123.9878)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidFormat1 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "(39.4019881 67.9419888)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidFormat2 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT39.4019881 67.9419888)").dataType(DataType.GEOGRAPHIC).build(); + + ScopeObject invalidFormat3 = ScopeObject.builder("AntennaModule").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("geoColumn").queryFunction(QueryFunction.EQ).parameter( + "POINT(39.4019881 67.9419888").dataType(DataType.GEOGRAPHIC).build(); + + // spotless:off + assertEquals(condition("ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"geoColumn\" = st_geomfromtext('point(39.4019881 67.9419888)')") + .toString(), new ScopeLogicalBlock(valid1).getCondition().toString()); + assertEquals(condition("ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"geoColumn\" = st_geomfromtext('POINT(39.4019881 67.9419888)')") + .toString(), new ScopeLogicalBlock(valid2).getCondition().toString()); + + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidContains)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidCoordinate0)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidCoordinate1)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidCoordinate2)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidCoordinate3)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidFormat1)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidFormat2)::getCondition); + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidFormat3)::getCondition); + // spotless:on + } + + @Test + void testConditions_entityAttributes_containerObject() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId")).leaf("mnc").queryFunction( + QueryFunction.EQ).parameter("789").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId")).leaf("mcc").queryFunction( + QueryFunction.CONTAINS).parameter("456").dataType(DataType.PRIMITIVE).build(); + + ScopeObject invalidQueryFunction = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId")).leaf("mcc").queryFunction( + QueryFunction.NOT_NULL).parameter("456").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb1.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"dUpLMNId\" -> 'mnc' = '\"789\"'\n" + + " or ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"dUpLMNId\" ->> 'mcc' like '%456%'\n") + .toString(), actualCondition.toString()); + + assertThrows(TiesPathException.class, new ScopeLogicalBlock(invalidQueryFunction)::getCondition); + // spotless:on + } + + @Test + void testConditions_entityAttributes_containerObject_multipleElements() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId", "mcc")).leaf("mcca").queryFunction( + QueryFunction.EQ).parameter("789").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject11 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId", "mcc")).leaf("mccb").queryFunction( + QueryFunction.EQ).parameter("789").dataType(DataType.INTEGER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("dUpLMNId", "mcc")).leaf("mcca").queryFunction( + QueryFunction.CONTAINS).parameter("789").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb11 = new ScopeLogicalBlock(scopeObject11); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb11)); + + AndOrLogicalBlock alb2 = new OrLogicalBlock(); + alb2.setChildren(List.of(alb1, slb2)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"dUpLMNId\" -> 'mcc' -> 'mcca' = '\"789\"'\n" + + " or ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"dUpLMNId\" -> 'mcc' -> 'mccb' = '789'\n" + + " or ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"dUpLMNId\" -> 'mcc' ->> 'mcca' like '%789%'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_containerArray() { + ScopeObject scopeObject1 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("eUtranFqBands")).leaf(ITEM).queryFunction( + QueryFunction.EQ).parameter("789").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject11 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("eUtranFqBands")).leaf(ITEM).queryFunction( + QueryFunction.EQ).parameter("789").dataType(DataType.INTEGER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("eUtranFqBands")).leaf(ITEM).queryFunction( + QueryFunction.CONTAINS).parameter("456").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb11 = new ScopeLogicalBlock(scopeObject11); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb11)); + + AndOrLogicalBlock alb2 = new OrLogicalBlock(); + alb2.setChildren(List.of(alb1, slb2)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"eUtranFqBands\" @> '\"789\"')\n" + + " or (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"eUtranFqBands\" @> '789')\n" + + " or (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"eUtranFqBands\"::text like '%456%')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes_containerArray_multipleLevels() { + ScopeObject scopeObject1 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("jsonbColumn", "levelOneField", + "levelTwoField")).leaf(ITEM).queryFunction(QueryFunction.EQ).parameter("456").dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("jsonbColumn", "levelOneField", + "levelTwoField")).leaf(ITEM).queryFunction(QueryFunction.EQ).parameter("456").dataType( + DataType.INTEGER).build(); + + ScopeObject scopeObject3 = ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).innerContainer(List.of("jsonbColumn", "levelOneField", + "levelTwoField")).leaf(ITEM).queryFunction(QueryFunction.CONTAINS).parameter("456").dataType( + DataType.INTEGER).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + AndOrLogicalBlock alb1 = new OrLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + AndOrLogicalBlock alb2 = new OrLogicalBlock(); + alb2.setChildren(List.of(alb1, slb3)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"jsonbColumn\" -> 'levelOneField' -> 'levelTwoField' @> '\"456\"')\n" + + " or (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"jsonbColumn\" -> 'levelOneField' -> 'levelTwoField' @> '456')\n" + + " or (ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"jsonbColumn\" -> 'levelOneField' ->> 'levelTwoField'::text like '%456%')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAttributes() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("1").dataType( + DataType.BIGINT).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ATTRIBUTES).leaf("decimalId").queryFunction(QueryFunction.EQ).parameter("2.5") + .dataType(DataType.DECIMAL).build(); + + ScopeObject scopeObject3 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).leaf("nRPCI").queryFunction(QueryFunction.CONTAINS).parameter("ABC789").dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject4 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ATTRIBUTES).innerContainer(List.of("pLMNId")).leaf("mnc").queryFunction(QueryFunction.EQ) + .parameter("789").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + LogicalBlock slb4 = new ScopeLogicalBlock(scopeObject4); + + AndOrLogicalBlock alb1 = new AndLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + AndOrLogicalBlock alb2 = new AndLogicalBlock(); + alb2.setChildren(List.of(slb3, slb4)); + + AndOrLogicalBlock alb3 = new AndLogicalBlock(); + alb3.setChildren(List.of(alb1, alb2)); + + Condition actualCondition = alb3.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"gNBId\" = 1\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"decimalId\" = 2.5\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"nRPCI\" like (('%' || replace(\n" + + " replace(\n" + + " replace('ABC789', '!', '!!'),\n" + + " '%',\n" + + " '!%'\n" + + " ),\n" + + " '_',\n" + + " '!_'\n" + + " )) || '%') escape '!'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"pLMNId\" -> 'mnc' = '\"789\"'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationshipAttributes() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ATTRIBUTES).leaf("rel_column1").queryFunction( + QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ATTRIBUTES).leaf("rel_column2").queryFunction( + QueryFunction.EQ).parameter("ABC789").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"rel_column1\" = 1\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"rel_column2\" = 'ABC789'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_undefinedAttributes_throws() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.UNDEFINED).container(ContainerType.ATTRIBUTES).leaf("rel_column1").queryFunction( + QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + + assertThrows(TiesPathException.class, slb1::getCondition); + } + + @Test + void testConditions_relation() { + ScopeObject scopeObject1 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRCELLDU")).queryFunction( + QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEV").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("NRSectorCarrier").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER")) + .queryFunction(QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEW").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject3 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER")).leaf( + "id").queryFunction(QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEZ").dataType( + DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + AndOrLogicalBlock alb1 = new AndLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + + AndOrLogicalBlock alb2 = new AndLogicalBlock(); + alb2.setChildren(List.of(alb1, slb3)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\" = 'urn:base64:TWFuYWdlZEV'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" = 'urn:base64:TWFuYWdlZEW'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" = 'urn:base64:TWFuYWdlZEZ'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relation_throws() { + ScopeObject scopeObject1 = ScopeObject.builder("NOT_ENTITY").topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRCELLDU")).leaf("id") + .queryFunction(QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEZ").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("NOT_RELATION").topologyObjectType(TopologyObjectType.RELATION) + .container(ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRCELLDU")).leaf("id") + .queryFunction(QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEZ").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject3 = ScopeObject.builder("NOT_RELATION").topologyObjectType(TopologyObjectType.RELATION) + .container(ContainerType.RELATION).innerContainer(List.of("GNBDUFUNCTION_PROVIDES_NRCELLDU")).leaf("id") + .queryFunction(QueryFunction.CONTAINS).parameter("urn:base64:TWFuYWdlZEZ").dataType(DataType.PRIMITIVE) + .build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + assertThrows(TiesPathException.class, slb1::getCondition); + assertThrows(TiesPathException.class, slb2::getCondition); + assertThrows(TiesPathException.class, slb3::getCondition); + } + + @Test + void testConditions_entityId() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.ID).queryFunction(QueryFunction.EQ).parameter("ABC123").dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(NR_CELL_DU).topologyObjectType(TopologyObjectType.ENTITY).container( + ContainerType.ID).queryFunction(QueryFunction.CONTAINS).parameter("DEF456").dataType(DataType.PRIMITIVE) + .build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" = 'ABC123'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"id\" like (('%' || replace(\n" + + " replace(\n" + + " replace('DEF456', '!', '!!'),\n" + + " '%',\n" + + " '!%'\n" + + " ),\n" + + " '_',\n" + + " '!_'\n" + + " )) || '%') escape '!'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationId() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ID).queryFunction(QueryFunction.EQ).parameter( + "urn:base64:TWFuYWdlZEV").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ID).queryFunction(QueryFunction.CONTAINS).parameter( + "urn:base64:TWFuYWdlZEW").dataType(DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\" = 'urn:base64:TWFuYWdlZEV'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" like (('%' || replace(\n" + + " replace(\n" + + " replace('urn:base64:TWFuYWdlZEW', '!', '!!'),\n" + + " '%',\n" + + " '!%'\n" + + " ),\n" + + " '_',\n" + + " '!_'\n" + + " )) || '%') escape '!'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationIdIsNotNull() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ID).queryFunction(QueryFunction.NOT_NULL).dataType( + DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.ID).queryFunction(QueryFunction.NOT_NULL).dataType( + DataType.PRIMITIVE).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU\" is not null\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_idThrows() { + ScopeLogicalBlock undefinedTOType = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU") + .topologyObjectType(TopologyObjectType.UNDEFINED).container(ContainerType.ID).queryFunction( + QueryFunction.EQ).parameter("urn:base64:TWFuYWdlZEV").dataType(DataType.PRIMITIVE).build()); + + ScopeLogicalBlock invalidTopologyObjectType = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction") + .topologyObjectType(TopologyObjectType.UNDEFINED).container(ContainerType.ID).queryFunction( + QueryFunction.NOT_NULL).parameter("urn:base64:TWFuYWdlZEV").dataType(DataType.PRIMITIVE).build()); + + assertThrows(TiesPathException.class, undefinedTOType::getCondition); + assertThrows(TiesPathException.class, invalidTopologyObjectType::getCondition); + } + + @Test + void testConditions_entityAssociation_oneToMany1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ENodeBFunction").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_ENodeBFunction\".\"REL_FK_managed-by-managedElement\" = 'me1'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_FK_managed-by-managedElement\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_oneToMany2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder(MANAGED_ELEMENT).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-gnbduFunction")).leaf("id").queryFunction(QueryFunction.EQ).parameter("gnbdu1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder(MANAGED_ELEMENT).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-gnbcucpFunction")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_FK_managed-by-managedElement\" is not null\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" = 'gnbdu1'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBCUCPFunction\".\"REL_FK_managed-by-managedElement\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToOne1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_MODULE).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of("installed-at-site")) + .leaf("id").queryFunction(QueryFunction.EQ).parameter("site1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_MODULE).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of("installed-at-site")) + .leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null).build()); + + AndOrLogicalBlock alb = new OrLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" = 'site1'\n" + + " or ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToOne2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("Site").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "installed-antennaModule")).leaf("id").queryFunction(QueryFunction.EQ).parameter("am1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("Site").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "installed-antennaModule")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new OrLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (\n" + + " ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n" + + " and ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"id\" = 'am1'\n" + + " )\n" + + " or ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToOne1Contains() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("Site").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "installed-antennaModule")).leaf("id").queryFunction(QueryFunction.CONTAINS).parameter("am1") + .build()); + + Condition actualCondition = scopeObject1.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + "ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n" + + "and ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"id\" like (" + + "('%' || replace(" + "\n"+ + "replace(" + "\n"+ + "replace('am1', '!', '!!')," + "\n"+ + "'%'," + "\n"+ + "'!%'" + "\n"+ + ")," + "\n"+ + "'_'," + "\n"+ + "'!_'" + "\n"+ + ")) || '%') escape '!'" + "\n") + .toString().replace(" ", ""), actualCondition.toString().replace(" ", "")); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToMany1Contains() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_MODULE).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serviced-antennaCapability")).leaf("id").queryFunction(QueryFunction.CONTAINS).parameter("ac1") + .build()); + + Condition actualCondition = scopeObject1.getCondition(); + // spotless:off + assertEquals(("ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\"" + + ".\"bSide_AntennaCapability\"like(('%'||replace(" + "\n"+ + "replace(" + "\n"+ + "replace('ac1','!','!!')," + "\n"+ + "'%'," + "\n"+ + "'!%'" + "\n"+ + ")," + "\n"+ + "'_'," + "\n"+ + "'!_'" + "\n"+ + "))||'%')escape'!'") + .replace(" ", ""), actualCondition.toString().replace(" ", "")); + // spotless:on + } + + @Test + void testConditions_entityAssociation_oneToMany1Contains() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ENodeBFunction").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.CONTAINS).parameter("me1") + .build()); + + Condition actualCondition = scopeObject1.getCondition(); + // spotless:off + assertEquals( + ("ties_data.\"o-ran-smo-teiv-ran_ENodeBFunction\".\"REL_FK_managed-by-managedElement\"like(('%'||replace(" + "\n" + + "replace(" +"\n"+ + "replace('me1','!','!!')," + "\n" + + "'%'," + "\n" + + "'!%'" + "\n" + + ")," + "\n" + + "'_'," + "\n" + + "'!_'" + "\n" + + "))||'%')escape'!'" + ).replace(" ", ""), actualCondition.toString().replace(" ", "")); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToMany1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_MODULE).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serviced-antennaCapability")).leaf("id").queryFunction(QueryFunction.EQ).parameter("ac1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_MODULE).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serviced-antennaCapability")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".\"bSide_AntennaCapability\" = 'ac1'\n" + + " and ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".id is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_manyToMany2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serving-antennaModule")).leaf("id").queryFunction(QueryFunction.EQ).parameter("am1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder(ANTENNA_CAPABILITY).topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serving-antennaModule")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null).build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".\"aSide_AntennaModule\" = 'am1'\n" + + " and ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".id is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_oneToMany1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("managed-by-managedElement")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_ENodeBFunction\".\"REL_FK_managed-by-managedElement\" = 'me1'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_FK_managed-by-managedElement\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_oneToMany2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("managed-enodebFunction")).leaf("id").queryFunction(QueryFunction.EQ).parameter("enbf1") + .build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("managed-by-managedElement")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_ENodeBFunction\".\"REL_FK_managed-by-managedElement\" is not null\n" + + " and ties_data.\"o-ran-smo-teiv-ran_ENodeBFunction\".\"id\" = 'enbf1'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"REL_FK_managed-by-managedElement\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_manyToOne1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_INSTALLED_AT_SITE") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("installed-at-site")).leaf("id").queryFunction(QueryFunction.EQ).parameter("site1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_INSTALLED_AT_SITE") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("installed-at-site")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null).build()); + + AndOrLogicalBlock alb = new OrLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" = 'site1'\n" + + " or ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_manyToOne2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_INSTALLED_AT_SITE") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("installed-antennaModule")).leaf("id").queryFunction(QueryFunction.EQ).parameter("am1") + .build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_INSTALLED_AT_SITE") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("installed-antennaModule")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new OrLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (\n" + + " ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n" + + " and ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"id\" = 'am1'\n" + + " )\n" + + " or ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\".\"REL_FK_installed-at-site\" is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_manyToMany1() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_SERVES_ANTENNACAPABILITY") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("serviced-antennaCapability")).leaf("id").queryFunction(QueryFunction.EQ).parameter("ac1") + .build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_SERVES_ANTENNACAPABILITY") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("serviced-antennaCapability")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".\"bSide_AntennaCapability\" = 'ac1'\n" + + " and ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".id is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationAssociation_manyToMany2() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_SERVES_ANTENNACAPABILITY") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("serving-antennaModule")).leaf("id").queryFunction(QueryFunction.EQ).parameter("am1").build()); + + ScopeLogicalBlock scopeObject2 = new ScopeLogicalBlock(ScopeObject.builder("ANTENNAMODULE_SERVES_ANTENNACAPABILITY") + .topologyObjectType(TopologyObjectType.RELATION).container(ContainerType.ASSOCIATION).innerContainer(List + .of("serving-antennaModule")).leaf(null).queryFunction(QueryFunction.NOT_NULL).parameter(null) + .build()); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(scopeObject1, scopeObject2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".\"aSide_AntennaModule\" = 'am1'\n" + + " and ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".id is not null\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityAssociation_throws() { + ScopeLogicalBlock scopeObject1 = new ScopeLogicalBlock(ScopeObject.builder("CloudNativeApplication").container( + ContainerType.ASSOCIATION).innerContainer(List.of("realised-gnbduFunction")).leaf("id").queryFunction( + QueryFunction.CONTAINS).parameter("gnbdu1").build()); + assertThrows(TiesPathException.class, scopeObject1::getCondition); + } + + @Test + void testConditions_entityClassifiers() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.CLASSIFIERS).leaf(ITEM).queryFunction(QueryFunction.CONTAINS).parameter( + "gnbdu-function-model:Ru").dataType(DataType.CONTAINER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBCUCP_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.CLASSIFIERS).leaf(ITEM).queryFunction(QueryFunction.EQ).parameter( + "gnbcucp-function-model:Weekend").dataType(DataType.CONTAINER).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"CD_classifiers\"::text like '%gnbdu-function-model:Ru%')\n" + + " and (ties_data.\"o-ran-smo-teiv-ran_GNBCUCPFunction\".\"CD_classifiers\" @> '\"gnbcucp-function-model:Weekend\"')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationshipClassifiers() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.CLASSIFIERS).leaf(ITEM).queryFunction( + QueryFunction.CONTAINS).parameter("gnbdu-function-model:Ru").dataType(DataType.CONTAINER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.CLASSIFIERS).leaf(ITEM).queryFunction(QueryFunction.EQ) + .parameter("gnbcucp-function-model:Weekend").dataType(DataType.CONTAINER).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU\"::text like '%gnbdu-function-model:Ru%')\n" + + " and (ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" @> '\"gnbcucp-function-model:Weekend\"')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entitySourceIds() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.SOURCE_IDS).leaf(ITEM).queryFunction(QueryFunction.CONTAINS).parameter( + "urn:cmHandle:").dataType(DataType.CONTAINER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBCUCP_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.SOURCE_IDS).leaf(ITEM).queryFunction(QueryFunction.EQ).parameter( + "urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16") + .dataType(DataType.CONTAINER).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"CD_sourceIds\"::text like '%urn:cmHandle:%')\n" + + " and (ties_data.\"o-ran-smo-teiv-ran_GNBCUCPFunction\".\"CD_sourceIds\" @> '\"urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16\"')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationshipSourceIds() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.SOURCE_IDS).leaf(ITEM).queryFunction( + QueryFunction.CONTAINS).parameter("urn:cmHandle:").dataType(DataType.CONTAINER).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.SOURCE_IDS).leaf(ITEM).queryFunction(QueryFunction.EQ) + .parameter( + "urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16") + .dataType(DataType.CONTAINER).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + + AndOrLogicalBlock alb = new AndLogicalBlock(); + alb.setChildren(List.of(slb1, slb2)); + + Condition actualCondition = alb.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " (ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU\"::text like '%urn:cmHandle:%')\n" + + " and (ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" @> '\"urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16\"')\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_entityDecorators() { + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.DECORATORS).leaf("gnbdu-function-model:location").queryFunction( + QueryFunction.CONTAINS).parameter("Stock").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder(GNBCUCP_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.DECORATORS).leaf("gnbdu-function-model:stringdata").queryFunction(QueryFunction.EQ) + .parameter("ASD").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject3 = ScopeObject.builder(GNBCUCP_FUNCTION).topologyObjectType(TopologyObjectType.ENTITY) + .container(ContainerType.DECORATORS).leaf("gnbdu-function-model:intdata").queryFunction(QueryFunction.EQ) + .parameter("2").dataType(DataType.BIGINT).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + AndOrLogicalBlock alb1 = new AndLogicalBlock(); + AndOrLogicalBlock alb2 = new AndLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + alb2.setChildren(List.of(alb1, slb3)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"CD_decorators\" ->> 'gnbdu-function-model:location' like '%Stock%'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBCUCPFunction\".\"CD_decorators\" -> 'gnbdu-function-model:stringdata' = '\"ASD\"'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_GNBCUCPFunction\".\"CD_decorators\" -> 'gnbdu-function-model:intdata' = '2'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testConditions_relationshipDecorators() { + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.DECORATORS).leaf("gnbdu-function-model:location") + .queryFunction(QueryFunction.CONTAINS).parameter("Stock").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.DECORATORS).leaf("gnbdu-function-model:stringdata") + .queryFunction(QueryFunction.EQ).parameter("ASD").dataType(DataType.PRIMITIVE).build(); + + ScopeObject scopeObject3 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").topologyObjectType( + TopologyObjectType.RELATION).container(ContainerType.DECORATORS).leaf("gnbdu-function-model:intdata") + .queryFunction(QueryFunction.EQ).parameter("2").dataType(DataType.BIGINT).build(); + + LogicalBlock slb1 = new ScopeLogicalBlock(scopeObject1); + LogicalBlock slb2 = new ScopeLogicalBlock(scopeObject2); + LogicalBlock slb3 = new ScopeLogicalBlock(scopeObject3); + + AndOrLogicalBlock alb1 = new AndLogicalBlock(); + AndOrLogicalBlock alb2 = new AndLogicalBlock(); + alb1.setChildren(List.of(slb1, slb2)); + alb2.setChildren(List.of(alb1, slb3)); + + Condition actualCondition = alb2.getCondition(); + // spotless:off + assertEquals(condition( + "\n" + + " ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU\" ->> 'gnbdu-function-model:location' like '%Stock%'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" -> 'gnbdu-function-model:stringdata' = '\"ASD\"'\n" + + " and ties_data.\"o-ran-smo-teiv-ran_NRSectorCarrier\".\"REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER\" -> 'gnbdu-function-model:intdata' = '2'\n") + .toString(), actualCondition.toString()); + // spotless:on + } + + @Test + void testGetJoinCondition() { + LogicalBlock slb1 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of("provided-nrCellDu")) + .build()); + + InnerFilterCriteria innerFilterCriteria1 = InnerFilterCriteria.builder().scope(slb1).build(); + + Pair pair1 = new ImmutablePair<>("ties_data.\"o-ran-smo-teiv-ran_NRCellDU\"", field( + "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\".\"REL_FK_provided-by-gnbduFunction\"" + "=" + "ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"")); + + Assertions.assertEquals(new HashSet(Arrays.asList(pair1)), innerFilterCriteria1.builder().scope(slb1).build() + .getJoinCondition()); + + LogicalBlock slb2 = new ScopeLogicalBlock(ScopeObject.builder("AntennaCapability").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ASSOCIATION).innerContainer(List.of( + "serving-antennaModule")).build()); + + InnerFilterCriteria innerFilterCriteria2 = InnerFilterCriteria.builder().scope(slb2).build(); + + Pair pair2 = new ImmutablePair<>("ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\"", field( + "ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\".\"bSide_AntennaCapability\"" + "=" + "ties_data.\"o-ran-smo-teiv-ran_AntennaCapability\".\"id\"")); + + Assertions.assertEquals(new HashSet(Arrays.asList(pair2)), innerFilterCriteria2.builder().scope(slb2).build() + .getJoinCondition()); + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteriaTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteriaTest.java index ba35f10..bcfd4bb 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteriaTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/FilterCriteriaTest.java @@ -20,77 +20,136 @@ */ package org.oran.smo.teiv.exposure.tiespath.innerlanguage; -import java.util.Arrays; +import static org.jooq.impl.DSL.condition; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.table; + +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.jooq.SelectField; +import org.jooq.Table; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataValidator; +import org.oran.smo.teiv.exposure.tiespath.refiner.BasePathRefinement; +import org.oran.smo.teiv.exposure.tiespath.resolver.ScopeResolver; +import org.oran.smo.teiv.exposure.tiespath.resolver.TargetResolver; import org.oran.smo.teiv.schema.DataType; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; class FilterCriteriaTest { + + private static BasePathRefinement basePathRefinement; + private static ConsumerDataValidator consumerDataValidator; + private final TargetResolver targetResolver = new TargetResolver(); + private final ScopeResolver scopeResolver = new ScopeResolver(); + + @BeforeAll + static void setUp() throws SchemaLoaderException { + new MockSchemaLoader().loadSchemaRegistry(); + basePathRefinement = new BasePathRefinement(consumerDataValidator); + } + @Test void testFilterCriteria() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - TargetObject targetObject = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).params(List - .of("gNBId")).build(); - filterCriteria.setTargets(List.of(targetObject)); - ScopeObject scopeObject = new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, "gNBIDLength", - QueryFunction.EQ, "1", DataType.BIGINT); - ScopeLogicalBlock logicalBlock = new ScopeLogicalBlock(scopeObject); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(null, null); + List targetObjects = targetResolver.resolve("GNBDUFunction", "/attributes(gNBId)"); + filterCriteria.setTargets(targetObjects); + LogicalBlock logicalBlock = scopeResolver.resolve("GNBDUFunction", "/attributes[@gNBIdLength=1]"); filterCriteria.setScope(logicalBlock); - Assertions.assertEquals(1, filterCriteria.getTargets().size()); - Assertions.assertEquals("RAN_LOGICAL", filterCriteria.getDomain()); Assertions.assertEquals(QueryFunction.EQ, ((ScopeLogicalBlock) filterCriteria.getScope()).getScopeObject() .getQueryFunction()); + Assertions.assertEquals("gNBIdLength", ((ScopeLogicalBlock) filterCriteria.getScope()).getScopeObject().getLeaf()); + Assertions.assertEquals(ContainerType.ATTRIBUTES, ((ScopeLogicalBlock) filterCriteria.getScope()).getScopeObject() + .getContainer()); + } @Test void testGetTables() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - TargetObject targetObject = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).params(List - .of("gNBId", "gNBIdLength")).build(); - filterCriteria.setTargets(Arrays.asList(targetObject)); - OrLogicalBlock orLogicalBlock = new OrLogicalBlock(); - ScopeObject scopeObject1 = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBIdLength", - QueryFunction.EQ, "1", DataType.BIGINT); - ScopeObject scopeObject2 = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBId", QueryFunction.EQ, - "8", DataType.BIGINT); - ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(scopeObject1); - ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(scopeObject2); - orLogicalBlock.setChildren(Arrays.asList(scopeLogicalBlock1, scopeLogicalBlock2)); - filterCriteria.setScope(orLogicalBlock); - - Set expected = new HashSet<>(); - expected.add(null); - Assertions.assertEquals(expected, filterCriteria.getTables()); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(null, null); + List targetObjects = targetResolver.resolve("GNBDUFunction", "/attributes(gNBId,gNBIdLength)"); + filterCriteria.setTargets(targetObjects); + targetObjects.get(0).setTopologyObjectType(TopologyObjectType.ENTITY); + LogicalBlock logicalBlock = scopeResolver.resolve("GNBDUFunction", "/attributes[@gNBIdLength=1 or @gNBId=8]"); + ((OrLogicalBlock) logicalBlock).getChildren().forEach(l -> ((ScopeLogicalBlock) l).getScopeObject() + .setTopologyObjectType(TopologyObjectType.ENTITY)); + filterCriteria.setScope(logicalBlock); + basePathRefinement.resolveUndefinedTopologyObjectTypes(FilterCriteria.builder("RAN").filterCriteriaList(List.of( + filterCriteria)).build()); + + Set
result = new HashSet<>(); + result.add(table("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"")); + + Assertions.assertEquals(result, filterCriteria.getTables()); + + InnerFilterCriteria filterCriteria2 = new InnerFilterCriteria(null, null); + List targetObjects2 = targetResolver.resolve("GNBDUFUNCTION_PROVIDES_NRCELLDU", null); + filterCriteria2.setTargets(targetObjects2); + LogicalBlock logicalBlock2 = scopeResolver.resolve("NRCellDU", "/attributes[@nCI=12]"); + filterCriteria2.setScope(logicalBlock2); + basePathRefinement.resolveUndefinedTopologyObjectTypes(FilterCriteria.builder("RAN").filterCriteriaList(List.of( + filterCriteria2)).build()); + + result.clear(); + + result.add(table("ties_data.\"o-ran-smo-teiv-ran_NRCellDU\"")); + + Assertions.assertEquals(result, filterCriteria2.getTables()); + + InnerFilterCriteria filterCriteria3 = new InnerFilterCriteria(null, null); + List targetObjects3 = targetResolver.resolve("GNBDUFunction", "/attributes(gNBId,gNBIdLength)"); + filterCriteria3.setTargets(targetObjects3); + LogicalBlock logicalBlock3 = scopeResolver.resolve("GNBDUFunction", "/attributes[@gNBIdLength=1 or @gNBId=8]"); + filterCriteria3.setScope(logicalBlock3); + + Assertions.assertThrows(TiesException.class, filterCriteria3::getTables); + } @Test void testGetSelects() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - - TargetObject targetObject = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).params(List - .of("gNBId", "gNBIdLength")).build(); - filterCriteria.setTargets(Arrays.asList(targetObject)); - - Set expected = new HashSet<>(); - expected.add(null); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(null, null); + List targetObjects = targetResolver.resolve("GNBDUFunction", "/attributes(gNBId,gNBIdLength)"); + targetObjects.get(0).setTopologyObjectType(TopologyObjectType.ENTITY); + filterCriteria.setTargets(targetObjects); + Map> expected = new HashMap<>(); + expected.put(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), new HashMap<>()); + expected.get(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id")).put(field( + "ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"gNBId\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), DataType.BIGINT); + expected.get(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id")).put(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"") + .as("o-ran-smo-teiv-ran:GNBDUFunction.id"), DataType.PRIMITIVE); + expected.get(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id")).put(field( + "ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"gNBIdLength\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBIdLength"), DataType.INTEGER); Assertions.assertEquals(expected, filterCriteria.getSelects()); } @Test void testGetCondition() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - ScopeObject scopeObject = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, QueryFunction.EQ, "1", - DataType.BIGINT); - ScopeLogicalBlock scopeLogicalBlock = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scopeLogicalBlock); - - Assertions.assertEquals(null, filterCriteria.getCondition()); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(null, null); + LogicalBlock logicalBlock = scopeResolver.resolve("GNBDUFunction", "/attributes[@gNBIdLength=1]"); + filterCriteria.setScope(logicalBlock); + filterCriteria.setTargets(List.of()); + basePathRefinement.resolveUndefinedTopologyObjectTypes(FilterCriteria.builder("RAN").filterCriteriaList(List.of( + filterCriteria)).build()); + basePathRefinement.validateScopeParametersDataType(FilterCriteria.builder("RAN").filterCriteriaList(List.of( + filterCriteria)).build()); + Assertions.assertEquals(condition(field("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"gNBIdLength\"").eq(1)) + .toString(), filterCriteria.getCondition().toString()); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlockTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlockTest.java new file mode 100644 index 0000000..fdba4e9 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/ScopeLogicalBlockTest.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.innerlanguage; + +import static org.jooq.impl.DSL.table; +import static org.junit.Assert.assertThrows; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.jooq.Table; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.schema.DataType; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; + +class ScopeLogicalBlockTest { + + @BeforeAll + static void setUp() throws SchemaLoaderException { + SchemaLoader mockedSchemaLoader = new MockSchemaLoader(); + mockedSchemaLoader.loadSchemaRegistry(); + } + + @Test + void testGetTables() { + + Set
resultTables = new HashSet<>(); + + ScopeObject scopeObject = ScopeObject.builder("GNBDUFunction").container(ContainerType.ASSOCIATION).leaf("id") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + scopeObject.setInnerContainer(Arrays.asList("provided-nrCellDu")); + scopeObject.setTopologyObjectType(TopologyObjectType.ENTITY); + + ScopeObject scopeObject1 = ScopeObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).leaf( + "gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.INTEGER).build(); + scopeObject1.setTopologyObjectType(TopologyObjectType.ENTITY); + + ScopeObject scopeObject2 = ScopeObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("8").dataType(DataType.BIGINT).build(); + scopeObject2.setTopologyObjectType(TopologyObjectType.ENTITY); + + ScopeObject scopeObject3 = ScopeObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + scopeObject3.setTopologyObjectType(TopologyObjectType.UNDEFINED); + + ScopeObject scopeObject4 = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").container(ContainerType.ID) + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.PRIMITIVE).build(); + scopeObject4.setTopologyObjectType(TopologyObjectType.RELATION); + + ScopeObject scopeObject5 = ScopeObject.builder("GNBDUFunction").container(ContainerType.ASSOCIATION).leaf("id") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + scopeObject5.setInnerContainer(Arrays.asList("managed-by-managedElement")); + scopeObject5.setTopologyObjectType(TopologyObjectType.ENTITY); + + ScopeObject scopeObject6 = ScopeObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION").container( + ContainerType.ASSOCIATION).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1").dataType( + DataType.PRIMITIVE).build(); + scopeObject6.setInnerContainer(Arrays.asList("managed-by-managedElement")); + scopeObject6.setTopologyObjectType(TopologyObjectType.RELATION); + + ScopeObject scopeObject7 = ScopeObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION").container( + ContainerType.ASSOCIATION).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1").dataType( + DataType.PRIMITIVE).build(); + scopeObject7.setInnerContainer(Arrays.asList("provided-by-gnbduFunction")); + scopeObject7.setTopologyObjectType(TopologyObjectType.RELATION); + + ScopeLogicalBlock scopeLogicalBlock = new ScopeLogicalBlock(scopeObject); + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(scopeObject1); + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(scopeObject2); + ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(scopeObject3); + ScopeLogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(scopeObject4); + ScopeLogicalBlock scopeLogicalBlock5 = new ScopeLogicalBlock(scopeObject5); + ScopeLogicalBlock scopeLogicalBlock6 = new ScopeLogicalBlock(scopeObject6); + ScopeLogicalBlock scopeLogicalBlock7 = new ScopeLogicalBlock(scopeObject7); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_NRCellDU\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock.getTables()); + resultTables.clear(); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock1.getTables()); + resultTables.clear(); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock2.getTables()); + resultTables.clear(); + + assertThrows(TiesException.class, scopeLogicalBlock3::getTables); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_NRCellDU\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock4.getTables()); + resultTables.clear(); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock5.getTables()); + resultTables.clear(); + + resultTables.add(table("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"")); + Assertions.assertEquals(resultTables, scopeLogicalBlock6.getTables()); + resultTables.clear(); + + Assertions.assertThrows(TiesException.class, () -> scopeLogicalBlock7.getTables()); + } + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/SelectBlockTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/SelectBlockTest.java new file mode 100644 index 0000000..d10e277 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/innerlanguage/SelectBlockTest.java @@ -0,0 +1,250 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.innerlanguage; + +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; +import static org.oran.smo.teiv.schema.DataType.*; +import static org.jooq.impl.DSL.field; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; + +public class SelectBlockTest { + + @BeforeAll + static void setup() throws SchemaLoaderException { + new MockSchemaLoader().loadSchemaRegistry(); + } + + @Test + void idInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.ID).topologyObjectType( + TopologyObjectType.ENTITY).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE)), filterCriteria.getSelects()); + } + + @Test + void attributesInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of("gNBDUId", "dUpLMNId")).container( + ContainerType.ATTRIBUTES).topologyObjectType(TopologyObjectType.ENTITY).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE, field("ties_data.\"GNBDUFunction\".\"gNBDUId\"") + .as("o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId"), BIGINT, field( + "ties_data.\"GNBDUFunction\".\"dUpLMNId\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.dUpLMNId"), CONTAINER)), + filterCriteria.getSelects()); + } + + @Test + void allAttributesInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.ATTRIBUTES) + .topologyObjectType(TopologyObjectType.ENTITY).isAllParamQueried(true).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE, field("ties_data.\"GNBDUFunction\".\"gNBId\"") + .as("o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), BIGINT, field( + "ties_data.\"GNBDUFunction\".\"gNBIdLength\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBIdLength"), INTEGER, field( + "ties_data.\"GNBDUFunction\".\"dUpLMNId\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.dUpLMNId"), + CONTAINER, field("ties_data.\"GNBDUFunction\".\"gNBDUId\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId"), BIGINT)), filterCriteria.getSelects()); + } + + @Test + void decoratorsInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.DECORATORS) + .topologyObjectType(TopologyObjectType.ENTITY).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE, field( + "ties_data.\"GNBDUFunction\".\"CD_decorators\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.decorators"), CONTAINER)), filterCriteria + .getSelects()); + } + + @Test + void classifiersInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.CLASSIFIERS) + .topologyObjectType(TopologyObjectType.ENTITY).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE, field( + "ties_data.\"GNBDUFunction\".\"CD_classifiers\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.classifiers"), CONTAINER)), filterCriteria + .getSelects()); + } + + @Test + void sourceIdInEntity() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.SOURCE_IDS) + .topologyObjectType(TopologyObjectType.ENTITY).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), Map.of(field("ties_data.\"GNBDUFunction\".\"id\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), PRIMITIVE, field( + "ties_data.\"GNBDUFunction\".\"CD_sourceIds\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.sourceIds"), CONTAINER)), filterCriteria + .getSelects()); + } + + @Test + void idInRelationship() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("SECTOR_GROUPS_ANTENNAMODULE").params(List.of()).container(ContainerType.ID) + .topologyObjectType(TopologyObjectType.RELATION).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias("o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), Map.of(field( + "ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"REL_FK_grouped-by-sector\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.aSide")), + PRIMITIVE, field("ties_data.\"AntennaModule\".\"id\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.bSide")), PRIMITIVE)), + filterCriteria.getSelects()); + } + + @Test + void decoratorsInRelationship() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("SECTOR_GROUPS_ANTENNAMODULE").params(List.of()).container( + ContainerType.DECORATORS).topologyObjectType(TopologyObjectType.RELATION).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias("o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), Map.of(field( + "ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.decorators")), + CONTAINER, field("ties_data.\"AntennaModule\".\"REL_FK_grouped-by-sector\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.aSide")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"id\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.bSide")), + PRIMITIVE)), filterCriteria.getSelects()); + } + + @Test + void classifiersInRelationship() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("SECTOR_GROUPS_ANTENNAMODULE").params(List.of()).container( + ContainerType.CLASSIFIERS).topologyObjectType(TopologyObjectType.RELATION).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias("o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), Map.of(field( + "ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE\"") + .as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.classifiers")), + CONTAINER, field("ties_data.\"AntennaModule\".\"REL_FK_grouped-by-sector\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.aSide")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"id\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.bSide")), + PRIMITIVE)), filterCriteria.getSelects()); + } + + @Test + void sourceIdInRelationship() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("SECTOR_GROUPS_ANTENNAMODULE").params(List.of()).container( + ContainerType.SOURCE_IDS).topologyObjectType(TopologyObjectType.RELATION).build()); + + Assertions.assertEquals(Map.of(field("ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias("o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), Map.of(field( + "ties_data.\"AntennaModule\".\"REL_ID_SECTOR_GROUPS_ANTENNAMODULE\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.id")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE\"").as( + hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.sourceIds")), + CONTAINER, field("ties_data.\"AntennaModule\".\"REL_FK_grouped-by-sector\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.aSide")), PRIMITIVE, field( + "ties_data.\"AntennaModule\".\"id\"").as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE.bSide")), + PRIMITIVE)), filterCriteria.getSelects()); + } + + @Test + void wrongTopologyObjectType() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.CLASSIFIERS) + .topologyObjectType(TopologyObjectType.UNDEFINED).build()); + + Assertions.assertThrowsExactly(TiesException.class, filterCriteria::getSelects); + } + + @Test + void wrongContainerType() { + List targets = new ArrayList<>(); + InnerFilterCriteria filterCriteria = new InnerFilterCriteria(targets, null); + + targets.add(TargetObject.builder("GNBDUFunction").params(List.of()).container(ContainerType.ASSOCIATION) + .topologyObjectType(TopologyObjectType.ENTITY).build()); + + Assertions.assertThrowsExactly(TiesException.class, filterCriteria::getSelects); + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapperTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapperTest.java new file mode 100644 index 0000000..d83c1c7 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/AliasMapperTest.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.refiner; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class AliasMapperTest { + + @Test + void testAliasMapper() { + final String LONG_ALIAS = "this-is-a-very-long-alias-which-exceeds-the-sixty-three-characters"; + //hashed alias is same as alias if less than 63 chars + final String hashedAlias1 = AliasMapper.hashAlias("alias"); + assertEquals("alias", hashedAlias1); + //hashed alias is SHA-1 hash of alias + final String hashedAlias2 = AliasMapper.hashAlias(LONG_ALIAS); + assertEquals(40, hashedAlias2.length()); + assertEquals("8CE1DE1724594D06F010A083831CA2B0A345F730", hashedAlias2); + + //alias is same as hashed alias if less than 63 chars + assertEquals("alias", AliasMapper.getOriginalAlias("alias")); + //verify the retrieval of original alias from hashed alias + assertEquals(LONG_ALIAS, AliasMapper.getOriginalAlias("8CE1DE1724594D06F010A083831CA2B0A345F730")); + } + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinementTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinementTest.java index ca044db..cd77164 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinementTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/BasePathRefinementTest.java @@ -20,19 +20,30 @@ */ package org.oran.smo.teiv.exposure.tiespath.refiner; +import static org.oran.smo.teiv.utils.TiesConstants.ID_COLUMN_NAME; +import static org.oran.smo.teiv.utils.TiesConstants.ITEM; +import static org.oran.smo.teiv.utils.TiesConstants.WILDCARD; +import static org.mockito.Mockito.mock; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; -import org.apache.commons.lang3.NotImplementedException; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.EmptyLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.InnerFilterCriteria; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataValidator; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndOrLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; -import org.oran.smo.teiv.exposure.tiespath.innerlanguage.EmptyLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; @@ -41,331 +52,1265 @@ import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeLogicalBlock; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeObject; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TargetObject; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TopologyObjectType; +import org.oran.smo.teiv.exposure.tiespath.resolver.ResolverDataType; +import org.oran.smo.teiv.exposure.tiespath.resolver.ScopeResolver; +import org.oran.smo.teiv.exposure.tiespath.resolver.TargetResolver; import org.oran.smo.teiv.schema.DataType; import org.oran.smo.teiv.schema.MockSchemaLoader; import org.oran.smo.teiv.schema.SchemaLoader; import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; -import org.junit.jupiter.api.BeforeAll; +class BasePathRefinementTest { -import static org.oran.smo.teiv.utils.TiesConstants.ITEMS; + private static final ConsumerDataValidator consumerDataValidator = mock(ConsumerDataValidator.class); + private static BasePathRefinement basePathRefinement; + private final TargetResolver targetResolver = new TargetResolver(); + private final ScopeResolver scopeResolver = new ScopeResolver(); -class BasePathRefinementTest { + private static final String GNBDU_FUNCTION = "GNBDUFunction"; @BeforeAll static void setUp() throws SchemaLoaderException { SchemaLoader mockedSchemaLoader = new MockSchemaLoader(); mockedSchemaLoader.loadSchemaRegistry(); + basePathRefinement = new BasePathRefinement(consumerDataValidator); } @Test - void testResolveWildCardObjectsInScopeAndTarget() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - Assertions.assertThrows(NotImplementedException.class, () -> BasePathRefinement - .resolveWildCardObjectsInScopeAndTarget(filterCriteria)); + void testRefinementOrchestration() { + LogicalBlock logicalBlock = scopeResolver.process(null, "/attributes[@gNBCUName='someCUCPName']"); + List targets = targetResolver.resolve(null, "/GNBCUCPFunction/attributes"); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(targets).scope(logicalBlock).build())).resolvingTopologyObjectType( + FilterCriteria.ResolvingTopologyObjectType.ENTITY).build(); + + basePathRefinement.refine(filterCriteria); + + LogicalBlock expectedLogicalBlock = scopeResolver.process(null, "/attributes[@gNBCUName='someCUCPName']"); + List expectedTargets = targetResolver.resolve(null, "/GNBCUCPFunction/attributes"); + FilterCriteria expectedFilterCriteria = FilterCriteria.builder("RAN").filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(expectedTargets).scope(expectedLogicalBlock).build())).resolvingTopologyObjectType( + FilterCriteria.ResolvingTopologyObjectType.ENTITY).build(); + + ScopeObject expectedScopeObject = ((ScopeLogicalBlock) expectedLogicalBlock).getScopeObject(); + expectedScopeObject.setTopologyObject("GNBCUCPFunction"); + expectedScopeObject.setTopologyObjectType(TopologyObjectType.ENTITY); + expectedScopeObject.setContainer(ContainerType.ATTRIBUTES); + expectedScopeObject.setLeaf("gNBCUName"); + expectedScopeObject.setQueryFunction(QueryFunction.EQ); + expectedScopeObject.setParameter("someCUCPName"); + expectedScopeObject.setDataType(DataType.PRIMITIVE); + + expectedTargets.get(0).setTopologyObjectType(TopologyObjectType.ENTITY); + expectedTargets.get(0).setAllParamQueried(true); + + Assertions.assertEquals(expectedFilterCriteria, filterCriteria); + } + + @Test + void processTopologyObjectsWithContainerTypeNull() { + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + LogicalBlock logicalBlock1 = scopeResolver.process(null, "/managed-by-managedElement[@id='me1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock1).build())); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(filterCriteria); + + ScopeObject scopeObjectResult1 = ScopeObject.builder(WILDCARD).container(ContainerType.ASSOCIATION).innerContainer( + List.of("managed-by-managedElement")).resolverDataType(ResolverDataType.STRING).queryFunction( + QueryFunction.EQ).leaf(ID_COLUMN_NAME).parameter("me1").build(); + Assertions.assertEquals(scopeObjectResult1, ((ScopeLogicalBlock) logicalBlock1).getScopeObject()); + + LogicalBlock logicalBlock2 = scopeResolver.process(GNBDU_FUNCTION, "/managed-by-managedElement"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock2).build())); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(filterCriteria); + + ScopeObject scopeObjectResult2 = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ASSOCIATION) + .innerContainer(List.of("managed-by-managedElement")).resolverDataType(ResolverDataType.NOT_NULL) + .queryFunction(QueryFunction.NOT_NULL).build(); + Assertions.assertEquals(scopeObjectResult2, ((ScopeLogicalBlock) logicalBlock2).getScopeObject()); + + LogicalBlock logicalBlock3 = scopeResolver.process(null, "/GNBDUFUNCTION_PROVIDES_NRCELLDU"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock3).build())); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(filterCriteria); + + ScopeObject scopeObjectResult3 = ScopeObject.builder(WILDCARD).container(ContainerType.RELATION).innerContainer(List + .of("GNBDUFUNCTION_PROVIDES_NRCELLDU")).resolverDataType(ResolverDataType.NOT_NULL).queryFunction( + QueryFunction.NOT_NULL).build(); + Assertions.assertEquals(scopeObjectResult3, ((ScopeLogicalBlock) logicalBlock3).getScopeObject()); + + LogicalBlock logicalBlock4 = scopeResolver.process(null, "/GNBDUFunction[@id='gnbdu1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock4).build())); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(filterCriteria); + + ScopeObject scopeObjectResult4 = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ID).resolverDataType( + ResolverDataType.STRING).queryFunction(QueryFunction.EQ).parameter("gnbdu1").build(); + Assertions.assertEquals(scopeObjectResult4, ((ScopeLogicalBlock) logicalBlock4).getScopeObject()); + + LogicalBlock logicalBlock5 = scopeResolver.process("NRCellDU", "/GNBDUFunction[@id='GNBDU_1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock5).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement + .processTopologyObjectsWithContainerTypeNull(filterCriteria)); + + ScopeObject scopeObject = ScopeObject.builder(WILDCARD).container(null).build(); + LogicalBlock logicalBlock6 = new ScopeLogicalBlock(scopeObject); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock6).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement + .processTopologyObjectsWithContainerTypeNull(filterCriteria)); + + try (MockedStatic utilities = Mockito.mockStatic(SchemaRegistry.class)) { + utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN")).thenReturn(Arrays.asList( + "RelationAndEntity")); + utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN")).thenReturn(Arrays.asList( + "RelationAndEntity")); + LogicalBlock logicalBlock7 = scopeResolver.process(null, "/RelationAndEntity[@id='relAndEnt1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock7).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement + .processTopologyObjectsWithContainerTypeNull(filterCriteria)); + utilities.when(() -> SchemaRegistry.getAssociationNamesByEntityName(GNBDU_FUNCTION)).thenReturn(Arrays.asList( + "RelationAndAssociation")); + utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN")).thenReturn(Arrays.asList( + "RelationAndAssociation")); + LogicalBlock logicalBlock8 = scopeResolver.process(null, "/RelationAndAssociation[@id='relAndAssoc1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock8).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement + .processTopologyObjectsWithContainerTypeNull(filterCriteria)); + } + + LogicalBlock logicalBlock9 = scopeResolver.process(null, "/NRCellDU/attributes[@nCI=12]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock9).build())); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(filterCriteria); + + ScopeObject scopeObjectResult9 = ScopeObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES) + .resolverDataType(ResolverDataType.INTEGER).queryFunction(QueryFunction.EQ).leaf("nCI").parameter("12") + .build(); + Assertions.assertEquals(scopeObjectResult9, ((ScopeLogicalBlock) logicalBlock9).getScopeObject()); + + LogicalBlock logicalBlock10 = scopeResolver.process(null, "/NRCellDU[@nCI=12]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock10).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement + .processTopologyObjectsWithContainerTypeNull(filterCriteria)); + + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_1() { + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().targets(targetResolver.resolve(null, + "/GNBDUFunction/attributes(gNBDUId); /GNBDUFunction/attributes(gNBId); /attributes(name)")).scope( + EmptyLogicalBlock.getInstance()).build(); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveWildCardObjectsInScopeAndTarget( + filterCriteria, "RAN", FilterCriteria.ResolvingTopologyObjectType.ENTITY)); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_2() { + //root:GNBDUFunction + //Target: /attributes(gNBId); /attributes(dUpLMNId) + //Scope: /attribute[gNBIdLength = 2] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, + "/GNBDUFunction/attributes(dUpLMNId); /GNBDUFunction/attributes(gNBId)")); + filterCriteria.setScope(scopeResolver.resolve(null, "/GNBDUFunction/attributes[@gNBIdLength=2]")); + + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).leaf( + "gNBIdLength").queryFunction(QueryFunction.EQ).parameter("2").resolverDataType(ResolverDataType.INTEGER) + .build(); + LogicalBlock scopeResult1 = new ScopeLogicalBlock(scopeObject1); + + TargetObject targetObjectResult = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).params( + new ArrayList<>(Arrays.asList("dUpLMNId", "gNBId"))).build(); + List resultTargetObjects = new ArrayList<>(); + resultTargetObjects.add(targetObjectResult); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects, filterCriteria.getTargets()); + Assertions.assertEquals(scopeResult1, filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_3() { + //root:- + //Target:/attributes;/attributes(cellLocalId,nCI) + //Scope:/NRCellDU[nCI=12] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes;/attributes(cellLocalId,nCI)")); + filterCriteria.setScope(scopeResolver.resolve(null, "/NRCellDU/attributes[@nCI=12]")); + + TargetObject targetObjectResult3_1 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).params( + new ArrayList<>(Arrays.asList("nCI", "cellLocalId"))).isAllParamQueried(true).build(); + List resultTargetObjects3_1 = new ArrayList<>(); + resultTargetObjects3_1.add(targetObjectResult3_1); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects3_1, filterCriteria.getTargets()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_4() { + //root:- + //Target:/attributes;/attributes(cellLocalId) + //Scope:/attributes[nCI = 12] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes;/attributes(cellLocalId)")); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@nCI=12]")); + + TargetObject targetObjectResult4_1 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).params( + List.of("cellLocalId")).isAllParamQueried(true).build(); + TargetObject targetObjectResult4_2 = TargetObject.builder("NRCellCU").container(ContainerType.ATTRIBUTES).params( + List.of("cellLocalId")).isAllParamQueried(true).build(); + List resultTargetObjects4_1 = new ArrayList<>(); + resultTargetObjects4_1.add(targetObjectResult4_1); + resultTargetObjects4_1.add(targetObjectResult4_2); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects4_1, filterCriteria.getTargets()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_5() { + //root:- + //Target:- + //Scope:/attributes[gNBId = 6 and gNBIdLength = 1] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, null)); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@gNBId = 6 and @gNBIdLength = 1]")); + + ScopeLogicalBlock GNBCUUPFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder("GNBCUUPFunction").container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBDUFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBCUCPFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBCUUPFunctionPgNBIdLength = new ScopeLogicalBlock(ScopeObject.builder("GNBCUUPFunction") + .container(ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1") + .resolverDataType(ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBDUFunctionPgNBIdLength = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1") + .resolverDataType(ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBCUCPFunctionPgNBIdLength = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction") + .container(ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1") + .resolverDataType(ResolverDataType.INTEGER).build()); + + AndLogicalBlock GNBCUUPFunction = new AndLogicalBlock(); + AndLogicalBlock GNBDUFunction = new AndLogicalBlock(); + AndLogicalBlock GNBCUCPFunction = new AndLogicalBlock(); + + GNBCUCPFunction.getChildren().add(GNBCUCPFunctionPgNBId); + GNBCUCPFunction.getChildren().add(GNBCUCPFunctionPgNBIdLength); + GNBCUUPFunction.getChildren().add(GNBCUUPFunctionPgNBId); + GNBCUUPFunction.getChildren().add(GNBCUUPFunctionPgNBIdLength); + GNBDUFunction.getChildren().add(GNBDUFunctionPgNBId); + GNBDUFunction.getChildren().add(GNBDUFunctionPgNBIdLength); + + OrLogicalBlock or1 = new OrLogicalBlock(); + OrLogicalBlock or2 = new OrLogicalBlock(); + + or1.getChildren().add(or2); + or1.getChildren().add(GNBDUFunction); + or2.getChildren().add(GNBCUCPFunction); + or2.getChildren().add(GNBCUUPFunction); + + TargetObject targetObjectResult5_1 = TargetObject.builder("GNBCUUPFunction").container(ContainerType.ID).build(); + TargetObject targetObjectResult5_2 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ID).build(); + TargetObject targetObjectResult5_3 = TargetObject.builder("GNBCUCPFunction").container(ContainerType.ID).build(); + List resultTargetObjects5_1 = new ArrayList<>(); + resultTargetObjects5_1.add(targetObjectResult5_1); + resultTargetObjects5_1.add(targetObjectResult5_2); + resultTargetObjects5_1.add(targetObjectResult5_3); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + Assertions.assertEquals(resultTargetObjects5_1, filterCriteria.getTargets()); + Assertions.assertEquals(or1, filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_6() { + //root:- + //Target:/NRCellDU + //Scope:/attributes[@cellLocalId = 156] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/NRCellDU")); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@cellLocalId = 156]")); + + TargetObject targetObjectResult6_1 = TargetObject.builder("NRCellDU").container(ContainerType.ID).build(); + List resultTargetObjects6_1 = new ArrayList<>(); + resultTargetObjects6_1.add(targetObjectResult6_1); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + ScopeObject scopeObjectResult6_1 = ScopeObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).leaf( + "cellLocalId").queryFunction(QueryFunction.EQ).parameter("156").resolverDataType(ResolverDataType.INTEGER) + .build(); + LogicalBlock logicalBlockResult6_1 = new ScopeLogicalBlock(scopeObjectResult6_1); + + Assertions.assertEquals(resultTargetObjects6_1, filterCriteria.getTargets()); + Assertions.assertEquals(logicalBlockResult6_1, filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_7() { + //root:- + //Target:/attributes(gNBId);/attributes(nCI) + //Scope:- + //error no intersection + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes(gNBId);/attributes(nCI)")); + filterCriteria.setScope(scopeResolver.resolve(null, null)); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveWildCardObjectsInScopeAndTarget( + filterCriteria, "RAN", FilterCriteria.ResolvingTopologyObjectType.ENTITY)); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_8() { + //root:- + //Target:/attributes(nCI) + //Scope:/attributes[gNBId = 6] + //error no intersection + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes(nCI)")); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@gNBId = 6]")); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveWildCardObjectsInScopeAndTarget( + filterCriteria, "RAN", FilterCriteria.ResolvingTopologyObjectType.ENTITY)); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_9() { + //root:- + //Target:/attributes + //Scope:/attributes[cellLocalId = 178]; /attributes[nCI = 12] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes")); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@cellLocalId = 178]; /attributes[@nCI = 12]")); + + ScopeLogicalBlock NRCellDUCellLocalId = new ScopeLogicalBlock(ScopeObject.builder("NRCellDU").container( + ContainerType.ATTRIBUTES).leaf("cellLocalId").queryFunction(QueryFunction.EQ).parameter("178") + .resolverDataType(ResolverDataType.INTEGER).build()); + ScopeLogicalBlock NRCellCUCellLocalId = new ScopeLogicalBlock(ScopeObject.builder("NRCellCU").container( + ContainerType.ATTRIBUTES).leaf("cellLocalId").queryFunction(QueryFunction.EQ).parameter("178") + .resolverDataType(ResolverDataType.INTEGER).build()); + ScopeLogicalBlock NRCellDUnCI = new ScopeLogicalBlock(ScopeObject.builder("NRCellDU").container( + ContainerType.ATTRIBUTES).leaf("nCI").queryFunction(QueryFunction.EQ).parameter("12").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock NRCellCUnCI = new ScopeLogicalBlock(ScopeObject.builder("NRCellCU").container( + ContainerType.ATTRIBUTES).leaf("nCI").queryFunction(QueryFunction.EQ).parameter("12").resolverDataType( + ResolverDataType.INTEGER).build()); + + AndLogicalBlock NRCellDU = new AndLogicalBlock(); + NRCellDU.getChildren().add(NRCellDUnCI); + NRCellDU.getChildren().add(NRCellDUCellLocalId); + + AndLogicalBlock NRCellCU = new AndLogicalBlock(); + NRCellCU.getChildren().add(NRCellCUnCI); + NRCellCU.getChildren().add(NRCellCUCellLocalId); + + OrLogicalBlock or = new OrLogicalBlock(); + or.getChildren().add(NRCellCU); + or.getChildren().add(NRCellDU); + + TargetObject targetObjectResult9_1 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).isAllParamQueried(true).build(); + TargetObject targetObjectResult9_2 = TargetObject.builder("NRCellCU").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).isAllParamQueried(true).build(); + + List resultTargetObjects9_1 = new ArrayList<>(); + resultTargetObjects9_1.add(targetObjectResult9_1); + resultTargetObjects9_1.add(targetObjectResult9_2); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects9_1, filterCriteria.getTargets()); + Assertions.assertEquals(or, filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_10() { + //root:- + //Target:/attributes + //Scope:/attributes[nCI = 12]; /attributes[gNBId = 6] + //error no intersection in scope + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes")); + filterCriteria.setScope(scopeResolver.resolve(null, "/attributes[@nCI = 12]; /attributes[@gNBId = 6]")); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveWildCardObjectsInScopeAndTarget( + filterCriteria, "RAN", FilterCriteria.ResolvingTopologyObjectType.ENTITY)); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_11() { + //root:- + //Target:/attributes, /id + //Scope:/[id = "testId"]; /attributes[gNBId = 6] + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/attributes; /id")); + filterCriteria.setScope(scopeResolver.resolve(null, "/id[@id = \"testId\"]; /attributes[@gNBId = 6]")); + + ScopeLogicalBlock GNBCUUPFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder("GNBCUUPFunction").container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBDUFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBCUCPFunctionPgNBId = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ATTRIBUTES).leaf("gNBId").queryFunction(QueryFunction.EQ).parameter("6").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock GNBCUUPFunctionPid = new ScopeLogicalBlock(ScopeObject.builder("GNBCUUPFunction").container( + ContainerType.ID).queryFunction(QueryFunction.EQ).parameter("testId").resolverDataType( + ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBDUFunctionPid = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ID).queryFunction(QueryFunction.EQ).parameter("testId").resolverDataType( + ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBCUCPFunctionPid = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ID).queryFunction(QueryFunction.EQ).parameter("testId").resolverDataType( + ResolverDataType.STRING).build()); + + AndLogicalBlock GNBCUUPFunction = new AndLogicalBlock(); + GNBCUUPFunction.getChildren().add(GNBCUUPFunctionPgNBId); + GNBCUUPFunction.getChildren().add(GNBCUUPFunctionPid); + + AndLogicalBlock GNBDUFunction = new AndLogicalBlock(); + GNBDUFunction.getChildren().add(GNBDUFunctionPgNBId); + GNBDUFunction.getChildren().add(GNBDUFunctionPid); + + AndLogicalBlock GNBCUCPFunction = new AndLogicalBlock(); + GNBCUCPFunction.getChildren().add(GNBCUCPFunctionPgNBId); + GNBCUCPFunction.getChildren().add(GNBCUCPFunctionPid); + + OrLogicalBlock or1 = new OrLogicalBlock(); + OrLogicalBlock or2 = new OrLogicalBlock(); + + or1.getChildren().add(or2); + or1.getChildren().add(GNBDUFunction); + or2.getChildren().add(GNBCUCPFunction); + or2.getChildren().add(GNBCUUPFunction); + + TargetObject targetObjectResult11_1 = TargetObject.builder("GNBCUUPFunction").container(ContainerType.ID).build(); + TargetObject targetObjectResult11_2 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ID).build(); + TargetObject targetObjectResult11_3 = TargetObject.builder("GNBCUCPFunction").container(ContainerType.ID).build(); + TargetObject targetObjectResult11_4 = TargetObject.builder("GNBCUUPFunction").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + TargetObject targetObjectResult11_5 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + TargetObject targetObjectResult11_6 = TargetObject.builder("GNBCUCPFunction").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + List resultTargetObjects11_1 = new ArrayList<>(); + resultTargetObjects11_1.add(targetObjectResult11_4); + resultTargetObjects11_1.add(targetObjectResult11_5); + resultTargetObjects11_1.add(targetObjectResult11_6); + resultTargetObjects11_1.add(targetObjectResult11_1); + resultTargetObjects11_1.add(targetObjectResult11_2); + resultTargetObjects11_1.add(targetObjectResult11_3); + + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects11_1, filterCriteria.getTargets()); + Assertions.assertEquals(or1, filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_12() { + //root:- + //Target: /attributes + //Scope: /managed-by-managedElement[id = "me1"] + InnerFilterCriteria filterCriteria2 = InnerFilterCriteria.builder().build(); + filterCriteria2.setTargets(targetResolver.resolve(null, "/attributes")); + filterCriteria2.setScope(scopeResolver.resolve(null, "/managed-by-managedElement[@id = \"me1\"]")); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("OAM").filterCriteriaList(List + .of(filterCriteria2)).build()); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveWildCardObjectsInScopeAndTarget( + filterCriteria2, "OAM", FilterCriteria.ResolvingTopologyObjectType.ENTITY)); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_13() { + //root:- + //Target: /attributes + //Scope: /managed-by-managedElement[id = "me1"] + InnerFilterCriteria filterCriteria2 = InnerFilterCriteria.builder().build(); + filterCriteria2.setTargets(targetResolver.resolve(null, "/attributes")); + filterCriteria2.setScope(scopeResolver.resolve(null, "/managed-by-managedElement[@id = \"me1\"]")); + + TargetObject targetObjectResult13_1 = TargetObject.builder("GNBCUUPFunction").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + TargetObject targetObjectResult13_2 = TargetObject.builder("ENodeBFunction").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + TargetObject targetObjectResult13_3 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + TargetObject targetObjectResult13_4 = TargetObject.builder("GNBCUCPFunction").container(ContainerType.ATTRIBUTES) + .isAllParamQueried(true).build(); + List resultTargetObjectsResult13_1 = new ArrayList<>(); + resultTargetObjectsResult13_1.add(targetObjectResult13_1); + resultTargetObjectsResult13_1.add(targetObjectResult13_2); + resultTargetObjectsResult13_1.add(targetObjectResult13_3); + resultTargetObjectsResult13_1.add(targetObjectResult13_4); + + ScopeLogicalBlock GNBCUUPFunction = new ScopeLogicalBlock(ScopeObject.builder("GNBCUUPFunction").container( + ContainerType.ASSOCIATION).innerContainer(List.of("managed-by-managedElement")).leaf("id").queryFunction( + QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock ENodeBFunction = new ScopeLogicalBlock(ScopeObject.builder("ENodeBFunction").container( + ContainerType.ASSOCIATION).innerContainer(List.of("managed-by-managedElement")).leaf("id").queryFunction( + QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBDUFunction = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ASSOCIATION).innerContainer(List.of("managed-by-managedElement")).leaf("id").queryFunction( + QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBCUCPFunction = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ASSOCIATION).innerContainer(List.of("managed-by-managedElement")).leaf("id").queryFunction( + QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + + AndOrLogicalBlock or1 = new OrLogicalBlock(); + AndOrLogicalBlock or2 = new OrLogicalBlock(); + AndOrLogicalBlock or3 = new OrLogicalBlock(); + + or3.getChildren().add(ENodeBFunction); + or3.getChildren().add(GNBCUCPFunction); + or2.getChildren().add(or3); + or2.getChildren().add(GNBCUUPFunction); + or1.getChildren().add(or2); + or1.getChildren().add(GNBDUFunction); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("RAN").filterCriteriaList(List + .of(filterCriteria2)).build()); + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria2, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjectsResult13_1, filterCriteria2.getTargets()); + Assertions.assertEquals(or1, filterCriteria2.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_14() { + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, null)); + filterCriteria.setScope(scopeResolver.resolve(null, "/GNBDUFunction[@id = \"testId\"]")); + + TargetObject targetObjectResult9_1 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ID) + .isAllParamQueried(false).build(); + + List resultTargetObjects9_1 = new ArrayList<>(); + resultTargetObjects9_1.add(targetObjectResult9_1); + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("RAN").filterCriteriaList(List + .of(filterCriteria)).build()); + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.ENTITY); + + Assertions.assertEquals(resultTargetObjects9_1, filterCriteria.getTargets()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_15() { + InnerFilterCriteria filterCriteria = InnerFilterCriteria.builder().build(); + filterCriteria.setTargets(targetResolver.resolve(null, "/GNBDUFUNCTION_PROVIDES_NRCELLDU")); + filterCriteria.setScope(scopeResolver.resolve(null, "/id[text() = \"testId\"]")); + + ScopeObject scopeObject = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").container(ContainerType.ID) + .parameter("testId").queryFunction(QueryFunction.EQ).resolverDataType(ResolverDataType.STRING).build(); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("RAN").filterCriteriaList(List + .of(filterCriteria)).build()); + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria, "RAN", + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP); + + Assertions.assertEquals(new ScopeLogicalBlock(scopeObject), filterCriteria.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_16() { + //root:- + //Target: /decorators + //Scope: /managed-by-managedElement[id = "me1"] + InnerFilterCriteria filterCriteria2 = InnerFilterCriteria.builder().build(); + filterCriteria2.setTargets(targetResolver.resolve(null, + "/MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION/decorators; /MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/decorators")); + filterCriteria2.setScope(scopeResolver.resolve(null, "/managed-by-managedElement[@id = \"me1\"]")); + + TargetObject targetObjectResult13_1 = TargetObject.builder("MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION").container( + ContainerType.DECORATORS).build(); + TargetObject targetObjectResult13_2 = TargetObject.builder("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION").container( + ContainerType.DECORATORS).build(); + List resultTargetObjectsResult13_1 = new ArrayList<>(); + resultTargetObjectsResult13_1.add(targetObjectResult13_1); + resultTargetObjectsResult13_1.add(targetObjectResult13_2); + + ScopeLogicalBlock GNBCUCPFunction = new ScopeLogicalBlock(ScopeObject.builder( + "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION").container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock ENodeBFunction = new ScopeLogicalBlock(ScopeObject.builder( + "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION").container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + + AndOrLogicalBlock or1 = new OrLogicalBlock(); + + or1.getChildren().add(GNBCUCPFunction); + or1.getChildren().add(ENodeBFunction); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("RAN").filterCriteriaList(List + .of(filterCriteria2)).build()); + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria2, "RAN", + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP); + + Assertions.assertEquals(resultTargetObjectsResult13_1, filterCriteria2.getTargets()); + Assertions.assertEquals(or1, filterCriteria2.getScope()); + } + + @Test + void testResolveWildCardObjectsInScopeAndTarget_17() { + //root:- + //Target: /decorators + //Scope: /managed-by-managedElement[id = "me1"] + InnerFilterCriteria filterCriteria2 = InnerFilterCriteria.builder().build(); + filterCriteria2.setTargets(targetResolver.resolve(null, "/decorators")); + filterCriteria2.setScope(scopeResolver.resolve(null, "/managed-by-managedElement[@id = \"me1\"]")); + + TargetObject targetObjectResult13_1 = TargetObject.builder("MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION").container( + ContainerType.DECORATORS).build(); + TargetObject targetObjectResult13_2 = TargetObject.builder("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION").container( + ContainerType.DECORATORS).build(); + TargetObject targetObjectResult13_3 = TargetObject.builder("MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION").container( + ContainerType.DECORATORS).build(); + TargetObject targetObjectResult13_4 = TargetObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION").container( + ContainerType.DECORATORS).build(); + List resultTargetObjectsResult13_1 = new ArrayList<>(); + resultTargetObjectsResult13_1.add(targetObjectResult13_1); + resultTargetObjectsResult13_1.add(targetObjectResult13_2); + resultTargetObjectsResult13_1.add(targetObjectResult13_3); + resultTargetObjectsResult13_1.add(targetObjectResult13_4); + + ScopeLogicalBlock GNBCUUPFunction = new ScopeLogicalBlock(ScopeObject.builder( + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION").container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock ENodeBFunction = new ScopeLogicalBlock(ScopeObject.builder( + "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION").container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBDUFunction = new ScopeLogicalBlock(ScopeObject.builder("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION") + .container(ContainerType.ASSOCIATION).innerContainer(List.of("managed-by-managedElement")).leaf("id") + .queryFunction(QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock GNBCUCPFunction = new ScopeLogicalBlock(ScopeObject.builder( + "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION").container(ContainerType.ASSOCIATION).innerContainer(List.of( + "managed-by-managedElement")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + + AndOrLogicalBlock or1 = new OrLogicalBlock(); + AndOrLogicalBlock or2 = new OrLogicalBlock(); + AndOrLogicalBlock or3 = new OrLogicalBlock(); + + or3.getChildren().add(ENodeBFunction); + or3.getChildren().add(GNBCUCPFunction); + or2.getChildren().add(or3); + or2.getChildren().add(GNBCUUPFunction); + or1.getChildren().add(or2); + or1.getChildren().add(GNBDUFunction); + + basePathRefinement.processTopologyObjectsWithContainerTypeNull(FilterCriteria.builder("REL_OAM_RAN") + .filterCriteriaList(List.of(filterCriteria2)).build()); + basePathRefinement.resolveWildCardObjectsInScopeAndTarget(filterCriteria2, "REL_OAM_RAN", + FilterCriteria.ResolvingTopologyObjectType.RELATIONSHIP); + + Assertions.assertEquals(resultTargetObjectsResult13_1, filterCriteria2.getTargets()); + Assertions.assertEquals(or1, filterCriteria2.getScope()); } @Test void testResolveUndefinedTopologyObjects_Entity() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - TargetObject targetObject = TargetObject.builder("GNBDUFunction").build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject))); - ScopeObject scopeObject = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBId", QueryFunction.EQ, "1", - DataType.BIGINT); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + TargetObject targetObject = TargetObject.builder(GNBDU_FUNCTION).build(); + ScopeObject scopeObject = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); LogicalBlock scope = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scope); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject))).scope(scope).build())); try (MockedStatic utilities = Mockito.mockStatic(SchemaRegistry.class)) { - utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( - "GNBDUFunction", "NRCellDU")); - utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( + utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN")).thenReturn(Arrays.asList(GNBDU_FUNCTION, + "NRCellDU")); + utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN")).thenReturn(Arrays.asList( "GNBDUFUNCTION_PROVIDES_NRCELLDU")); - BasePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); + basePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); - Assertions.assertEquals(TopologyObjectType.ENTITY, filterCriteria.getTargets().get(0).getTopologyObjectType()); - Assertions.assertEquals(TopologyObjectType.ENTITY, ((ScopeLogicalBlock) filterCriteria.getScope()) - .getScopeObject().getTopologyObjectType()); + Assertions.assertEquals(TopologyObjectType.ENTITY, filterCriteria.getFilterCriteriaList().get(0).getTargets() + .get(0).getTopologyObjectType()); + Assertions.assertEquals(TopologyObjectType.ENTITY, ((ScopeLogicalBlock) filterCriteria.getFilterCriteriaList() + .get(0).getScope()).getScopeObject().getTopologyObjectType()); - filterCriteria.setScope(EmptyLogicalBlock.getInstance()); + filterCriteria.getFilterCriteriaList().get(0).setScope(EmptyLogicalBlock.getInstance()); targetObject.setTopologyObjectType(TopologyObjectType.UNDEFINED); - BasePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); + basePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); - Assertions.assertEquals(TopologyObjectType.ENTITY, filterCriteria.getTargets().get(0).getTopologyObjectType()); + Assertions.assertEquals(TopologyObjectType.ENTITY, filterCriteria.getFilterCriteriaList().get(0).getTargets() + .get(0).getTopologyObjectType()); } } @Test void testResolveUndefinedTopologyObjects_Relation() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); TargetObject targetObject = TargetObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject))); - ScopeObject scopeObject = new ScopeObject("GNBDUFUNCTION_PROVIDES_NRCELLDU", ContainerType.ID, QueryFunction.EQ, - "1", DataType.PRIMITIVE); + ScopeObject scopeObject = ScopeObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").container(ContainerType.ID) + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.PRIMITIVE).build(); LogicalBlock scope = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scope); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject))).scope(scope).build())); try (MockedStatic utilities = Mockito.mockStatic(SchemaRegistry.class)) { - utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( - "GNBDUFunction", "NRCellDU")); - utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( + utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN")).thenReturn(Arrays.asList(GNBDU_FUNCTION, + "NRCellDU")); + utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN")).thenReturn(Arrays.asList( "GNBDUFUNCTION_PROVIDES_NRCELLDU")); - BasePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); + basePathRefinement.resolveUndefinedTopologyObjectTypes(filterCriteria); - Assertions.assertEquals(TopologyObjectType.RELATION, filterCriteria.getTargets().get(0) - .getTopologyObjectType()); - Assertions.assertEquals(TopologyObjectType.RELATION, ((ScopeLogicalBlock) filterCriteria.getScope()) - .getScopeObject().getTopologyObjectType()); + Assertions.assertEquals(TopologyObjectType.RELATION, filterCriteria.getFilterCriteriaList().get(0).getTargets() + .get(0).getTopologyObjectType()); + Assertions.assertEquals(TopologyObjectType.RELATION, ((ScopeLogicalBlock) filterCriteria.getFilterCriteriaList() + .get(0).getScope()).getScopeObject().getTopologyObjectType()); } } @Test void testResolveUndefinedTopologyObjects_InvalidTargetAndScope() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); TargetObject targetObject = TargetObject.builder("InvalidObject").build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject))); - ScopeObject scopeObject = new ScopeObject("InvalidObject", ContainerType.ATTRIBUTES, "gNBId", QueryFunction.EQ, "1", - DataType.BIGINT); + ScopeObject scopeObject = ScopeObject.builder("InvalidObject").container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); LogicalBlock scope = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scope); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject))).scope(scope).build())); try (MockedStatic utilities = Mockito.mockStatic(SchemaRegistry.class)) { - utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( - "GNBDUFunction", "NRCellDU", "EntityAndRelation")); - utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN_LOGICAL")).thenReturn(Arrays.asList( + utilities.when(() -> SchemaRegistry.getEntityNamesByDomain("RAN")).thenReturn(Arrays.asList(GNBDU_FUNCTION, + "NRCellDU", "EntityAndRelation")); + utilities.when(() -> SchemaRegistry.getRelationNamesByDomain("RAN")).thenReturn(Arrays.asList( "GNBDUFUNCTION_PROVIDES_NRCELLDU", "EntityAndRelation")); // Error thrown because of invalid topology object in targetFilter - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.resolveUndefinedTopologyObjectTypes( + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveUndefinedTopologyObjectTypes( filterCriteria)); - targetObject.setTopologyObject("GNBDUFunction"); + targetObject.setTopologyObject(GNBDU_FUNCTION); // Error thrown because of invalid topology object in scopeFilter - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.resolveUndefinedTopologyObjectTypes( + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveUndefinedTopologyObjectTypes( filterCriteria)); scopeObject.setTopologyObject("EntityAndRelation"); // Error thrown because of topology object type is ambiguous - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.resolveUndefinedTopologyObjectTypes( + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveUndefinedTopologyObjectTypes( filterCriteria)); targetObject.setTopologyObjectType(TopologyObjectType.UNDEFINED); targetObject.setTopologyObject("EntityAndRelation"); // Error thrown because of topology object type is ambiguous - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.resolveUndefinedTopologyObjectTypes( + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.resolveUndefinedTopologyObjectTypes( filterCriteria)); } } @Test void testValidateContainers() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); - TargetObject targetObject0 = TargetObject.builder("GNBDUFunction").container(ContainerType.ID).params( + TargetObject targetObject0 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ID).params( new ArrayList<>(Arrays.asList("gNBId"))).build(); targetObject0.setTopologyObjectType(TopologyObjectType.ENTITY); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject0))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject0))).build())); // Reason: container:ID, params is not empty - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); - TargetObject targetObject1 = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).params( + TargetObject targetObject1 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).params( new ArrayList<>(Arrays.asList("gNBId", "gNBIdLength", "notValidAttribute1", "notValidAttribute2"))).build(); targetObject1.setTopologyObjectType(TopologyObjectType.ENTITY); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject1))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(List.of(targetObject1)) + .build())); + + ScopeObject scopeObject = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); - ScopeObject scopeObject = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBId", QueryFunction.EQ, "1", - DataType.BIGINT); scopeObject.setTopologyObjectType(TopologyObjectType.ENTITY); LogicalBlock scopeLogicalBlock = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scopeLogicalBlock); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1))).scope(scopeLogicalBlock).build())); // Reason: invalid attributes in ENTITY type targetObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); TargetObject targetObject2 = TargetObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").container( ContainerType.ATTRIBUTES).topologyObjectType(TopologyObjectType.RELATION).params(new ArrayList<>(Arrays .asList("notValidAttribute1", "notValidAttribute2"))).build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject2))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject2))).scope(scopeLogicalBlock).build())); // Reason: invalid attributes in RELATION type targetObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setLeaf("notValidAttribute"); - TargetObject targetObject3 = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES) + TargetObject targetObject3 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES) .topologyObjectType(TopologyObjectType.ENTITY).params(new ArrayList<>(Arrays.asList("gNBId", "gNBIdLength"))).build(); targetObject3.setTopologyObjectType(TopologyObjectType.ENTITY); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject3))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject3))).scope(scopeLogicalBlock).build())); // Reason: invalid attributes in ENTITY type scopeObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setLeaf("gNBId"); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); - TargetObject targetObject4 = TargetObject.builder("GNBDUFunction").container(ContainerType.SOURCE_IDS) + TargetObject targetObject4 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.SOURCE_IDS) .topologyObjectType(TopologyObjectType.ENTITY).params(new ArrayList<>(Arrays.asList("gNBId"))).build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject4))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject4))).scope(scopeLogicalBlock).build())); // Reason: invalid source id param for ENTITY type targetObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); targetObject4.setParams(Collections.emptyList()); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); TargetObject targetObject5 = TargetObject.builder("GNBDUFUNCTION_PROVIDES_NRCELLDU").container( ContainerType.SOURCE_IDS).topologyObjectType(TopologyObjectType.RELATION).params(new ArrayList<>(Arrays .asList("InvalidSourceIdParam"))).build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject5))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject5))).scope(scopeLogicalBlock).build())); // Reason: invalid source id param for RELATION type targetObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); - targetObject5.setParams(new ArrayList<>(Arrays.asList(ITEMS))); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + targetObject5.setParams(new ArrayList<>(Arrays.asList(ITEM))); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); } @Test void testValidateContainers_Associations() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - ScopeObject scopeObject = new ScopeObject("GNBDUFunction", ContainerType.ASSOCIATION, "nCI", QueryFunction.EQ, "1", - DataType.BIGINT); - scopeObject.setInnerContainer(Arrays.asList("provided-by-gnbduFunction")); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + ScopeObject scopeObject = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ASSOCIATION).leaf("nCI") + .queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + scopeObject.setInnerContainer(Arrays.asList("provided-nrCellDu")); scopeObject.setTopologyObjectType(TopologyObjectType.ENTITY); LogicalBlock scopeLogicalBlock = new ScopeLogicalBlock(scopeObject); - filterCriteria.setScope(scopeLogicalBlock); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(List.of()).scope( + scopeLogicalBlock).build())); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setLeaf(null); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setLeaf("invalid"); // Reason: invalid leaf for scopeObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setLeaf("nCI"); scopeObject.setInnerContainer(Arrays.asList("invalid-association")); // Reason: invalid association added in innerContainer list for ENTITY type scopeObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setInnerContainer(Collections.emptyList()); // Reason: no association name added in innerContainer list for scopeObject in case of association containerType - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setTopologyObject("GNBDUFUNCTION_PROVIDES_NRCELLDU"); scopeObject.setTopologyObjectType(TopologyObjectType.RELATION); - scopeObject.setInnerContainer(Arrays.asList("provided-by-gnbduFunction")); + scopeObject.setInnerContainer(Arrays.asList("provided-nrCellDu")); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setTopologyObjectType(TopologyObjectType.UNDEFINED); // Reason: cannot validate container for UNDEFINED type topologyObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); scopeObject.setTopologyObjectType(TopologyObjectType.RELATION); scopeObject.setInnerContainer(Arrays.asList("invalid-association")); // Reason: invalid association added in innerContainer list for RELATION type scopeObject - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.validateContainers(filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateContainers(filterCriteria)); } @Test void testValidateScopeParametersDataType() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - Assertions.assertThrows(NotImplementedException.class, () -> BasePathRefinement.validateScopeParametersDataType( + // for gNBId attribute the BIGINT dataType is set + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + LogicalBlock logicalBlock1 = scopeResolver.process(GNBDU_FUNCTION, "/attributes[@gNBId=21]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock1).build())); + + basePathRefinement.validateScopeParametersDataType(filterCriteria); + Assertions.assertEquals(DataType.BIGINT, ((ScopeLogicalBlock) logicalBlock1).getScopeObject().getDataType()); + + // error reason: for gNBId attribute string value is not accepted + LogicalBlock logicalBlock2 = scopeResolver.process(GNBDU_FUNCTION, "/attributes[@gNBId='abc']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock2).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // error reason: id value should be entered as string (' ') + LogicalBlock logicalBlock3 = scopeResolver.process(GNBDU_FUNCTION, "/GNBDUFunction[@id=1]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock3).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // scopeFilter: /managed-by-managedElement[@id='me1'] -> dataType is set to PRIMITIVE + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).innerContainer( + new ArrayList<>(Arrays.asList("managed-by-managedElement"))).container(ContainerType.ASSOCIATION) + .topologyObjectType(TopologyObjectType.ENTITY).queryFunction(QueryFunction.EQ).leaf(ID_COLUMN_NAME) + .parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(scopeLogicalBlock1).build())); + + basePathRefinement.validateScopeParametersDataType(filterCriteria); + + Assertions.assertEquals(DataType.PRIMITIVE, scopeLogicalBlock1.getScopeObject().getDataType()); + + // error reason: scopeFilter: /managed-by-managedElement[@id=1] -> ResolverDataType is INTEGER, but in case of id it should be STRING + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).innerContainer( + new ArrayList<>(Arrays.asList("managed-by-managedElement"))).container(ContainerType.ASSOCIATION) + .topologyObjectType(TopologyObjectType.ENTITY).queryFunction(QueryFunction.EQ).leaf(ID_COLUMN_NAME) + .parameter("1").resolverDataType(ResolverDataType.INTEGER).build()); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(scopeLogicalBlock2).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // error reason: scopeFilter: /provided-nrCellDu[@cellLocalId=1] -> only id can be queried for associations + ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).innerContainer( + new ArrayList<>(Arrays.asList("provided-nrCellDu"))).container(ContainerType.ASSOCIATION) + .topologyObjectType(TopologyObjectType.ENTITY).queryFunction(QueryFunction.EQ).leaf("cellLocalId") + .parameter("1").resolverDataType(ResolverDataType.INTEGER).build()); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(scopeLogicalBlock3).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // for id the PRIMITIVE dataType is set + LogicalBlock logicalBlock4 = scopeResolver.process(GNBDU_FUNCTION, "/GNBDUFunction[@id='gnbdu1']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock4).build())); + + basePathRefinement.validateScopeParametersDataType(filterCriteria); + Assertions.assertEquals(DataType.PRIMITIVE, ((ScopeLogicalBlock) logicalBlock4).getScopeObject().getDataType()); + + // error reason: for id INTEGER ResolverDataType is not accepted + LogicalBlock logicalBlock5 = scopeResolver.process(GNBDU_FUNCTION, "/GNBDUFunction[@id=1]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock5).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // error reason: for gNBCUName attribute INTEGER ResolverDataType is not accepted + LogicalBlock logicalBlock6 = scopeResolver.process("GNBCUCPFunction", "/attributes[@gNBCUName=1]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock6).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + // for sourceIds container PRIMITIVE dataType is set + LogicalBlock logicalBlock7 = scopeResolver.process(GNBDU_FUNCTION, "/sourceIds[@items = 'someSourceId']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock7).build())); + + basePathRefinement.validateScopeParametersDataType(filterCriteria); + + Assertions.assertEquals(DataType.PRIMITIVE, scopeLogicalBlock1.getScopeObject().getDataType()); + + // error reason: for sourceIds container INTEGER dataType is not accepted + LogicalBlock logicalBlock8 = scopeResolver.process(GNBDU_FUNCTION, "/sourceIds[@items = 1]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock8).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( filterCriteria)); + + // for decorators container PRIMITIVE dataType is accepted + LogicalBlock logicalBlock9 = scopeResolver.process(GNBDU_FUNCTION, "/decorators[@module-x:stringdata = 'ORAN']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock9).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); + + // for decorators container INTEGER dataType is accepted + LogicalBlock logicalBlock10 = scopeResolver.process(GNBDU_FUNCTION, "/decorators[@module-x:intdata = 2]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock10).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); + + LogicalBlock logicalBlock11 = scopeResolver.process(GNBDU_FUNCTION, + "/decorators[contains(@gnbdu-function-model:location, 'Stock')]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock11).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); + + //For classifiers container PRIMITIVE dataType is accepted + LogicalBlock logicalBlock12 = scopeResolver.process(GNBDU_FUNCTION, + "/classifiers[@item = 'gnbdu-function-model:Rural']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock12).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); + + //For classifiers container INTEGER dataType is NOT accepted + LogicalBlock logicalBlock13 = scopeResolver.process(GNBDU_FUNCTION, "/classifiers[@item = 23 ]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock13).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateScopeParametersDataType( + filterCriteria)); + + //for complex attribute INTEGER is accepted + LogicalBlock logicalBlock14 = scopeResolver.process(GNBDU_FUNCTION, "/attributes/dUpLMNId[@mnc = 2]"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock14).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); + + //for complex attribute PRIMITIVE is accepted + LogicalBlock logicalBlock15 = scopeResolver.process(GNBDU_FUNCTION, "/attributes/dUpLMNId[@mnc = 'some value']"); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(logicalBlock15).build())); + + Assertions.assertDoesNotThrow(() -> basePathRefinement.validateScopeParametersDataType(filterCriteria)); } @Test void testCheckIfTargetMatchesWithScope() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - TargetObject targetObject1 = TargetObject.builder("GNBDUFunction").container(ContainerType.ATTRIBUTES).params(List + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + TargetObject targetObject1 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).params(List .of("gNBId", "gNBIdLength")).build(); TargetObject targetObject2 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).params(List.of( "nCI")).build(); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject1, targetObject2))); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1, targetObject2))).build())); OrLogicalBlock orLogicalBlock1 = new OrLogicalBlock(); - ScopeObject scopeObject1 = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBIdLength", - QueryFunction.EQ, "1", DataType.BIGINT); - ScopeObject scopeObject2 = new ScopeObject("GNBDUFunction", ContainerType.ATTRIBUTES, "gNBId", QueryFunction.EQ, - "8", DataType.BIGINT); + + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).leaf( + "gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1").dataType(DataType.BIGINT).build(); + ScopeObject scopeObject2 = ScopeObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).leaf("gNBId") + .queryFunction(QueryFunction.EQ).parameter("8").dataType(DataType.BIGINT).build(); ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(scopeObject1); ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(scopeObject2); orLogicalBlock1.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock1, scopeLogicalBlock2))); - filterCriteria.setScope(orLogicalBlock1); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1, targetObject2))).scope(orLogicalBlock1).build())); - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.checkIfTargetMatchesWithScope( - filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.checkIfTargetMatchesWithScope( + filterCriteria.getFilterCriteriaList().get(0), filterCriteria.getDomain())); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1))).scope(orLogicalBlock1).build())); - filterCriteria.setTargets(new ArrayList<>(Arrays.asList(targetObject1))); + Assertions.assertDoesNotThrow(() -> basePathRefinement.checkIfTargetMatchesWithScope(filterCriteria + .getFilterCriteriaList().get(0), filterCriteria.getDomain())); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.checkIfTargetMatchesWithScope(filterCriteria)); + ScopeObject scopeObject3 = ScopeObject.builder("NRSectorCarrier").container(ContainerType.ATTRIBUTES).leaf( + "arfcnUL").queryFunction(QueryFunction.EQ).parameter("8").dataType(DataType.BIGINT).build(); - ScopeObject scopeObject3 = new ScopeObject("NRSectorCarrier", ContainerType.ATTRIBUTES, "arfcnUL", QueryFunction.EQ, - "8", DataType.BIGINT); ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(scopeObject3); - filterCriteria.setScope(scopeLogicalBlock3); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1))).scope(scopeLogicalBlock3).build())); - Assertions.assertThrows(TiesPathException.class, () -> BasePathRefinement.checkIfTargetMatchesWithScope( - filterCriteria)); + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.checkIfTargetMatchesWithScope( + filterCriteria.getFilterCriteriaList().get(0), filterCriteria.getDomain())); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(Collections.emptyList()).scope( + scopeLogicalBlock3).build())); - filterCriteria.setTargets(Collections.emptyList()); + Assertions.assertDoesNotThrow(() -> basePathRefinement.checkIfTargetMatchesWithScope(filterCriteria + .getFilterCriteriaList().get(0), filterCriteria.getDomain())); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.checkIfTargetMatchesWithScope(filterCriteria)); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(Collections.emptyList()).scope( + EmptyLogicalBlock.getInstance()).build())); - filterCriteria.setScope(EmptyLogicalBlock.getInstance()); + Assertions.assertDoesNotThrow(() -> basePathRefinement.checkIfTargetMatchesWithScope(filterCriteria + .getFilterCriteriaList().get(0), filterCriteria.getDomain())); - Assertions.assertDoesNotThrow(() -> BasePathRefinement.checkIfTargetMatchesWithScope(filterCriteria)); + } + @Test + void testSplitFilterCriteria() { + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + TargetObject targetObject1 = TargetObject.builder(GNBDU_FUNCTION).container(ContainerType.ATTRIBUTES).params(List + .of("gNBId", "gNBIdLength")).build(); + TargetObject targetObject2 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).params(List.of( + "nCI")).build(); + TargetObject targetObject3 = TargetObject.builder("NRCellDU").container(ContainerType.ATTRIBUTES).params(List.of( + "nRPCI")).build(); + TargetObject targetObject4 = TargetObject.builder("EUtranCell").container(ContainerType.ATTRIBUTES).params(List.of( + "earFcn", "fdn")).isAllParamQueried(true).build(); + + ScopeObject scopeObject1 = ScopeObject.builder(GNBDU_FUNCTION).leaf("leaf1").build(); + ScopeObject scopeObject2 = ScopeObject.builder("NRCellDU").leaf("leaf1").build(); + ScopeObject scopeObject3 = ScopeObject.builder("EUtranCell").leaf("leaf1").build(); + ScopeObject scopeObject4 = ScopeObject.builder(GNBDU_FUNCTION).leaf("leaf2").build(); + ScopeObject scopeObject5 = ScopeObject.builder("NRCellDU").leaf("leaf2").build(); + ScopeObject scopeObject6 = ScopeObject.builder("EUtranCell").leaf("leaf2").build(); + + OrLogicalBlock or1 = new OrLogicalBlock(); + AndLogicalBlock and1 = new AndLogicalBlock(); + AndLogicalBlock and2 = new AndLogicalBlock(); + OrLogicalBlock or2 = new OrLogicalBlock(); + OrLogicalBlock or3 = new OrLogicalBlock(); + + or1.getChildren().add(or2); + or1.getChildren().add(and1); + and1.getChildren().add(and2); + and2.getChildren().add(or3); + or2.getChildren().add(new ScopeLogicalBlock(scopeObject1)); + or2.getChildren().add(new ScopeLogicalBlock(scopeObject2)); + and1.getChildren().add(new ScopeLogicalBlock(scopeObject3)); + and2.getChildren().add(new ScopeLogicalBlock(scopeObject4)); + or3.getChildren().add(new ScopeLogicalBlock(scopeObject5)); + or3.getChildren().add(new ScopeLogicalBlock(scopeObject6)); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().targets(new ArrayList<>(Arrays.asList( + targetObject1, targetObject2, targetObject3, targetObject4))).scope(or1).build())); + + basePathRefinement.splitFilterCriteria(filterCriteria); + + OrLogicalBlock fc1or1 = new OrLogicalBlock(); + + fc1or1.getChildren().add(new ScopeLogicalBlock(scopeObject1)); + fc1or1.getChildren().add(new ScopeLogicalBlock(scopeObject4)); + + OrLogicalBlock fc2or1 = new OrLogicalBlock(); + + fc2or1.getChildren().add(new ScopeLogicalBlock(scopeObject2)); + fc2or1.getChildren().add(new ScopeLogicalBlock(scopeObject5)); + + AndLogicalBlock fc3and1 = new AndLogicalBlock(); + fc3and1.getChildren().add(new ScopeLogicalBlock(scopeObject6)); + fc3and1.getChildren().add(new ScopeLogicalBlock(scopeObject3)); + + InnerFilterCriteria innerFilterCriteria1 = InnerFilterCriteria.builder().targets(List.of(targetObject1)).scope( + fc1or1).build(); + InnerFilterCriteria innerFilterCriteria2 = InnerFilterCriteria.builder().targets(List.of(targetObject2, + targetObject3)).scope(fc2or1).build(); + InnerFilterCriteria innerFilterCriteria3 = InnerFilterCriteria.builder().targets(List.of(targetObject4)).scope( + fc3and1).build(); + + Assertions.assertEquals(Set.of(innerFilterCriteria1, innerFilterCriteria2, innerFilterCriteria3), new HashSet<>( + filterCriteria.getFilterCriteriaList())); } @Test void testValidateQuery() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); - Assertions.assertThrows(NotImplementedException.class, () -> BasePathRefinement.validateQuery(filterCriteria)); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(null); + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder("NRCellDU").build()); + ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(ScopeObject.builder("NRSectorCarrier").build()); + ScopeLogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(null); + ScopeLogicalBlock scopeLogicalBlock5 = new ScopeLogicalBlock(null); + ScopeLogicalBlock scopeLogicalBlock6 = new ScopeLogicalBlock(null); + AndOrLogicalBlock orLogicalBlock1 = new OrLogicalBlock(); + AndOrLogicalBlock orLogicalBlock2 = new OrLogicalBlock(); + AndOrLogicalBlock orLogicalBlock3 = new OrLogicalBlock(); + AndOrLogicalBlock andLogicalBlock1 = new AndLogicalBlock(); + AndOrLogicalBlock andLogicalBlock2 = new AndLogicalBlock(); + + orLogicalBlock1.setChildren(new ArrayList<>(Arrays.asList(orLogicalBlock2, andLogicalBlock1))); + orLogicalBlock2.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock1, andLogicalBlock2))); + andLogicalBlock2.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock2, scopeLogicalBlock3))); + andLogicalBlock1.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock4, orLogicalBlock3))); + orLogicalBlock3.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock5, scopeLogicalBlock6))); + + scopeLogicalBlock1.setValid(false); + scopeLogicalBlock4.setValid(false); + scopeLogicalBlock6.setValid(false); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(orLogicalBlock1).build())); + + basePathRefinement.validateQuery(filterCriteria); + + Assertions.assertEquals(andLogicalBlock2, filterCriteria.getFilterCriteriaList().get(0).getScope()); + + ScopeLogicalBlock scopeLogicalBlock2_1 = new ScopeLogicalBlock(null); + ScopeLogicalBlock scopeLogicalBlock2_2 = new ScopeLogicalBlock(null); + AndOrLogicalBlock andLogicalBlock2_1 = new AndLogicalBlock(); + + scopeLogicalBlock2_1.setValid(false); + + andLogicalBlock2_1.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock2_1, scopeLogicalBlock2_2))); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(andLogicalBlock2_1).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateQuery(filterCriteria)); + + ScopeLogicalBlock scopeLogicalBlock3_1 = new ScopeLogicalBlock(null); + ScopeLogicalBlock scopeLogicalBlock3_2 = new ScopeLogicalBlock(null); + AndOrLogicalBlock orLogicalBlock3_1 = new OrLogicalBlock(); + + scopeLogicalBlock3_2.setValid(false); + scopeLogicalBlock3_1.setValid(false); + + orLogicalBlock3_1.setChildren(new ArrayList<>(Arrays.asList(scopeLogicalBlock3_1, scopeLogicalBlock3_2))); + + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(orLogicalBlock3_1).build())); + + Assertions.assertThrows(TiesPathException.class, () -> basePathRefinement.validateQuery(filterCriteria)); } @Test void testRunOnTree() { - FilterCriteria filterCriteria = new FilterCriteria("RAN_LOGICAL"); + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").build(); OrLogicalBlock orLogicalBlock = new OrLogicalBlock(); - filterCriteria.setScope(orLogicalBlock); + filterCriteria.setFilterCriteriaList(List.of(InnerFilterCriteria.builder().scope(orLogicalBlock).build())); OrLogicalBlock orLogicalBlockChild1 = new OrLogicalBlock(); OrLogicalBlock orLogicalBlockChild2 = new OrLogicalBlock(); - LogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, - "gNBIdLength", QueryFunction.EQ, "1", DataType.BIGINT)); - LogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, - "gNBIdLength", QueryFunction.EQ, "2", DataType.BIGINT)); - LogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, - "gNBIdLength", QueryFunction.EQ, "3", DataType.BIGINT)); - LogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, - "gNBIdLength", QueryFunction.EQ, "4", DataType.BIGINT)); + LogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("1").dataType( + DataType.BIGINT).build()); + LogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("2").dataType( + DataType.BIGINT).build()); + LogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("3").dataType( + DataType.BIGINT).build()); + LogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(ScopeObject.builder(GNBDU_FUNCTION).container( + ContainerType.ATTRIBUTES).leaf("gNBIdLength").queryFunction(QueryFunction.EQ).parameter("4").dataType( + DataType.BIGINT).build()); orLogicalBlockChild1.setChildren(Arrays.asList(scopeLogicalBlock1, scopeLogicalBlock2)); orLogicalBlockChild2.setChildren(Arrays.asList(scopeLogicalBlock3, scopeLogicalBlock4)); orLogicalBlock.setChildren(Arrays.asList(orLogicalBlockChild1, orLogicalBlockChild2)); - BasePathRefinement.runOnTree(orLogicalBlock, filterCriteria.getDomain(), (ScopeLogicalBlock lb, String domain) -> lb + basePathRefinement.runOnTree(orLogicalBlock, filterCriteria.getDomain(), (ScopeLogicalBlock lb, String domain) -> lb .getScopeObject().setParameter("0")); Assertions.assertEquals("0", ((ScopeLogicalBlock) scopeLogicalBlock1).getScopeObject().getParameter()); diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinementTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinementTest.java index 95eaecf..4051be4 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinementTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/refiner/PathToJooqRefinementTest.java @@ -20,28 +20,70 @@ */ package org.oran.smo.teiv.exposure.tiespath.refiner; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.InnerFilterCriteria; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.QueryFunction; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeLogicalBlock; -import org.oran.smo.teiv.exposure.tiespath.innerlanguage.FilterCriteria; import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeObject; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TargetObject; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.TopologyObjectType; import org.oran.smo.teiv.schema.DataType; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.apache.commons.lang3.NotImplementedException; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; -public class PathToJooqRefinementTest { - @Test - void toJooqTest() { - Assertions.assertThrows(NotImplementedException.class, () -> PathToJooqRefinement.toJooq(new FilterCriteria( - "RAN_LOGICAL"))); +class PathToJooqRefinementTest { + + @BeforeAll + static void setUp() throws SchemaLoaderException { + new MockSchemaLoader().loadSchemaRegistry(); } @Test - void logicalBlockToJooqTest() { - ScopeObject scopeObject = new ScopeObject("GNDBUFunction", ContainerType.ATTRIBUTES, "gNBIdLength", - QueryFunction.EQ, "1", DataType.BIGINT); - Assertions.assertThrows(NotImplementedException.class, () -> PathToJooqRefinement.logicalBlockToJooq( - new ScopeLogicalBlock(scopeObject))); + void basicToJooqTest() { + FilterCriteria filterCriteria = FilterCriteria.builder("RAN").filterCriteriaList(List.of(InnerFilterCriteria + .builder().targets(List.of(TargetObject.builder("GNBDUFunction").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ATTRIBUTES).params(List.of("gNBDUId")).build())) + .scope(new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").topologyObjectType( + TopologyObjectType.ENTITY).container(ContainerType.ID).dataType(DataType.PRIMITIVE).parameter("123") + .queryFunction(QueryFunction.EQ).build())).build())).build(); + + //spotless:off + Assertions.assertEquals("(\n" + + " select\n" + + " null \"o-ran-smo-teiv-ran:GNBDUFunction.id\",\n" + + " null::bigint \"o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId\",\n" + + " (\n" + + " select count(*)\n" + + " from (\n" + + " select ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" \"o-ran-smo-teiv-ran:GNBDUFunction.id\"\n" + + " from ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"\n" + + " where ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" = '123'\n" + + " ) \"alias_87147237\"\n" + + " ) \"count\"\n" + + ")\n" + + "union all (\n" + + " select\n" + + " \"o-ran-smo-teiv-ran:GNBDUFunction.id\",\n" + + " \"o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId\",\n" + + " null \"count\"\n" + + " from (\n" + + " select\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" \"o-ran-smo-teiv-ran:GNBDUFunction.id\",\n" + + " ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"gNBDUId\" \"o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId\"\n" + + " from ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"\n" + + " where ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\".\"id\" = '123'\n" + + " order by \"o-ran-smo-teiv-ran:GNBDUFunction.id\" asc\n" + + " ) \"alias_49572850\"\n" + + " limit 100\n" + + " offset 0\n" + + ")", PathToJooqRefinement.toJooq(filterCriteria,0,100).toString()); + //spotless:on } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolverTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolverTest.java new file mode 100644 index 0000000..72badc0 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/ScopeResolverTest.java @@ -0,0 +1,284 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.tiespath.resolver; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.AndOrLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ContainerType; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.EmptyLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.LogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.OrLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.QueryFunction; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeLogicalBlock; +import org.oran.smo.teiv.exposure.tiespath.innerlanguage.ScopeObject; +import org.oran.smo.teiv.utils.query.exception.TiesPathException; + +class ScopeResolverTest { + + private final ScopeResolver scopeResolver = new ScopeResolver(); + + @Test + void testEmptyScope() { + LogicalBlock expected = EmptyLogicalBlock.getInstance(); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, null); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void resolveScopeWithMultipleTokensWithSameContainer() { + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("gnBId").queryFunction(QueryFunction.EQ).parameter("1").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("date").queryFunction(QueryFunction.EQ).parameter("2").resolverDataType( + ResolverDataType.STRING).build()); + ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("refs").queryFunction(QueryFunction.EQ).parameter("12341").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(ScopeObject.builder("*").container( + ContainerType.ATTRIBUTES).leaf("fdn").queryFunction(QueryFunction.CONTAINS).parameter("GNBDUFunction=10") + .resolverDataType(ResolverDataType.STRING).build()); + AndOrLogicalBlock logicalBlock1 = new AndLogicalBlock(); + AndOrLogicalBlock logicalBlock2 = new OrLogicalBlock(); + AndOrLogicalBlock logicalBlock3 = new AndLogicalBlock(); + logicalBlock1.addChild(scopeLogicalBlock1); + logicalBlock1.addChild(scopeLogicalBlock2); + logicalBlock2.addChild(logicalBlock1); + logicalBlock2.addChild(scopeLogicalBlock3); + logicalBlock3.addChild(scopeLogicalBlock4); + logicalBlock3.addChild(logicalBlock2); + final LogicalBlock resolverLB = scopeResolver.resolve(null, + "/GNBDUFunction/attributes[@gnBId = 1 and @date = \"2\" or @refs = 12341];/attributes[contains(@fdn,\"'GNBDUFunction=10'\")]"); + Assertions.assertEquals(logicalBlock3, resolverLB); + } + + @Test + void resolveScopeWithMultipleTokensWithDifferentContainers() { + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("gnBId").queryFunction(QueryFunction.EQ).parameter("1").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("date").queryFunction(QueryFunction.EQ).parameter("2").resolverDataType( + ResolverDataType.STRING).build()); + ScopeLogicalBlock scopeLogicalBlock3 = new ScopeLogicalBlock(ScopeObject.builder("GNBDUFunction").container( + ContainerType.ATTRIBUTES).leaf("refs").queryFunction(QueryFunction.EQ).parameter("12341").resolverDataType( + ResolverDataType.INTEGER).build()); + ScopeLogicalBlock scopeLogicalBlock4 = new ScopeLogicalBlock(ScopeObject.builder("*").container( + ContainerType.DECORATORS).leaf("vendor").queryFunction(QueryFunction.CONTAINS).parameter("ORAN") + .resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock scopeLogicalBlock5 = new ScopeLogicalBlock(ScopeObject.builder("*").container( + ContainerType.CLASSIFIERS).leaf("item").queryFunction(QueryFunction.EQ).parameter("cmHandle") + .resolverDataType(ResolverDataType.STRING).build()); + ScopeLogicalBlock scopeLogicalBlock6 = new ScopeLogicalBlock(ScopeObject.builder("*").container( + ContainerType.SOURCE_IDS).leaf("item").queryFunction(QueryFunction.EQ).parameter("fdn1").resolverDataType( + ResolverDataType.STRING).build()); + AndOrLogicalBlock logicalBlock1 = new AndLogicalBlock(); + AndOrLogicalBlock logicalBlock2 = new OrLogicalBlock(); + AndOrLogicalBlock logicalBlock3 = new OrLogicalBlock(); + AndOrLogicalBlock logicalBlock4 = new AndLogicalBlock(); + AndOrLogicalBlock logicalBlock5 = new OrLogicalBlock(); + logicalBlock1.addChild(scopeLogicalBlock1); + logicalBlock1.addChild(scopeLogicalBlock2); + logicalBlock2.addChild(logicalBlock1); + logicalBlock2.addChild(scopeLogicalBlock3); + logicalBlock3.addChild(logicalBlock2); + logicalBlock3.addChild(scopeLogicalBlock4); + logicalBlock4.addChild(scopeLogicalBlock5); + logicalBlock4.addChild(logicalBlock3); + logicalBlock5.addChild(scopeLogicalBlock6); + logicalBlock5.addChild(logicalBlock4); + + final LogicalBlock resolverLB = scopeResolver.resolve(null, + "/decorators[contains(@vendor, 'ORAN')]|/GNBDUFunction/attributes[@gnBId = 1 and @date = '2' or @refs = 12341] ; " + "/classifiers[@item = 'cmHandle']| /sourceIds[@item = 'fdn1']"); + Assertions.assertEquals(logicalBlock5, resolverLB, + "If in test failure contents are identical then check if AndLB/OrLB are used appropriately"); + } + + @Test + void testRelationshipInScope() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ManagedElement").container(null) + .innerContainer(List.of("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION")).leaf(null).queryFunction( + QueryFunction.NOT_NULL).parameter(null).resolverDataType(ResolverDataType.NOT_NULL).build()); + final LogicalBlock logicalBlock = scopeResolver.resolve("ManagedElement", "/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); + Assertions.assertEquals(expected, logicalBlock); + } + + @Test + void testNoLeavesInScope() { + ScopeLogicalBlock scopeLogicalBlock1 = new ScopeLogicalBlock(ScopeObject.builder("ENodeBFunction").container(null) + .innerContainer(List.of("managed-by-managedObject")).leaf(null).queryFunction(QueryFunction.NOT_NULL) + .parameter(null).resolverDataType(ResolverDataType.NOT_NULL).build()); + ScopeLogicalBlock scopeLogicalBlock2 = new ScopeLogicalBlock(ScopeObject.builder(null).container(null) + .innerContainer(List.of("managed-by-managedObject")).leaf("id").queryFunction(QueryFunction.EQ).parameter( + "me1").resolverDataType(ResolverDataType.STRING).build()); + AndOrLogicalBlock logicalBlock = new AndLogicalBlock(); + logicalBlock.addChild(scopeLogicalBlock1); + logicalBlock.addChild(scopeLogicalBlock2); + final LogicalBlock actualLogicalBlock = scopeResolver.resolve(null, + "/managed-by-managedObject[@id='me1']; /ENodeBFunction/managed-by-managedObject"); + Assertions.assertEquals(logicalBlock, actualLogicalBlock); + } + + @Test + void testResolveAssociationWithoutRootObjectInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder(null).container(null).innerContainer(List.of( + "managed-by-managedObject")).leaf("id").queryFunction(QueryFunction.EQ).parameter("me1").resolverDataType( + ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, "/managed-by-managedObject[@id='me1']"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testEqualTextFunction() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("*").container(ContainerType.ID).leaf(null) + .queryFunction(QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, "/id[text()='me1']"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testContainsTxtFunctionCondition() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("*").container(ContainerType.ID).leaf(null) + .queryFunction(QueryFunction.CONTAINS).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, "/id[contains(text(),'me1')]"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testExceptionWhenTextConditionUsedOnOtherThanID() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> scopeResolver.resolve(null, + "/ManagedElement[text()='me1']")); + assertEquals("text() is supported for ID only", thrown.getDetails()); + } + + @Test + void testResolveWithRootObjectAndAssociationInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ENodeBFunction").container(null) + .innerContainer(List.of("managed-by-managedObject")).leaf("id").queryFunction(QueryFunction.EQ).parameter( + "me1").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve("ENodeBFunction", "/managed-by-managedObject[@id='me1']"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testResolveWithRootObjectAndEntityInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ManagedElement").container(null) + .innerContainer(List.of("GNBDUFunction")).leaf("id").queryFunction(QueryFunction.CONTAINS).parameter("me1") + .resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve("ManagedElement", "/GNBDUFunction[contains(@id,'me1')]"); + Assertions.assertEquals(expected, resolvedScope); + + } + + @Test + void testResolveObjectWithTopologyObjectInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ManagedElement").container(ContainerType.ID) + .queryFunction(QueryFunction.EQ).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve("ManagedElement", "/ManagedElement[@id='me1']"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testResolveComplexAttributeInScopeFilter() { + //Without root object & Entity type provided in the container + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ATTRIBUTES).innerContainer(List.of("pLMNId")).leaf("mcc").queryFunction(QueryFunction.EQ) + .parameter("01").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, "/GNBCUCPFunction/attributes/pLMNId[@mcc='01']"); + Assertions.assertEquals(expected, resolvedScope); + + //Without root object & Entity type not provided + ScopeLogicalBlock expected1 = new ScopeLogicalBlock(ScopeObject.builder(null).container(ContainerType.ATTRIBUTES) + .innerContainer(List.of("pLMNId")).leaf("mcc").queryFunction(QueryFunction.EQ).parameter("01") + .resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope1 = scopeResolver.resolve(null, "/attributes/pLMNId[@mcc='01']"); + Assertions.assertEquals(expected1, resolvedScope1); + + //With root object & Entity type provided in the container + ScopeLogicalBlock expected2 = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ATTRIBUTES).innerContainer(List.of("pLMNId")).leaf("mcc").queryFunction(QueryFunction.EQ) + .parameter("01").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope2 = scopeResolver.resolve("GNBCUCPFunction", + "/GNBCUCPFunction/attributes/pLMNId[@mcc='01']"); + Assertions.assertEquals(expected2, resolvedScope2); + + //With root object & Entity type not provided + ScopeLogicalBlock expected3 = new ScopeLogicalBlock(ScopeObject.builder("GNBCUCPFunction").container( + ContainerType.ATTRIBUTES).innerContainer(List.of("pLMNId")).leaf("mcc").queryFunction(QueryFunction.EQ) + .parameter("01").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope3 = scopeResolver.resolve("GNBCUCPFunction", "/attributes/pLMNId[@mcc='01']"); + Assertions.assertEquals(expected3, resolvedScope3); + + //With root object & wrong Entity type not provided + final TiesPathException exception = assertThrows(TiesPathException.class, () -> scopeResolver.resolve( + "GNBCUCPFunction", "/GNBDUFunction/attributes/pLMNId[@mcc='01']")); + Assertions.assertEquals("Target/Scope filter can only contain Root Object types mentioned in the path parameter", + exception.getDetails()); + } + + @Test + void testExceptionWithTopologyObjectInScopeFilterWhichDoesNotHaveValidContainerTypeInLeaf() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> scopeResolver.resolve("ManagedElement", + "/ManagedElement[@id1='me1']")); + assertEquals("id1 is not a valid leaf for topology object: ManagedElement", thrown.getDetails()); + } + + @Test + void testExceptionWithScopeFilterLeafButNoCondition() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> scopeResolver.resolve("ManagedElement", + "/GNBDUFunction(fdn))")); + assertEquals("Parameter without any condition is not supported in scope filter", thrown.getDetails()); + } + + @Test + void testSameRootObjectAndContainerNameButNonMatchingContainerTypeInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ManagedElement").container(ContainerType.ID) + .queryFunction(QueryFunction.CONTAINS).parameter("me1").resolverDataType(ResolverDataType.STRING).build()); + final LogicalBlock resolvedScope = scopeResolver.resolve("ManagedElement", "/ManagedElement[contains(@id,'me1')]"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testWithNoRootObjectAndNonMatchingContainerTypeInScopeFilter() { + ScopeLogicalBlock expected = new ScopeLogicalBlock(ScopeObject.builder("ManagedElement").container(null) + .queryFunction(QueryFunction.CONTAINS).parameter("me1").resolverDataType(ResolverDataType.STRING) + .innerContainer(List.of("attr")).leaf("id").build()); + final LogicalBlock resolvedScope = scopeResolver.resolve(null, "/ManagedElement/attr[contains(@id,'me1')]"); + Assertions.assertEquals(expected, resolvedScope); + } + + @Test + void testWithNonMatchingRootObjectInScopeFilter() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> scopeResolver.resolve("GNBDUFunction", + "/ManagedElement/attr[contains(@id,'me1')]")); + assertEquals("Target/Scope filter can only contain Root Object types mentioned in the path parameter", thrown + .getDetails()); + } + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolverTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolverTest.java index 6807f32..5e3d4b6 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolverTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/tiespath/resolver/TargetResolverTest.java @@ -34,19 +34,19 @@ import org.oran.smo.teiv.utils.query.exception.TiesPathException; class TargetResolverTest { - private TargetResolver targetResolver = new TargetResolver(); + private final TargetResolver targetResolver = new TargetResolver(); @Test void testIdOnlyWhenTopologyObjectInRootObjectType() { List expectedObject = List.of(TargetObject.builder("GNBDUFunction").build()); - Assertions.assertEquals(expectedObject, targetResolver.resolve("GNBDUFunction", "")); + Assertions.assertEquals(expectedObject, targetResolver.resolve("GNBDUFunction", null)); } @Test void testIdOnlyWhenTopologyObjectAndContainerInTargetOnlyTest() { List expectedObject = List.of(TargetObject.builder("ENodeBFunction").build()); - Assertions.assertEquals(expectedObject, targetResolver.resolve("", "/ENodeBFunction/id")); + Assertions.assertEquals(expectedObject, targetResolver.resolve(null, "/ENodeBFunction/id")); } @Test @@ -65,15 +65,15 @@ class TargetResolverTest { @Test void testExceptionWhenTopologyObjectInTargetWithParamButNoMatchingContainer() { - TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("", + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, "/GNBDUFunction(fdn, enbId)")); assertEquals("Attributes cannot be associated at this level", thrown.getDetails()); } @Test void testEmptyTargetAndRootObjectType() { - List expectedObject = List.of(TargetObject.builder("*" + "").build()); - Assertions.assertEquals(expectedObject, targetResolver.resolve("", "")); + List expectedObject = List.of(TargetObject.builder("*").build()); + Assertions.assertEquals(expectedObject, targetResolver.resolve(null, null)); } @Test @@ -86,7 +86,7 @@ class TargetResolverTest { @Test void testAllAttributesWithEmptyRootObject() { List expectedObject = List.of(TargetObject.builder("*").container(ContainerType.ATTRIBUTES).build()); - Assertions.assertEquals(expectedObject, targetResolver.resolve("", "/attributes")); + Assertions.assertEquals(expectedObject, targetResolver.resolve(null, "/attributes")); } @Test @@ -98,6 +98,13 @@ class TargetResolverTest { } + @Test + void testAttributesOnSourceIds() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, + "/GNBDUFunction/sourceIds(fdn, enbId)")); + assertEquals("Parameters are not supported for sourceIds in target filter", thrown.getDetails()); + } + @Test void testLogicalANDWithTwoDifferentContainersTypes() { List expectedObject = List.of(TargetObject.builder("GNBDUFunction").container( @@ -108,36 +115,41 @@ class TargetResolverTest { } @Test - void testLogicalANDWithTwoDifferentContainersTypesWithAttributes() { + void testLogicalANDWithTwoDifferentContainersTypesOneWithParams() { List expectedObject = List.of(TargetObject.builder("GNBDUFunction").container( ContainerType.ATTRIBUTES).params(List.of("fdn", "enbId")).build(), TargetObject.builder("GNBDUFunction") - .container(ContainerType.DECORATORS).params(List.of("module-x:location", "module-y:vendor")) - .build()); - Assertions.assertEquals(expectedObject, targetResolver.resolve("", - "/GNBDUFunction/attributes(fdn, enbId);" + "/GNBDUFunction/decorators(module-x:location,module-y:vendor)")); + .container(ContainerType.DECORATORS).build()); + Assertions.assertEquals(expectedObject, targetResolver.resolve(null, + "/GNBDUFunction/attributes(fdn, enbId);" + "/GNBDUFunction/decorators")); + } + + @Test + void testExceptionWithParamOnDecorators() { + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, + "/GNBDUFunction/attributes(fdn, enbId); /GNBDUFunction/decorators(module-x:location,module-y:vendor)")); + assertEquals("Parameters are not supported for decorators in target filter", thrown.getDetails()); } @Test void testExceptionWithMoreThanTwoLevel() { - TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("", + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, "/GNBDUFunction/NRCellDU/attributes")); assertEquals("More than two level deep path is not allowed", thrown.getDetails()); } @Test void testExceptionWithPipeInTargetFilter() { - TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("", + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, "/GNBDUFunction/attributes(fdn, enbId)|/GNBDUFunction/classifiers")); assertEquals("OR (|) is not supported for target filter", thrown.getDetails()); } - /* ToDo Below test will be activated when scopeFilter work is done - @Test + @Test void testExceptionWithScopeFilterInTargetFilter() { TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("GNBDUFunction", - "/GNBDUFunction/attributes[@gNBIdLength=3]")); - assertEquals("Condition of parameter(s) is not supported for target filter", thrown.getDetails()); - }*/ + "/GNBDUFunction/attributes[@gNBIdLength=3 or @abc=5 ]")); + assertEquals("Parameter condition is not supported in target filter", thrown.getDetails()); + } @Test void testTargetWithoutSlash() { @@ -158,14 +170,21 @@ class TargetResolverTest { void testDifferentTopologyObjectInTargetFilterWithAttributesAndRootObjectType() { TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("GNBDUFunction", "/ENodeBFunction/attributes")); - assertEquals("Target filter can only contain Root Object types mentioned in the path parameter", thrown + assertEquals("Target/Scope filter can only contain Root Object types mentioned in the path parameter", thrown .getDetails()); } @Test void testEmptyRootObjectTypeWithOneOfTheWrongTargetToken() { - TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve("", + TiesPathException thrown = assertThrows(TiesPathException.class, () -> targetResolver.resolve(null, "/GNBDUFunction/attributes(fdn, enbId);/GNBDUFunction/NRCellDU/attributes")); assertEquals("More than two level deep path is not allowed", thrown.getDetails()); } + + @Test + void testTargetResolverWithTwoObjects() { + List expectedObject = List.of(TargetObject.builder("GNBDUFunction").build(), TargetObject.builder( + "ENodeBFunction").build()); + Assertions.assertEquals(expectedObject, targetResolver.resolve(null, "/GNBDUFunction; /ENodeBFunction")); + } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/PaginationUtilTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/PaginationUtilTest.java new file mode 100644 index 0000000..f014237 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/PaginationUtilTest.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.exposure.utils; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.api.model.OranTeivHref; +import org.oran.smo.teiv.exception.TiesException; + +class PaginationUtilTest { + private static final RequestDetails requestDetails = RequestDetails.builder().basePath("/test").queryParam("q1", "val2") + .offset(2).limit(5).build(); + + @Test + void testGetViableLimit() { + //offset and limit are less than totalCount + final int limit1 = PaginationUtil.getViableLimit(0, 5, 10); + assertEquals(5, limit1); + + //offset is less than totalCount and limit is greater than totalCount + final int limit2 = PaginationUtil.getViableLimit(0, 5, 3); + assertEquals(3, limit2); + + //totalCount is 0 + final int limit3 = PaginationUtil.getViableLimit(0, 5, 0); + assertEquals(0, limit3); + + //offset is greater than totalCount + TiesException exception = assertThrows(TiesException.class, () -> PaginationUtil.getViableLimit(15, 5, 10)); + assertEquals("Offset cannot be larger than 9", exception.getDetails()); + } + + @Test + void firstHref() { + final OranTeivHref actual = PaginationUtil.firstHref(requestDetails); + + assertEquals(OranTeivHref.builder().href("/test?offset=0&limit=5&q1=val2").build(), actual); + } + + @Test + void prevHref() { + //totalCount < limit + final OranTeivHref actual1 = PaginationUtil.prevHref(requestDetails, 3); + + assertEquals(OranTeivHref.builder().href("/test?offset=0&limit=5&q1=val2").build(), actual1); + + //totalCount = limit + final OranTeivHref actual2 = PaginationUtil.prevHref(requestDetails, 5); + + assertEquals(OranTeivHref.builder().href("/test?offset=0&limit=5&q1=val2").build(), actual2); + + //totalCount > limit + final OranTeivHref actual3 = PaginationUtil.prevHref(requestDetails, 10); + + assertEquals(OranTeivHref.builder().href("/test?offset=0&limit=5&q1=val2").build(), actual3); + } + + @Test + void selfHref() { + final OranTeivHref actual = PaginationUtil.selfHref(requestDetails); + + assertEquals(OranTeivHref.builder().href("/test?offset=2&limit=5&q1=val2").build(), actual); + } + + @Test + void nextHref() { + //totalCount < limit + final OranTeivHref actual1 = PaginationUtil.nextHref(requestDetails, 3); + + assertEquals(OranTeivHref.builder().href("/test?offset=2&limit=5&q1=val2").build(), actual1); + + //totalCount = limit + final OranTeivHref actual2 = PaginationUtil.nextHref(requestDetails, 5); + + assertEquals(OranTeivHref.builder().href("/test?offset=2&limit=5&q1=val2").build(), actual2); + + //totalCount > limit + final OranTeivHref actual3 = PaginationUtil.nextHref(requestDetails, 10); + + assertEquals(OranTeivHref.builder().href("/test?offset=7&limit=5&q1=val2").build(), actual3); + } + + @Test + void lastHref() { + //totalCount < limit + final OranTeivHref actual = PaginationUtil.lastHref(requestDetails, 3); + + assertEquals(OranTeivHref.builder().href("/test?offset=2&limit=5&q1=val2").build(), actual); + + //totalCount = limit + final OranTeivHref actual1 = PaginationUtil.lastHref(requestDetails, 5); + + assertEquals(OranTeivHref.builder().href("/test?offset=2&limit=5&q1=val2").build(), actual1); + + //totalCount > limit + final OranTeivHref actual2 = PaginationUtil.lastHref(requestDetails, 10); + + assertEquals(OranTeivHref.builder().href("/test?offset=7&limit=5&q1=val2").build(), actual2); + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/RequestValidatorTest.java b/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/RequestValidatorTest.java index 2acc630..9b4ba46 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/RequestValidatorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/exposure/utils/RequestValidatorTest.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.schema.SchemaLoader; import org.oran.smo.teiv.schema.SchemaLoaderException; import org.oran.smo.teiv.schema.MockSchemaLoader; @@ -35,7 +34,7 @@ class RequestValidatorTest { @BeforeAll static void setUp() throws SchemaLoaderException { - SchemaLoader mockSchemaLoader = new MockSchemaLoader(); + MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); mockSchemaLoader.loadSchemaRegistry(); requestValidator = new RequestValidator(); } @@ -74,15 +73,4 @@ class RequestValidatorTest { "ANTENNAMODULE_INSTALLED_AT_SITE", "RAN")); } - @Test - void testValidateFiltersForRelationships() { - Assertions.assertDoesNotThrow(() -> requestValidator.validateFiltersForRelationships(null, null)); - Assertions.assertDoesNotThrow(() -> requestValidator.validateFiltersForRelationships(null, - "/GNBDUFunction/attributes[contains (@fdn, \"Hungary\")]")); - Assertions.assertThrowsExactly(TiesException.class, () -> requestValidator.validateFiltersForRelationships( - "/attributes", "/GNBDUFunction/attributes[contains (@fdn, \"Hungary\")]")); - Assertions.assertThrowsExactly(TiesException.class, () -> requestValidator.validateFiltersForRelationships(null, - "/attributes[contains (@fdn, \"Hungary\")]")); - } - } diff --git a/teiv/src/test/java/org/oran/smo/teiv/ingestion/validation/IngestionOperationValidatorTest.java b/teiv/src/test/java/org/oran/smo/teiv/ingestion/validation/IngestionOperationValidatorTest.java index f97d05f..c6d9b22 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/ingestion/validation/IngestionOperationValidatorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/ingestion/validation/IngestionOperationValidatorTest.java @@ -76,7 +76,7 @@ import jakarta.annotation.PostConstruct; @Configuration @SpringBootTest @ActiveProfiles({ "test", "ingestion" }) -public class IngestionOperationValidatorTest { +class IngestionOperationValidatorTest { public static TestPostgresqlContainer postgresqlContainer = TestPostgresqlContainer.getInstance(); @Autowired @@ -128,26 +128,28 @@ public class IngestionOperationValidatorTest { //MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM is a 0..1 to 1 relationship List entities = generateEntities(MAXIMUM_CARDINALITY_CASE.ONE_ONE); List relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-oam-to-cloud", "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", - "rel_1", "ManagedElement_1", "CloudNativeSystem_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-oam-to-cloud", "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", - "rel_2", "ManagedElement_2", "CloudNativeSystem_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-oam-to-cloud", + "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "rel_1", "ManagedElement_1", "CloudNativeSystem_1", List + .of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-oam-to-cloud", + "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "rel_2", "ManagedElement_2", "CloudNativeSystem_1", List + .of())); ParsedCloudEventData parsedCloudEventData = new ParsedCloudEventData(entities, relationships); //It's expected to fail, because the CloudNativeSystem_1 entity would be connected to 2 ManagedElement instances assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData)); //The whole transaction is rolled back. Neither the entities nor the relationships are persisted. - assertEmptyTable("ties_data.\"ManagedElement\""); - assertEmptyTable("ties_data.\"CloudNativeSystem\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); + assertEmptyTable("ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); //Remove the extra relationship that caused the cardinality violation. Successfully insert the others. Relationship redundantRelationship = relationships.remove(1); ParsedCloudEventData parsedCloudEventData2 = new ParsedCloudEventData(entities, relationships); assertEquals(entities.size() + relationships.size(), tiesDbOperations.executeEntityAndRelationshipMergeOperations( parsedCloudEventData2).size()); - verify(spiedDbServiceForValidation).acquireEntityInstanceExclusiveLock("ties_data.\"CloudNativeSystem\"", - "CloudNativeSystem_1"); + verify(spiedDbServiceForValidation).acquireEntityInstanceExclusiveLock( + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", "CloudNativeSystem_1"); //Try to insert an extra relationship. It's expected to fail, because the CloudNativeSystem_1 entity already has the maximum number of relationships. ParsedCloudEventData parsedCloudEventData3 = new ParsedCloudEventData(List.of(), List.of(redundantRelationship)); @@ -160,30 +162,30 @@ public class IngestionOperationValidatorTest { // TESTENTITYA_USES_TESTENTITYB is a 0..1 to 0..2 relationship List entities = generateEntities(MAXIMUM_CARDINALITY_CASE.ONE_CONST); List relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_USES_TESTENTITYB", "rel_1", "TestEntityA_1", - "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_USES_TESTENTITYB", "rel_2", "TestEntityA_1", - "TestEntityB_2", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_USES_TESTENTITYB", "rel_3", "TestEntityA_1", - "TestEntityB_3", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_USES_TESTENTITYB", "rel_1", + "TestEntityA_1", "TestEntityB_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_USES_TESTENTITYB", "rel_2", + "TestEntityA_1", "TestEntityB_2", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_USES_TESTENTITYB", "rel_3", + "TestEntityA_1", "TestEntityB_3", List.of())); ParsedCloudEventData parsedCloudEventData = new ParsedCloudEventData(entities, relationships); //It's expected to fail, because the TestEntityA_1 entity would be connected to 3 TestEntityB instances assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData)); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityA\"", - "TestEntityA_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\"", "TestEntityA_1"); //The whole transaction is rolled back. Neither the entities nor the relationships are persisted. - assertEmptyTable("ties_data.\"TestEntityA\""); - assertEmptyTable("ties_data.\"TestEntityB\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\""); //Remove the extra relationship that caused the cardinality violation. Successfully insert the others. Relationship redundantRelationship = relationships.remove(2); ParsedCloudEventData parsedCloudEventData2 = new ParsedCloudEventData(entities, relationships); assertEquals(entities.size() + relationships.size(), tiesDbOperations.executeEntityAndRelationshipMergeOperations( parsedCloudEventData2).size()); - verify(spiedDbServiceForValidation, times(2)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityA\"", - "TestEntityA_1"); + verify(spiedDbServiceForValidation, times(2)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\"", "TestEntityA_1"); verify(spiedDbServiceForValidation, times(2)).executeValidationQuery(any(), any(), any(), any(Long.class)); verifyNoMoreInteractions(spiedDbServiceForValidation); @@ -191,55 +193,55 @@ public class IngestionOperationValidatorTest { ParsedCloudEventData parsedCloudEventData3 = new ParsedCloudEventData(List.of(), List.of(redundantRelationship)); assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData3)); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityA\"", - "TestEntityA_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\"", "TestEntityA_1"); } @Test - void maximumCardinalityViolationConstToConstRelationship() throws InvalidFieldInYangDataException { + void maximumCardinalityViolationConstToConstRelationship() { // TESTENTITYA_PROVIDES_TESTENTITYB is a 0..2 to 0..3 relationship List entities = generateEntities(MAXIMUM_CARDINALITY_CASE.CONST_CONST); List relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_1", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_1", "TestEntityA_1", "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_2", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_2", "TestEntityA_1", "TestEntityB_2", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_3", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_3", "TestEntityA_1", "TestEntityB_3", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_4", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_4", "TestEntityA_1", "TestEntityB_4", List.of())); ParsedCloudEventData parsedCloudEventData = new ParsedCloudEventData(entities, relationships); //It's expected to fail, because the TestEntityA_1 entity would be connected to 4 TestEntityB instances assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData)); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_1"); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityA\"", - "TestEntityA_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\"", "TestEntityA_1"); //The whole transaction is rolled back. Neither the entities nor the relationships are persisted. - assertEmptyTable("ties_data.\"TestEntityA\""); - assertEmptyTable("ties_data.\"TestEntityB\""); - assertEmptyTable("ties_data.\"TESTENTITYA_PROVIDES_TESTENTITYB\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\""); + assertEmptyTable("ties_data.\"73936e503f137d82d1422c0f08c66c7ff8b90209\""); //Test the other side's cardinality as well relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_1", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_1", "TestEntityA_1", "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_2", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_2", "TestEntityA_2", "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_3", + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_PROVIDES_TESTENTITYB", "rel_3", "TestEntityA_3", "TestEntityB_1", List.of())); ParsedCloudEventData parsedCloudEventData2 = new ParsedCloudEventData(entities, relationships); //It's expected to fail, because the TestEntityB_1 entity would be connected to 3 TestEntityA instances assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData2)); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_1"); - assertEmptyTable("ties_data.\"TestEntityA\""); - assertEmptyTable("ties_data.\"TestEntityB\""); - assertEmptyTable("ties_data.\"TESTENTITYA_PROVIDES_TESTENTITYB\""); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_1"); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\""); + assertEmptyTable("ties_data.\"73936e503f137d82d1422c0f08c66c7ff8b90209\""); } @Test @@ -247,51 +249,50 @@ public class IngestionOperationValidatorTest { // TESTENTITYA_GROUPS_TESTENTITYB is a 0..2 to 0..n relationship List entities = generateEntities(MAXIMUM_CARDINALITY_CASE.CONST_INFINITE); List relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_1", "TestEntityA_1", - "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_2", "TestEntityA_2", - "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_3", "TestEntityA_3", - "TestEntityB_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_1", + "TestEntityA_1", "TestEntityB_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_2", + "TestEntityA_2", "TestEntityB_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_3", + "TestEntityA_3", "TestEntityB_1", List.of())); ParsedCloudEventData parsedCloudEventData = new ParsedCloudEventData(entities, relationships); //It's expected to fail, because the TestEntityB_1 entity would be connected to 3 TestEntityB instances assertThrows(MaximumCardinalityViolationException.class, () -> tiesDbOperations .executeEntityAndRelationshipMergeOperations(parsedCloudEventData)); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_1"); //The whole transaction is rolled back. Neither the entities nor the relationships are persisted. - assertEmptyTable("ties_data.\"TestEntityA\""); - assertEmptyTable("ties_data.\"TestEntityB\""); - assertEmptyTable("ties_data.\"TESTENTITYA_GROUPS_TESTENTITYB\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityA\""); + assertEmptyTable("ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\""); + assertEmptyTable("ties_data.\"70003c8082751e1832e7bc5c0d83db6d22c4fcdc\""); //Test the other side's cardinality - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_2", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_3", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_2", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_3", Map.of(), List.of())); relationships = new ArrayList<>(); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_1", "TestEntityA_1", - "TestEntityB_1", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_2", "TestEntityA_1", - "TestEntityB_2", List.of())); - relationships.add(new Relationship("o-ran-smo-teiv-ran", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_3", "TestEntityA_1", - "TestEntityB_3", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_1", + "TestEntityA_1", "TestEntityB_1", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_2", + "TestEntityA_1", "TestEntityB_2", List.of())); + relationships.add(new Relationship("o-ran-smo-teiv-ran-logical", "TESTENTITYA_GROUPS_TESTENTITYB", "rel_3", + "TestEntityA_1", "TestEntityB_3", List.of())); ParsedCloudEventData parsedCloudEventData2 = new ParsedCloudEventData(entities, relationships); assertEquals(entities.size() + relationships.size(), tiesDbOperations.executeEntityAndRelationshipMergeOperations( parsedCloudEventData2).size()); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_1"); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_2"); - verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock("ties_data.\"TestEntityB\"", - "TestEntityB_3"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_1"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_2"); + verify(spiedDbServiceForValidation, times(1)).acquireEntityInstanceExclusiveLock( + "ties_data.\"o-ran-smo-teiv-ran-logical_TestEntityB\"", "TestEntityB_3"); verify(spiedDbServiceForValidation, times(3)).executeValidationQuery(any(), any(), any(), any(Long.class)); verifyNoMoreInteractions(spiedDbServiceForValidation); } @ParameterizedTest @CsvSource({ "5, 5, A_SIDE", "3, 3, B_SIDE" }) - void unsupportedStorageLocation(int aSideMax, int bSideMax, RelationshipDataLocation location) - throws InvalidFieldInYangDataException { + void unsupportedStorageLocation(int aSideMax, int bSideMax, RelationshipDataLocation location) { try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { Relationship relationship = new Relationship("", "relation_type", "id", "a", "b", List.of()); RelationType relationType = RelationType.builder().aSideAssociation(Association.builder().maxCardinality( @@ -305,7 +306,7 @@ public class IngestionOperationValidatorTest { } @Test - void determineMaxCardinalityCase() throws InvalidFieldInYangDataException { + void determineMaxCardinalityCase() { assertThrows(IllegalArgumentException.class, () -> IngestionOperationValidator.determineMaxCardinalityCase(0, 0)); assertThrows(IllegalArgumentException.class, () -> IngestionOperationValidator.determineMaxCardinalityCase(-1, 0)); assertThrows(IllegalArgumentException.class, () -> IngestionOperationValidator.determineMaxCardinalityCase(0, -1)); @@ -339,23 +340,23 @@ public class IngestionOperationValidatorTest { List entities = new ArrayList<>(); switch (cardinalityCase) { case ONE_ONE: - entities.add(new Entity("o-ran-smo-teiv-oam", "ManagedElement", "ManagedElement_1", Map.of("fdn", "fdn1"), - List.of())); - entities.add(new Entity("o-ran-smo-teiv-oam", "ManagedElement", "ManagedElement_2", Map.of("fdn", "fdn2"), - List.of())); - entities.add(new Entity("o-ran-smo-teiv-cloud", "CloudNativeSystem", "CloudNativeSystem_1", Map.of("name", - "name1"), List.of())); - entities.add(new Entity("o-ran-smo-teiv-cloud", "CloudNativeSystem", "CloudNativeSystem_2", Map.of("name", - "name2"), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-oam", "ManagedElement", "ManagedElement_1", Map.of("fdn", + "fdn1"), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-oam", "ManagedElement", "ManagedElement_2", Map.of("fdn", + "fdn2"), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-cloud", "CloudNativeSystem", "CloudNativeSystem_1", Map.of( + "name", "name1"), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-cloud", "CloudNativeSystem", "CloudNativeSystem_2", Map.of( + "name", "name2"), List.of())); break; default: - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityA", "TestEntityA_1", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityA", "TestEntityA_2", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityA", "TestEntityA_3", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_1", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_2", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_3", Map.of(), List.of())); - entities.add(new Entity("o-ran-smo-teiv-ran", "TestEntityB", "TestEntityB_4", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityA", "TestEntityA_1", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityA", "TestEntityA_2", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityA", "TestEntityA_3", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_1", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_2", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_3", Map.of(), List.of())); + entities.add(new Entity("o-ran-smo-teiv-ran-logical", "TestEntityB", "TestEntityB_4", Map.of(), List.of())); break; } return entities; diff --git a/teiv/src/test/java/org/oran/smo/teiv/listener/CreateTopologyProcessorTest.java b/teiv/src/test/java/org/oran/smo/teiv/listener/CreateTopologyProcessorTest.java index df5cc07..5d2d8f6 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/listener/CreateTopologyProcessorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/listener/CreateTopologyProcessorTest.java @@ -44,7 +44,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; +import io.cloudevents.CloudEvent; + import org.oran.smo.teiv.CustomMetrics; +import org.oran.smo.teiv.schema.MockSchemaLoader; import org.oran.smo.teiv.schema.SchemaLoader; import org.oran.smo.teiv.schema.SchemaLoaderException; import org.oran.smo.teiv.service.TiesDbService; @@ -54,9 +57,6 @@ import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; import org.oran.smo.teiv.startup.SchemaHandler; import org.oran.smo.teiv.utils.CloudEventTestUtil; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import io.cloudevents.CloudEvent; - @SpringBootTest @ActiveProfiles({ "test", "ingestion" }) class CreateTopologyProcessorTest { @@ -80,9 +80,9 @@ class CreateTopologyProcessorTest { } @Test - void testCreateCloudNativeApplicationEntity1() { + void testCreateGNBDUFunctionEntity1() { CloudEvent event = CloudEventTestUtil.getCloudEvent("create", "{}"); - String entityType = "CloudNativeApplication"; + String entityType = "GNBDUFunction"; Map yangParserOutputMapBSide = new HashMap<>(); Entity entity = new Entity("", entityType, "cloud_id_1", yangParserOutputMapBSide, List.of()); @@ -99,7 +99,7 @@ class CreateTopologyProcessorTest { @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) void testInvalidAttribute() { CloudEvent event = CloudEventTestUtil.getCloudEvent("create", "{}"); - String entityType = "CloudNativeApplication"; + String entityType = "NFDeployment"; Map yangParserOutputMap = new HashMap<>(); yangParserOutputMap.put("invalidfield", "value1"); Entity entity = new Entity("", entityType, "id1", yangParserOutputMap, List.of()); diff --git a/teiv/src/test/java/org/oran/smo/teiv/listener/DeleteTopologyProcessorTest.java b/teiv/src/test/java/org/oran/smo/teiv/listener/DeleteTopologyProcessorTest.java index 5ecdd44..6e14176 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/listener/DeleteTopologyProcessorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/listener/DeleteTopologyProcessorTest.java @@ -20,16 +20,17 @@ */ package org.oran.smo.teiv.listener; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.service.TiesDbService; -import org.oran.smo.teiv.service.cloudevent.CloudEventParser; -import org.oran.smo.teiv.service.cloudevent.data.Entity; -import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; -import org.oran.smo.teiv.startup.SchemaHandler; -import org.oran.smo.teiv.utils.CloudEventTestUtil; -import io.cloudevents.CloudEvent; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -39,12 +40,17 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import io.cloudevents.CloudEvent; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; +import org.oran.smo.teiv.service.TiesDbService; +import org.oran.smo.teiv.service.cloudevent.CloudEventParser; +import org.oran.smo.teiv.service.cloudevent.data.Entity; +import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; +import org.oran.smo.teiv.startup.SchemaHandler; +import org.oran.smo.teiv.utils.CloudEventTestUtil; @SpringBootTest @ActiveProfiles({ "test", "ingestion" }) @@ -69,7 +75,7 @@ class DeleteTopologyProcessorTest { @Test void testDeleteCloudNativeApplicationEntity1() { CloudEvent event = CloudEventTestUtil.getCloudEvent("delete", "{}"); - String entityType = "CloudNativeApplication"; + String entityType = "NFDeployment"; Map yangParserOutputMapBSide = new HashMap<>(); Entity entity = new Entity("", entityType, "cloud_id_1", yangParserOutputMapBSide, List.of()); diff --git a/teiv/src/test/java/org/oran/smo/teiv/listener/MergeTopologyProcessorTest.java b/teiv/src/test/java/org/oran/smo/teiv/listener/MergeTopologyProcessorTest.java index 28151ad..1cdc2ce 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/listener/MergeTopologyProcessorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/listener/MergeTopologyProcessorTest.java @@ -33,8 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.oran.smo.teiv.CustomMetrics; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -43,20 +41,21 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; -import org.oran.smo.teiv.schema.SchemaLoader; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.startup.SchemaHandler; -import org.oran.smo.teiv.schema.MockSchemaLoader; import io.cloudevents.CloudEvent; +import org.oran.smo.teiv.CustomMetrics; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; import org.oran.smo.teiv.service.TiesDbService; import org.oran.smo.teiv.service.cloudevent.CloudEventParser; import org.oran.smo.teiv.service.cloudevent.data.Entity; import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; +import org.oran.smo.teiv.startup.SchemaHandler; import org.oran.smo.teiv.utils.CloudEventTestUtil; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; @SpringBootTest @ActiveProfiles({ "test", "ingestion" }) @@ -82,9 +81,9 @@ class MergeTopologyProcessorTest { } @Test - void testMergeCloudNativeApplicationEntity1() { + void testMergeGNBDUFunctionEntity1() { CloudEvent event = CloudEventTestUtil.getCloudEvent("merge", "{}"); - String entityType = "CloudNativeApplication"; + String entityType = "GNBDUFunction"; Map yangParserOutputMapBSide = new HashMap<>(); Entity entity = new Entity("", entityType, "cloud_id_1", yangParserOutputMapBSide, List.of()); @@ -101,7 +100,7 @@ class MergeTopologyProcessorTest { @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) void testInvalidAttribute() { CloudEvent event = CloudEventTestUtil.getCloudEvent("merge", "{}"); - String entityType = "CloudNativeApplication"; + String entityType = "NFDeployment"; Map yangParserOutputMap = new HashMap<>(); yangParserOutputMap.put("invalidfield", "value1"); Entity entity = new Entity("", entityType, "id1", yangParserOutputMap, List.of()); diff --git a/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorTest.java b/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorTest.java index 1d285ae..2ce5d04 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorTest.java @@ -23,20 +23,34 @@ package org.oran.smo.teiv.listener; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; +import java.lang.reflect.Field; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.jooq.DSLContext; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.oran.smo.teiv.service.models.OperationResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson; import org.springframework.boot.test.context.SpringBootTest; @@ -44,26 +58,31 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + import org.oran.smo.teiv.CustomMetrics; +import org.oran.smo.teiv.schema.BidiDbNameMapper; import org.oran.smo.teiv.schema.EntityType; import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.service.TiesDbOperations; import org.oran.smo.teiv.service.TiesDbService; import org.oran.smo.teiv.startup.SchemaHandler; -import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; @SpringBootTest @AutoConfigureJson @ActiveProfiles({ "test", "ingestion" }) class SourceEntityDeleteTopologyProcessorTest { + @Autowired private SourceEntityDeleteTopologyProcessor sourceEntityDeleteTopologyProcessor; - @Autowired CustomMetrics metrics; @MockBean private TiesDbService tiesDbService; @MockBean + private TiesDbOperations tiesDbOperations; + @MockBean private SchemaHandler schemaHandler; @Test @@ -111,17 +130,17 @@ class SourceEntityDeleteTopologyProcessorTest { void testSourceEntityDeleteUponRuntimeExceptionDuringDeletion() { //given try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { - EntityType entityType = Mockito.mock(EntityType.class); + EntityType entityType = mock(EntityType.class); CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( "{\"type\":\"cmHandle\",\"value\":\"abc\"}".getBytes(StandardCharsets.UTF_8)).build(); - mockedSchemaRegistry.when(SchemaRegistry::getEntityTypesWithCmId).thenReturn(List.of(entityType)); + mockedSchemaRegistry.when(SchemaRegistry::getEntityTypes).thenReturn(List.of(entityType)); doThrow(new RuntimeException()).when(tiesDbService).execute(anyList()); //when assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); //then - mockedSchemaRegistry.verify(SchemaRegistry::getEntityTypesWithCmId, times(1)); + mockedSchemaRegistry.verify(SchemaRegistry::getEntityTypes, times(1)); verify(tiesDbService, times(1)).execute(anyList()); assertEquals(1, metrics.getNumSuccessfullyParsedSourceEntityDeleteCloudEvents().count()); @@ -133,4 +152,57 @@ class SourceEntityDeleteTopologyProcessorTest { assertEquals(0, metrics.getCloudEventSourceEntityDeletePersistTime().count()); } } + + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) + void testSourceEntityDelete() throws NoSuchFieldException { + //given + try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { + DSLContext stream = mock(DSLContext.class); + CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") + .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") + .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( + "{\"type\":\"cmHandle\",\"value\":\"395221E080CCF0FD1924103B15873814\"}".getBytes( + StandardCharsets.UTF_8)).build(); + + Map mockNameMap = new HashMap<>(); + mockNameMap.put("GNBDUFunction", "GNBDUFunction"); + Field nameMapField = BidiDbNameMapper.class.getDeclaredField("nameMap"); + nameMapField.setAccessible(true); + nameMapField.set(null, mockNameMap); + + OperationResult mockOperationResult = mock(OperationResult.class); + EntityType gnbduFunction = EntityType.builder().name("GNBDUFunction").build(); + when(SchemaRegistry.getEntityTypes()).thenReturn(List.of(gnbduFunction)); + when(tiesDbOperations.selectByCmHandleFormSourceIds(any(), anyString(), anyString())).thenReturn(List.of( + "result1")); + when(tiesDbOperations.deleteEntity(any(), any(), anyString())).thenReturn(List.of(mockOperationResult)); + doAnswer(new Answer() { + @Override + public Void answer(InvocationOnMock invocation) { + List> consumers = invocation.getArgument(0); + consumers.forEach(consumer -> { + consumer.accept(stream); + }); + return null; + } + }).when(tiesDbService).execute(anyList()); + //when + assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); + //then + mockedSchemaRegistry.verify(SchemaRegistry::getEntityTypes, times(1)); + verify(tiesDbService, atLeastOnce()).execute(anyList()); + verify(tiesDbOperations, atLeastOnce()).selectByCmHandleFormSourceIds(any(), anyString(), anyString()); + verify(tiesDbOperations, atLeastOnce()).deleteEntity(any(), any(), anyString()); + + assertEquals(1, metrics.getNumSuccessfullyParsedSourceEntityDeleteCloudEvents().count()); + assertEquals(0, metrics.getNumUnsuccessfullyParsedSourceEntityDeleteCloudEvents().count()); + assertEquals(1, metrics.getNumSuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); + assertEquals(0, metrics.getNumUnsuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); + assertEquals(1, metrics.getCloudEventSourceEntityDeleteParseTime().count()); + assertEquals(1, metrics.getCloudEventSourceEntityDeletePersistTime().count()); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1Test.java b/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1Test.java deleted file mode 100644 index 08818dc..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/listener/SourceEntityDeleteTopologyProcessorV1Test.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.listener; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.lang.reflect.Field; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import org.jooq.DSLContext; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; - -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.service.models.OperationResult; -import org.oran.smo.teiv.schema.BidiDbNameMapper; -import org.oran.smo.teiv.schema.EntityType; -import org.oran.smo.teiv.schema.SchemaRegistry; -import org.oran.smo.teiv.service.TiesDbOperations; -import org.oran.smo.teiv.service.TiesDbService; -import org.oran.smo.teiv.startup.SchemaHandler; -import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; - -@SpringBootTest(properties = "feature_flags.use_alternate_delete_logic=true") -@AutoConfigureJson -@ActiveProfiles({ "test", "ingestion" }) -class SourceEntityDeleteTopologyProcessorV1Test { - - @Autowired - private SourceEntityDeleteTopologyProcessorV1 sourceEntityDeleteTopologyProcessor; - @Autowired - CustomMetrics metrics; - @MockBean - private TiesDbService tiesDbService; - @MockBean - private TiesDbOperations tiesDbOperations; - @MockBean - private SchemaHandler schemaHandler; - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) - void testSourceEntityDeleteWithInvalidEventData() { - //given - try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { - CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") - .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") - .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( - "{\"type\":\"cmHandle\",\"invalid\":\"abc\"}".getBytes(StandardCharsets.UTF_8)).build(); - //when - assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); - //then - mockedSchemaRegistry.verifyNoInteractions(); - verifyNoInteractions(tiesDbService); - - assertEquals(0, metrics.getNumSuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(1, metrics.getNumUnsuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumSuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumUnsuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getCloudEventSourceEntityDeleteParseTime().count()); - assertEquals(0, metrics.getCloudEventSourceEntityDeletePersistTime().count()); - } - } - - @Test - void testSourceEntityDeleteWithUnsupportedEntityType() { - //given - try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { - CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") - .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") - .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( - "{\"type\":\"unsupported-type\",\"value\":\"abc\"}".getBytes(StandardCharsets.UTF_8)).build(); - //when - assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); - //then - mockedSchemaRegistry.verifyNoInteractions(); - verifyNoInteractions(tiesDbService); - } - } - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) - void testSourceEntityDeleteUponRuntimeExceptionDuringDeletion() { - //given - try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { - EntityType entityType = Mockito.mock(EntityType.class); - CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") - .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") - .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( - "{\"type\":\"cmHandle\",\"value\":\"abc\"}".getBytes(StandardCharsets.UTF_8)).build(); - mockedSchemaRegistry.when(SchemaRegistry::getEntityTypes).thenReturn(List.of(entityType)); - doThrow(new RuntimeException()).when(tiesDbService).execute(anyList()); - //when - assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); - //then - mockedSchemaRegistry.verify(SchemaRegistry::getEntityTypes, times(1)); - verify(tiesDbService, times(1)).execute(anyList()); - - assertEquals(1, metrics.getNumSuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumUnsuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumSuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(1, metrics.getNumUnsuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(1, metrics.getCloudEventSourceEntityDeleteParseTime().count()); - assertTrue(metrics.getCloudEventSourceEntityDeleteParseTime().totalTime(TimeUnit.NANOSECONDS) > 0); - assertEquals(0, metrics.getCloudEventSourceEntityDeletePersistTime().count()); - } - } - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) - void testSourceEntityDelete() throws NoSuchFieldException { - //given - try (MockedStatic mockedSchemaRegistry = Mockito.mockStatic(SchemaRegistry.class)) { - DSLContext stream = mock(DSLContext.class); - CloudEvent event = CloudEventBuilder.v1().withId("test-id").withType("ran-logical.source-entity-delete") - .withSource(URI.create("http://localhost:8080/test-source")).withDataContentType("application/json") - .withDataSchema(URI.create("http://localhost:8080/schema/v1/source-entity-delete")).withData( - "{\"type\":\"cmHandle\",\"value\":\"395221E080CCF0FD1924103B15873814\"}".getBytes( - StandardCharsets.UTF_8)).build(); - - Map mockNameMap = new HashMap<>(); - mockNameMap.put("GNBDUFunction", "GNBDUFunction"); - Field nameMapField = BidiDbNameMapper.class.getDeclaredField("nameMap"); - nameMapField.setAccessible(true); - nameMapField.set(null, mockNameMap); - - OperationResult mockOperationResult = mock(OperationResult.class); - EntityType gnbduFunction = EntityType.builder().name("GNBDUFunction").build(); - when(SchemaRegistry.getEntityTypes()).thenReturn(List.of(gnbduFunction)); - when(tiesDbOperations.selectByCmHandleFormSourceIds(any(), anyString(), anyString())).thenReturn(List.of( - "result1")); - when(tiesDbOperations.deleteEntity(any(), any(), anyString())).thenReturn(List.of(mockOperationResult)); - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - List> consumers = invocation.getArgument(0); - consumers.forEach(consumer -> { - consumer.accept(stream); - }); - return null; - } - }).when(tiesDbService).execute(anyList()); - //when - assertDoesNotThrow(() -> sourceEntityDeleteTopologyProcessor.process(event, "messageKey")); - //then - mockedSchemaRegistry.verify(SchemaRegistry::getEntityTypes, times(1)); - verify(tiesDbService, atLeastOnce()).execute(anyList()); - verify(tiesDbOperations, atLeastOnce()).selectByCmHandleFormSourceIds(any(), anyString(), anyString()); - verify(tiesDbOperations, atLeastOnce()).deleteEntity(any(), any(), anyString()); - - assertEquals(1, metrics.getNumSuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumUnsuccessfullyParsedSourceEntityDeleteCloudEvents().count()); - assertEquals(1, metrics.getNumSuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(0, metrics.getNumUnsuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); - assertEquals(1, metrics.getCloudEventSourceEntityDeleteParseTime().count()); - assertEquals(1, metrics.getCloudEventSourceEntityDeletePersistTime().count()); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/schema/ConsumerDataCacheTest.java b/teiv/src/test/java/org/oran/smo/teiv/schema/ConsumerDataCacheTest.java index 3bc66ca..c4dd0ac 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/schema/ConsumerDataCacheTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/schema/ConsumerDataCacheTest.java @@ -20,11 +20,10 @@ */ package org.oran.smo.teiv.schema; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.impl.DataPersistanceServiceImpl; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataRepositoryImpl; + import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.Collections; import java.util.Map; import java.util.Set; @@ -35,15 +34,15 @@ import static org.mockito.Mockito.when; public class ConsumerDataCacheTest { - private static final DataPersistanceService dataPersistanceService = mock(DataPersistanceServiceImpl.class); - private final ConsumerDataCache underTest = new ConsumerDataCache(dataPersistanceService); + private static final ConsumerDataRepositoryImpl DATA_REPOSITORY = mock(ConsumerDataRepositoryImpl.class); + private final ConsumerDataCache underTest = new ConsumerDataCache(DATA_REPOSITORY); @BeforeAll static void beforeAll() { - when(dataPersistanceService.loadClassifiers()).thenReturn(Set.of("gnbdu-function-model:Rural", + when(DATA_REPOSITORY.loadClassifiers()).thenReturn(Set.of("gnbdu-function-model:Rural", "gnbcucp-gnbcuup-model:Weekend")); - when(dataPersistanceService.loadDecorators()).thenReturn(Map.of("gnbdu-function-model:location", DataType.PRIMITIVE, - "gnbcucp-gnbcuup-model:metadata", DataType.CONTAINER)); + when(DATA_REPOSITORY.loadDecorators()).thenReturn(Map.of("gnbdu-function-model:location", YangDataTypes.STRING, + "gnbcucp-gnbcuup-model:metadata", YangDataTypes.BOOLEAN)); } @Test @@ -62,7 +61,7 @@ public class ConsumerDataCacheTest { @Test void testGetDecorators() { - assertEquals(Map.of("gnbdu-function-model:location", DataType.PRIMITIVE, "gnbcucp-gnbcuup-model:metadata", - DataType.CONTAINER), underTest.getDecorators()); + assertEquals(Map.of("gnbdu-function-model:location", YangDataTypes.STRING, "gnbcucp-gnbcuup-model:metadata", + YangDataTypes.BOOLEAN), underTest.getDecorators()); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/schema/MockSchemaLoader.java b/teiv/src/test/java/org/oran/smo/teiv/schema/MockSchemaLoader.java index 026a08e..8ebc1d4 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/schema/MockSchemaLoader.java +++ b/teiv/src/test/java/org/oran/smo/teiv/schema/MockSchemaLoader.java @@ -20,576 +20,169 @@ */ package org.oran.smo.teiv.schema; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.oran.smo.teiv.exposure.spi.Module; import static org.oran.smo.teiv.schema.DataType.BIGINT; import static org.oran.smo.teiv.schema.DataType.CONTAINER; import static org.oran.smo.teiv.schema.DataType.DECIMAL; import static org.oran.smo.teiv.schema.DataType.GEOGRAPHIC; +import static org.oran.smo.teiv.schema.DataType.INTEGER; import static org.oran.smo.teiv.schema.DataType.PRIMITIVE; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.A_SIDE; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; +import static org.oran.smo.teiv.utils.TiesConstants.TEIV_DOMAIN; public class MockSchemaLoader extends SchemaLoader { @Override protected void loadBidiDbNameMapper() { - Map hashedNames = new HashMap<>(); - hashedNames.put("GNBDUFunction", "GNBDUFunction"); - hashedNames.put("GNBCUUPFunction", "GNBCUUPFunction"); - hashedNames.put("NRCellDU", "NRCellDU"); - hashedNames.put("NRSectorCarrier", "NRSectorCarrier"); - hashedNames.put("CloudNativeApplication", "CloudNativeApplication"); - hashedNames.put("AntennaCapability", "AntennaCapability"); - hashedNames.put("Sector", "Sector"); - hashedNames.put("AntennaModule", "AntennaModule"); - - hashedNames.put("ANTENNAMODULE_INSTALLED_AT_SITE", "ANTENNAMODULE_INSTALLED_AT_SITE"); - hashedNames.put("GNBDUFUNCTION_PROVIDES_NRCELLDU", "GNBDUFUNCTION_PROVIDES_NRCELLDU"); - hashedNames.put("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); - hashedNames.put("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - hashedNames.put("NRSECTORCARRIER_USES_ANTENNACAPABILITY", "NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - hashedNames.put("SECTOR_GROUPS_ANTENNAMODULE", "SECTOR_GROUPS_ANTENNAMODULE"); - hashedNames.put("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - - hashedNames.put("id", "id"); - hashedNames.put("fdn", "fdn"); - hashedNames.put("cmId", "cmId"); - hashedNames.put("CD_sourceIds", "CD_sourceIds"); - - // GNBDUFUNCTION - hashedNames.put("dUpLMNId", "dUpLMNId"); - hashedNames.put("gNBIdLength", "gNBIdLength"); - hashedNames.put("gNBId", "gNBId"); - hashedNames.put("gNBDUId", "gNBDUId"); - hashedNames.put("REL_FK_managed-by-managedElement", "REL_FK_managed-by-managedElement"); - hashedNames.put("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - - //NRCELLDU - hashedNames.put("nCI", "nCI"); - hashedNames.put("cellLocalId", "cellLocalId"); - hashedNames.put("nRPCI", "nRPCI"); - hashedNames.put("nRTAC", "nRTAC"); - hashedNames.put("REL_FK_grouped-by-sector", "REL_FK_grouped-by-sector"); - hashedNames.put("REL_ID_SECTOR_GROUPS_NRCELLDU", "REL_ID_SECTOR_GROUPS_NRCELLDU"); - hashedNames.put("REL_FK_provided-by-gnbduFunction", "REL_FK_provided-by-gnbduFunction"); - hashedNames.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU"); - hashedNames.put("REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU", - "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU"); - - //NrSectorCarrier - hashedNames.put("frequencyDL", "frequencyDL"); - hashedNames.put("frequencyUL", "frequencyUL"); - hashedNames.put("arfcnUL", "arfcnUL"); - hashedNames.put("essScLocalId", "essScLocalId"); - hashedNames.put("arfcnDL", "arfcnDL"); - hashedNames.put("REL_FK_used-by-nrCellDu", "REL_FK_used-by-nrCellDu"); - hashedNames.put("REL_ID_NRCELLDU_USES_NRSECTORCARRIER", "REL_ID_NRCELLDU_USES_NRSECTORCARRIER"); - hashedNames.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); - hashedNames.put("REL_FK_used-antennaCapability", "REL_FK_used-antennaCapability"); - hashedNames.put("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY", "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - - //CloudNativeApplication - hashedNames.put("name", "name"); - hashedNames.put("REL_FK_realised-managedElement", "REL_FK_realised-managedElement"); - hashedNames.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", - "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION"); - hashedNames.put("REL_FK_comprised-by-cloudNativeSystem", "REL_FK_comprised-by-cloudNativeSystem"); - hashedNames.put("REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", - "REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION"); - hashedNames.put("REL_FK_deployed-on-namespace", "REL_FK_deployed-on-namespace"); - hashedNames.put("REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE", - "REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE"); - - //AntennaCapability - hashedNames.put("nRFqBands", "nRFqBands"); - hashedNames.put("eUtranFqBands", "eUtranFqBands"); - hashedNames.put("geranFqBands", "geranFqBands"); - hashedNames.put("REL_FK_used-by-lteSectorCarrier", "REL_FK_used-by-lteSectorCarrier"); - - //Sector - hashedNames.put("sectorId", "sectorId"); - hashedNames.put("azimuth", "azimuth"); - - //AntennaModule - hashedNames.put("positionWithinSector", "positionWithinSector"); - hashedNames.put("antennaModelNumber", "antennaModelNumber"); - hashedNames.put("electricalAntennaTilt", "electricalAntennaTilt"); - hashedNames.put("mechanicalAntennaTilt", "mechanicalAntennaTilt"); - hashedNames.put("totalTilt", "totalTilt"); - hashedNames.put("mechanicalAntennaBearing", "mechanicalAntennaBearing"); - hashedNames.put("REL_ID_SECTOR_GROUPS_ANTENNAMODULE", "REL_ID_SECTOR_GROUPS_ANTENNAMODULE"); - hashedNames.put("REL_FK_installed-at-site", "REL_FK_installed-at-site"); - hashedNames.put("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE"); - - //GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION - hashedNames.put("aSide_GNBDUFunction", "aSide_GNBDUFunction"); - hashedNames.put("bSide_CloudNativeApplication", "bSide_CloudNativeApplication"); - - //ANTENNAMODULE_REALISED_BY_ANTENNAMODULE - hashedNames.put("aSide_AntennaModule", "aSide_AntennaModule"); - hashedNames.put("bSide_AntennaModule", "bSide_AntennaModule"); - Map reverseHashedNames = new HashMap<>(); - reverseHashedNames.put("GNBDUFunction", "GNBDUFunction"); - reverseHashedNames.put("GNBCUUPFunction", "GNBCUUPFunction"); - reverseHashedNames.put("NRCellDU", "NRCellDU"); - reverseHashedNames.put("NRSectorCarrier", "NRSectorCarrier"); - reverseHashedNames.put("CloudNativeApplication", "CloudNativeApplication"); - reverseHashedNames.put("AntennaCapability", "AntennaCapability"); - reverseHashedNames.put("Sector", "Sector"); - reverseHashedNames.put("AntennaModule", "AntennaModule"); - - reverseHashedNames.put("ANTENNAMODULE_INSTALLED_AT_SITE", "ANTENNAMODULE_INSTALLED_AT_SITE"); - reverseHashedNames.put("GNBDUFUNCTION_PROVIDES_NRCELLDU", "GNBDUFUNCTION_PROVIDES_NRCELLDU"); - reverseHashedNames.put("GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); - reverseHashedNames.put("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - reverseHashedNames.put("NRSECTORCARRIER_USES_ANTENNACAPABILITY", "NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - reverseHashedNames.put("SECTOR_GROUPS_ANTENNAMODULE", "SECTOR_GROUPS_ANTENNAMODULE"); - reverseHashedNames.put("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - - reverseHashedNames.put("id", "id"); - reverseHashedNames.put("fdn", "fdn"); - reverseHashedNames.put("cmId", "cmId"); - reverseHashedNames.put("CD_sourceIds", "CD_sourceIds"); - - // GNBDUFUNCTION - reverseHashedNames.put("dUpLMNId", "dUpLMNId"); - reverseHashedNames.put("gNBIdLength", "gNBIdLength"); - reverseHashedNames.put("gNBId", "gNBId"); - reverseHashedNames.put("gNBDUId", "gNBDUId"); - reverseHashedNames.put("REL_FK_managed-by-managedElement", "REL_FK_managed-by-managedElement"); - reverseHashedNames.put("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", - "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - - //NRCELLDU - reverseHashedNames.put("nCI", "nCI"); - reverseHashedNames.put("cellLocalId", "cellLocalId"); - reverseHashedNames.put("nRPCI", "nRPCI"); - reverseHashedNames.put("nRTAC", "nRTAC"); - reverseHashedNames.put("REL_FK_grouped-by-sector", "REL_FK_grouped-by-sector"); - reverseHashedNames.put("REL_ID_SECTOR_GROUPS_NRCELLDU", "REL_ID_SECTOR_GROUPS_NRCELLDU"); - reverseHashedNames.put("REL_FK_provided-by-gnbduFunction", "REL_FK_provided-by-gnbduFunction"); - reverseHashedNames.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU"); - reverseHashedNames.put("REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU", - "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU"); - - //NrSectorCarrier - reverseHashedNames.put("frequencyDL", "frequencyDL"); - reverseHashedNames.put("frequencyUL", "frequencyUL"); - reverseHashedNames.put("arfcnUL", "arfcnUL"); - reverseHashedNames.put("essScLocalId", "essScLocalId"); - reverseHashedNames.put("arfcnDL", "arfcnDL"); - reverseHashedNames.put("REL_FK_used-by-nrCellDu", "REL_FK_used-by-nrCellDu"); - reverseHashedNames.put("REL_ID_NRCELLDU_USES_NRSECTORCARRIER", "REL_ID_NRCELLDU_USES_NRSECTORCARRIER"); - reverseHashedNames.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); - reverseHashedNames.put("REL_FK_used-antennaCapability", "REL_FK_used-antennaCapability"); - reverseHashedNames.put("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY", - "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY"); - //CloudNativeApplication - reverseHashedNames.put("name", "name"); - reverseHashedNames.put("REL_FK_realised-managedElement", "REL_FK_realised-managedElement"); - reverseHashedNames.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", - "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION"); - reverseHashedNames.put("REL_FK_comprised-by-cloudNativeSystem", "REL_FK_comprised-by-cloudNativeSystem"); - reverseHashedNames.put("REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", - "REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION"); - reverseHashedNames.put("REL_FK_deployed-on-namespace", "REL_FK_deployed-on-namespace"); - reverseHashedNames.put("REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE", - "REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE"); - - //AntennaCapability - reverseHashedNames.put("nRFqBands", "nRFqBands"); - reverseHashedNames.put("eUtranFqBands", "eUtranFqBands"); - reverseHashedNames.put("geranFqBands", "geranFqBands"); - reverseHashedNames.put("REL_FK_used-by-lteSectorCarrier", "REL_FK_used-by-lteSectorCarrier"); - - //Sector - reverseHashedNames.put("sectorId", "sectorId"); - reverseHashedNames.put("azimuth", "azimuth"); - - //AntennaModule - reverseHashedNames.put("positionWithinSector", "positionWithinSector"); - reverseHashedNames.put("antennaModelNumber", "antennaModelNumber"); - reverseHashedNames.put("electricalAntennaTilt", "electricalAntennaTilt"); - reverseHashedNames.put("mechanicalAntennaTilt", "mechanicalAntennaTilt"); - reverseHashedNames.put("totalTilt", "totalTilt"); - reverseHashedNames.put("mechanicalAntennaBearing", "mechanicalAntennaBearing"); - reverseHashedNames.put("REL_ID_SECTOR_GROUPS_ANTENNAMODULE", "REL_ID_SECTOR_GROUPS_ANTENNAMODULE"); - reverseHashedNames.put("REL_FK_installed-at-site", "REL_FK_installed-at-site"); - reverseHashedNames.put("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE"); - - //GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION - reverseHashedNames.put("aSide_GNBDUFunction", "aSide_GNBDUFunction"); - reverseHashedNames.put("bSide_CloudNativeApplication", "bSide_CloudNativeApplication"); - - //ANTENNAMODULE_REALISED_BY_ANTENNAMODULE - reverseHashedNames.put("aSide_AntennaModule", "aSide_AntennaModule"); - reverseHashedNames.put("bSide_AntennaModule", "bSide_AntennaModule"); + List> hashInfo = extractModelInfoFromSqlFile("hash_info"); + hashInfo.forEach(l -> { + hashedNames.put(l.get(0), l.get(1)); + reverseHashedNames.put(l.get(1), l.get(0)); + }); BidiDbNameMapper.initialize(hashedNames, reverseHashedNames); } @Override protected void loadModules() { - Module ranLogicalModule = Module.builder().name("o-ran-smo-teiv-ran").namespace("urn:o-ran:smo-teiv-ran").domain( - "RAN").build(); - - Module ranEquipmentModule = Module.builder().name("o-ran-smo-teiv-equipment").namespace( - "urn:o-ran:smo-teiv-equipment").domain("EQUIPMENT").build(); + List modules = new ArrayList<>(); + + List> moduleReference = extractModelInfoFromSqlFile("module_reference"); + moduleReference.forEach(l -> { + String domain = l.get(2); + if (domain.equals("\\N")) { + domain = null; + } + + String name = l.get(0); + String namespace = l.get(1); + String content = l.get(5); + final Module.ModuleBuilder moduleBuilder = Module.builder().name(name).namespace(namespace).domain(domain) + .content(content); + final String includedModuleNames = l.get(3).replaceAll("[\\[\\]\"\\s]", ""); + if (!includedModuleNames.isEmpty()) { + moduleBuilder.includedModuleNames(List.of(includedModuleNames.split(","))).build(); + } + modules.add(moduleBuilder.build()); + }); - Module ranCloudModule = Module.builder().name("o-ran-smo-teiv-cloud").namespace("urn:o-ran:smo-teiv-cloud").domain( - "CLOUD").build(); - - Module ranLogicalToEquipmentModule = Module.builder().name("o-ran-smo-teiv-equipment-to-ran").namespace( - "urn:o-ran:smo-teiv-equipment-to-ran").domain("EQUIPMENT_TO_RAN").includedModuleName("o-ran-smo-teiv-ran") - .includedModuleName("o-ran-smo-teiv-equipment").build(); - - Module ranLogicalToCloudModule = Module.builder().name("o-ran-smo-teiv-cloud-to-ran").namespace( - "urn:o-ran:smo-teiv-cloud-to-ran").domain("CLOUD_TO_RAN").includedModuleName("o-ran-smo-teiv-ran") - .includedModuleName("o-ran-smo-teiv-cloud").build(); - - Module ranOamModule = Module.builder().name("o-ran-smo-teiv-oam").namespace("urn:o-ran:smo-teiv-oam").domain("OAM") - .build(); - - Module ranOamToLogicalModule = Module.builder().name("o-ran-smo-teiv-oam-to-ran").namespace( - "urn:o-ran:smo-teiv-oam-to-ran").domain("OAM_TO_RAN").includedModuleName("o-ran-smo-teiv-oam") - .includedModuleName("o-ran-smo-teiv-ran").build(); - - Module ranOamToCloudModule = Module.builder().name("o-ran-smo-teiv-oam-to-cloud").namespace( - "urn:o-ran:smo-teiv-oam-to-cloud").domain("OAM_TO_CLOUD").includedModuleName("o-ran-smo-teiv-oam") - .includedModuleName("o-ran-smo-teiv-cloud").build(); - - List modules = List.of(ranLogicalModule, ranEquipmentModule, ranCloudModule, ranLogicalToEquipmentModule, - ranLogicalToCloudModule, ranOamModule, ranOamToLogicalModule, ranOamToCloudModule); Map moduleMap = new HashMap<>(); modules.forEach(module -> moduleMap.put(module.getName(), module)); + moduleMap.put(TEIV_DOMAIN, Module.builder().name(TEIV_DOMAIN).namespace(TEIV_DOMAIN).domain(TEIV_DOMAIN) + .includedModuleNames(moduleMap.keySet()).build()); SchemaRegistry.initializeModules(moduleMap); } @Override protected void loadEntityTypes() { - EntityType gnbduFunction = EntityType.builder().name("GNBDUFunction").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).fields(getGnbduFunctionFields()).build(); - EntityType gnbcuupFunction = EntityType.builder().name("GNBCUUPFunction").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).fields(getGnbcuupFunctionFields()).build(); - - EntityType nrCellDU = EntityType.builder().name("NRCellDU").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).fields(getNrCellDuFields()).build(); - - EntityType nrSectorCarrier = EntityType.builder().name("NRSectorCarrier").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).fields(getNrSectorCarrierFields()).build(); - - EntityType gNBCUCPFunction = EntityType.builder().name("GNBCUCPFunction").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-cloud-to-ran")).fields(getGNBCUCPFunctionFields()).build(); - - EntityType managedElement = EntityType.builder().name("ManagedElement").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-oam")).fields(getManagedElementFields()).build(); - - EntityType cloudNativeApplication = EntityType.builder().name("CloudNativeApplication").module(SchemaRegistry - .getModuleByName("o-ran-smo-teiv-cloud")).fields(getCloudNativeApplicationFields()).build(); + List entityTypes = new ArrayList<>(); - EntityType antennaCapability = EntityType.builder().name("AntennaCapability").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).fields(getAntennaCapabilityFields()).build(); + List> entityInfo = extractModelInfoFromSqlFile("entity_info"); + entityInfo.forEach(l -> { + String storedAt = l.get(0); + String name = l.get(1); + String moduleReferenceName = l.get(2); + entityTypes.add(EntityType.builder().name(name).tableName(storedAt).module(SchemaRegistry.getModuleByName( + moduleReferenceName)).fields(extractDataFieldsFromSqlFile(storedAt)).build()); + }); - EntityType sector = EntityType.builder().name("Sector").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment-to-ran")).fields(getSectorFields()).build(); - - EntityType antennaModule = EntityType.builder().name("AntennaModule").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment")).fields(getAntennaModuleFields()).build(); - - EntityType site = EntityType.builder().name("Site").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment")).fields(getSiteFields()).build(); - - EntityType cloudSite = EntityType.builder().name("CloudSite").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-cloud")).fields(getCloudSiteFields()).build(); - - EntityType nodeCluster = EntityType.builder().name("NodeCluster").module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-cloud")).fields(getNodeClusterFields()).build(); - - List entityTypes = List.of(gnbduFunction, gnbcuupFunction, nrCellDU, nrSectorCarrier, gNBCUCPFunction, - managedElement, cloudNativeApplication, antennaCapability, sector, antennaModule, site, cloudSite, - nodeCluster); - Map entityTypeMap = new HashMap<>(); - entityTypes.forEach(entityType -> entityTypeMap.put(entityType.getName(), entityType)); - SchemaRegistry.initializeEntityTypes(entityTypeMap); + SchemaRegistry.initializeEntityTypes(entityTypes); } @Override protected void loadRelationTypes() { - - RelationType antennaModuleInstalledAtSite = RelationType.builder().name("ANTENNAMODULE_INSTALLED_AT_SITE") - .aSideAssociation(getRelationshipAssociation("installed-at-site", 0, 9223372036854775807L)).aSide( - SchemaRegistry.getEntityTypeByName("AntennaModule")).bSideAssociation(getRelationshipAssociation( - "installed-antennaModule", 0, 1)).bSide(SchemaRegistry.getEntityTypeByName("Site")) - .connectsSameEntity(false).relationshipStorageLocation(A_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment")).build(); - - RelationType gnbduFunctionProvidesNrcelldu = RelationType.builder().name("GNBDUFUNCTION_PROVIDES_NRCELLDU") - .aSideAssociation(getRelationshipAssociation("provided-nrCellDu", 1, 1)).aSide(SchemaRegistry - .getEntityTypeByName("GNBDUFunction")).bSideAssociation(getRelationshipAssociation( - "provided-by-gnbduFunction", 0, 9223372036854775807L)).bSide(SchemaRegistry - .getEntityTypeByName("NRCellDU")).connectsSameEntity(false) - .relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName("o-ran-smo-teiv-ran")).build(); - - RelationType gnbduFunctionProvidesNrsectorcarrier = RelationType.builder().name( - "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").aSideAssociation(getRelationshipAssociation( - "provided-nrSectorCarrier", 1, 1)).aSide(SchemaRegistry.getEntityTypeByName("GNBDUFunction")) - .bSideAssociation(getRelationshipAssociation("provided-by-gnbduFunction", 0, 9223372036854775807L)).bSide( - SchemaRegistry.getEntityTypeByName("NRSectorCarrier")).connectsSameEntity(false) - .relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName("o-ran-smo-teiv-ran")).build(); - - RelationType gnbduFunctionRealisedByCloudnativeapplication = RelationType.builder().name( - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION").aSideAssociation(getRelationshipAssociation( - "realised-by-cloudNativeApplication", 0, 9223372036854775807L)).aSide(SchemaRegistry - .getEntityTypeByName("GNBDUFunction")).bSideAssociation(getRelationshipAssociation( - "realised-gnbduFunction", 0, 9223372036854775807L)).bSide(SchemaRegistry - .getEntityTypeByName("CloudNativeApplication")).connectsSameEntity(false) - .relationshipStorageLocation(RELATION).module(SchemaRegistry.getModuleByName("o-ran-smo-teiv-cloud-to-ran")) - .build(); - - RelationType nrSectorcarrierUsesAntennacapability = RelationType.builder().name( - "NRSECTORCARRIER_USES_ANTENNACAPABILITY").aSideAssociation(getRelationshipAssociation( - "used-antennaCapability", 0, 9223372036854775807L)).aSide(SchemaRegistry.getEntityTypeByName( - "NRSectorCarrier")).bSideAssociation(getRelationshipAssociation("used-by-nrSectorCarrier", - 0, 1)).bSide(SchemaRegistry.getEntityTypeByName("AntennaCapability")) - .connectsSameEntity(false).relationshipStorageLocation(A_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).build(); - - RelationType sectorGroupsAntennamodule = RelationType.builder().name("SECTOR_GROUPS_ANTENNAMODULE") - .aSideAssociation(getRelationshipAssociation("grouped-antennaModule", 0, 1)).aSide(SchemaRegistry - .getEntityTypeByName("Sector")).bSideAssociation(getRelationshipAssociation("grouped-by-sector", 0, - 9223372036854775807L)).bSide(SchemaRegistry.getEntityTypeByName("AntennaModule")) - .connectsSameEntity(false).relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment-to-ran")).build(); - - RelationType sectorGroupsNrcelldu = RelationType.builder().name("SECTOR_GROUPS_NRCELLDU").aSideAssociation( - getRelationshipAssociation("grouped-nrCellDu", 0, 1)).aSide(SchemaRegistry.getEntityTypeByName("Sector")) - .bSideAssociation(getRelationshipAssociation("grouped-by-sector", 0, 9223372036854775807L)).bSide( - SchemaRegistry.getEntityTypeByName("NRCellDU")).connectsSameEntity(false) - .relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment-to-ran")).build(); - - RelationType nrCellDuUsesNrSectorcarrier = RelationType.builder().name("NRCELLDU_USES_NRSECTORCARRIER") - .aSideAssociation(getRelationshipAssociation("used-nrSectorCarrier", 0, 1)).aSide(SchemaRegistry - .getEntityTypeByName("NRCellDU")).bSideAssociation(getRelationshipAssociation("used-by-nrCellDu", 0, - 9223372036854775807L)).bSide(SchemaRegistry.getEntityTypeByName("NRSectorCarrier")) - .connectsSameEntity(false).relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-ran")).build(); - - RelationType managedElementManagesGNBCUCPFunction = RelationType.builder().name( - "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION").aSideAssociation(getRelationshipAssociation( - "managed-gnbcucpFunction", 1, 1)).aSide(SchemaRegistry.getEntityTypeByName("ManagedElement")) - .bSideAssociation(getRelationshipAssociation("managed-by-managedElement", 0, 9223372036854775807L)).bSide( - SchemaRegistry.getEntityTypeByName("GNBCUCPFunction")).connectsSameEntity(false) - .relationshipStorageLocation(B_SIDE).module(SchemaRegistry.getModuleByName("o-ran-smo-teiv-oam-to-ran")) - .build(); - - RelationType nodeClusterLocatedAtCloudSite = RelationType.builder().name("NODECLUSTER_LOCATED_AT_CLOUDSITE") - .aSideAssociation(getRelationshipAssociation("located-at-cloudSite", 0, 9223372036854775807L)).aSide( - SchemaRegistry.getEntityTypeByName("NodeCluster")).bSideAssociation(getRelationshipAssociation( - "location-of-nodeCluster", 1, 1)).bSide(SchemaRegistry.getEntityTypeByName("CloudSite")) - .connectsSameEntity(false).relationshipStorageLocation(A_SIDE).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-cloud")).build(); - - RelationType antennaModuleRealisedByAntennaModule = RelationType.builder().name( - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE").aSideAssociation(getRelationshipAssociation( - "realised-by-antennaModule", 0, 9223372036854775807L)).aSide(SchemaRegistry.getEntityTypeByName( - "AntennaModule")).bSideAssociation(getRelationshipAssociation("realised-antennaModule", 0, - 9223372036854775807L)).bSide(SchemaRegistry.getEntityTypeByName("AntennaModule")) - .connectsSameEntity(true).relationshipStorageLocation(RELATION).module(SchemaRegistry.getModuleByName( - "o-ran-smo-teiv-equipment")).build(); - - List relationTypes = List.of(gnbduFunctionProvidesNrcelldu, gnbduFunctionProvidesNrsectorcarrier, - gnbduFunctionRealisedByCloudnativeapplication, nrSectorcarrierUsesAntennacapability, - sectorGroupsAntennamodule, sectorGroupsNrcelldu, nrCellDuUsesNrSectorcarrier, - managedElementManagesGNBCUCPFunction, nodeClusterLocatedAtCloudSite, antennaModuleInstalledAtSite, - antennaModuleRealisedByAntennaModule); - Map relationTypeMap = new HashMap<>(); - relationTypes.forEach(relationType -> relationTypeMap.put(relationType.getName(), relationType)); - SchemaRegistry.initializeRelationTypes(relationTypeMap); - } - - private Map getGnbduFunctionFields() { - Map fields = new HashMap<>(); - fields.put("gNBDUId", BIGINT); - fields.put("gNBId", BIGINT); - fields.put("gNBIdLength", BIGINT); - fields.put("dUpLMNId", CONTAINER); - fields.put("id", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("fdn", PRIMITIVE); - fields.put("REL_FK_managed-by-managedElement", PRIMITIVE); - fields.put("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", PRIMITIVE); - - return fields; - } - - private Map getGnbcuupFunctionFields() { - Map fields = new HashMap<>(); - fields.put("gNBId", BIGINT); - fields.put("gNBIdLength", BIGINT); - fields.put("id", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("fdn", PRIMITIVE); - fields.put("REL_FK_managed-by-managedElement", PRIMITIVE); - fields.put("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", PRIMITIVE); - - return fields; - } - - private Map getNrCellDuFields() { - Map fields = new HashMap<>(); - fields.put("fdn", PRIMITIVE); - fields.put("nCI", BIGINT); - fields.put("cellLocalId", BIGINT); - fields.put("id", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("nRPCI", BIGINT); - fields.put("nRTAC", BIGINT); - fields.put("REL_FK_grouped-by-sector", PRIMITIVE); - fields.put("REL_ID_SECTOR_GROUPS_NRCELLDU", PRIMITIVE); - fields.put("REL_FK_provided-by-gnbduFunction", PRIMITIVE); - fields.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU", PRIMITIVE); - - return fields; - } - - private Map getNrSectorCarrierFields() { - Map fields = new HashMap<>(); - fields.put("frequencyDL", BIGINT); - fields.put("fdn", PRIMITIVE); - fields.put("frequencyUL", BIGINT); - fields.put("arfcnUL", BIGINT); - fields.put("id", PRIMITIVE); - fields.put("essScLocalId", BIGINT); - fields.put("cmId", CONTAINER); - fields.put("arfcnDL", BIGINT); - fields.put("REL_FK_used-by-nrCellDu", PRIMITIVE); - fields.put("REL_ID_NRCELLDU_USES_NRSECTORCARRIER", PRIMITIVE); - fields.put("REL_FK_provided-by-gnbduFunction", PRIMITIVE); - fields.put("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", PRIMITIVE); - fields.put("REL_FK_used-antennaCapability", PRIMITIVE); - fields.put("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY", PRIMITIVE); - - return fields; - } - - private Map getCloudNativeApplicationFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("name", PRIMITIVE); - fields.put("REL_FK_realised-managedElement", PRIMITIVE); - fields.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", PRIMITIVE); - fields.put("REL_FK_comprised-by-cloudNativeSystem", PRIMITIVE); - fields.put("REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", PRIMITIVE); - - return fields; - } - - private Map getAntennaCapabilityFields() { - Map fields = new HashMap<>(); - fields.put("nRFqBands", CONTAINER); - fields.put("id", PRIMITIVE); - fields.put("eUtranFqBands", CONTAINER); - fields.put("cmId", CONTAINER); - fields.put("geranFqBands", CONTAINER); - fields.put("fdn", PRIMITIVE); - fields.put("REL_FK_used-by-lteSectorCarrier", PRIMITIVE); - - return fields; - } - - private Map getSectorFields() { - Map fields = new HashMap<>(); - fields.put("sectorId", BIGINT); - fields.put("id", PRIMITIVE); - fields.put("azimuth", DECIMAL); - - return fields; - } - - private Map getAntennaModuleFields() { - Map fields = new HashMap<>(); - fields.put("positionWithinSector", PRIMITIVE); - fields.put("antennaModelNumber", PRIMITIVE); - fields.put("electricalAntennaTilt", BIGINT); - fields.put("mechanicalAntennaTilt", BIGINT); - fields.put("totalTilt", BIGINT); - fields.put("id", PRIMITIVE); - fields.put("mechanicalAntennaBearing", BIGINT); - fields.put("fdn", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("REL_FK_grouped-by-sector", PRIMITIVE); - fields.put("REL_ID_SECTOR_GROUPS_ANTENNAMODULE", PRIMITIVE); - fields.put("REL_FK_installed-at-site", PRIMITIVE); - fields.put("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE", PRIMITIVE); - - return fields; - } - - private Map getSiteFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("name", PRIMITIVE); - - return fields; - } - - private Map getCloudSiteFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("name", PRIMITIVE); - fields.put("geo-location", GEOGRAPHIC); - - return fields; - } - - private Map getNodeClusterFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("name", PRIMITIVE); - - return fields; - } - - private Map getManagedElementFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("fdn", PRIMITIVE); - fields.put("cmId", CONTAINER); - fields.put("REL_FK_deployed-as-cloudNativeSystem", PRIMITIVE); - fields.put("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", CONTAINER); - - return fields; - } - - private Map getGNBCUCPFunctionFields() { - Map fields = new HashMap<>(); - fields.put("id", PRIMITIVE); - fields.put("fdn", PRIMITIVE); - fields.put("pLMNId", CONTAINER); - fields.put("gNBCUName", PRIMITIVE); - fields.put("gNBId", BIGINT); - fields.put("cmId", CONTAINER); - fields.put("gNBIdLength", BIGINT); - fields.put("REL_FK_managed-by-managedElement", PRIMITIVE); - fields.put("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", CONTAINER); - - return fields; + List relationTypes = new ArrayList<>(); + List> relationshipInfo = extractModelInfoFromSqlFile("relationship_info"); + relationshipInfo.forEach(l -> { + String name = l.get(0); + String aSideAssociationName = l.get(1); + String aSideMOType = l.get(2); + long aSideMinCardinality = Long.parseLong(l.get(4)); + long aSideMaxCardinality = Long.parseLong(l.get(5)); + String bSideAssociationName = l.get(6); + String bSideMOType = l.get(7); + long bSideMinCardinality = Long.parseLong(l.get(9)); + long bSideMaxCardinality = Long.parseLong(l.get(10)); + RelationshipDataLocation relationshipDataLocation = RelationshipDataLocation.valueOf(l.get(13)); + boolean connectSameEntity = Boolean.parseBoolean(l.get(12)); + String storedAt = l.get(14); + String moduleReferenceName = l.get(15); + + relationTypes.add(RelationType.builder().name(name).aSideAssociation(getRelationshipAssociation( + aSideAssociationName, aSideMinCardinality, aSideMaxCardinality)).aSide(SchemaRegistry + .getEntityTypeByName(aSideMOType)).bSideAssociation(getRelationshipAssociation( + bSideAssociationName, bSideMinCardinality, bSideMaxCardinality)).bSide(SchemaRegistry + .getEntityTypeByName(bSideMOType)).connectsSameEntity(connectSameEntity) + .relationshipStorageLocation(relationshipDataLocation).tableName(storedAt).module(SchemaRegistry + .getModuleByName(moduleReferenceName)).build()); + }); + + SchemaRegistry.initializeRelationTypes(relationTypes); } private Association getRelationshipAssociation(String associationName, long minCardinality, long maxCardinality) { return Association.builder().name((associationName)).minCardinality(minCardinality).maxCardinality(maxCardinality) .build(); } + + private List> extractModelInfoFromSqlFile(String tableName) { + List> modelInfo = new ArrayList<>(); + try { + BufferedReader reader = new BufferedReader(new FileReader( + "src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql")); + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("COPY ties_model." + tableName)) { + while (!(line = reader.readLine()).startsWith("\\.")) { + List l = List.of(line.split("\t")); + modelInfo.add(l); + } + } + } + reader.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return modelInfo; + } + + private Map extractDataFieldsFromSqlFile(String tableName) { + Map dataFields = new HashMap<>(); + try { + BufferedReader reader = new BufferedReader(new FileReader( + "src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql")); + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("CREATE TABLE IF NOT EXISTS ties_data.\"" + tableName + "\"")) { + while (!(line = reader.readLine()).startsWith(");")) { + List l = List.of(line.trim().replace("\t\t\t", "\t").replaceAll("[\",]", "").split("\t")); + String fieldName = l.get(0); + String dataType = l.get(1); + switch (dataType) { + case "TEXT" -> dataFields.put(fieldName, PRIMITIVE); + case "INTEGER" -> dataFields.put(fieldName, INTEGER); + case "BIGINT" -> dataFields.put(fieldName, BIGINT); + case "DECIMAL" -> dataFields.put(fieldName, DECIMAL); + case "jsonb" -> dataFields.put(fieldName, CONTAINER); + case "geography" -> dataFields.put(fieldName, GEOGRAPHIC); + } + } + } + } + reader.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return dataFields; + } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryContainerizedTest.java b/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryContainerizedTest.java deleted file mode 100644 index 1cef7b2..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryContainerizedTest.java +++ /dev/null @@ -1,402 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.schema; - -import static org.oran.smo.teiv.schema.RelationshipDataLocation.A_SIDE; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; -import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; -import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; -import static org.oran.smo.teiv.utils.TiesConstants.TEIV_DOMAIN; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; -import static org.jooq.impl.DSL.field; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.sql.DataSource; - -import org.jooq.DSLContext; -import org.jooq.JSONB; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.jdbc.DataSourceBuilder; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.oran.smo.teiv.db.TestPostgresqlContainer; -import org.oran.smo.teiv.exception.TiesException; - -class SchemaRegistryContainerizedTest { - public static TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); - private static DSLContext dslContext; - - @BeforeAll - public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { - String url = postgreSQLContainer.getJdbcUrl(); - TestPostgresqlContainer.loadSampleData(); - DataSource ds = DataSourceBuilder.create().url(url).username("test").password("test").build(); - dslContext = DSL.using(ds, SQLDialect.POSTGRES); - PostgresSchemaLoader postgresSchemaLoader = new PostgresSchemaLoader(dslContext, new ObjectMapper()); - postgresSchemaLoader.loadSchemaRegistry(); - } - - @BeforeEach - public void deleteAll() { - dslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach(t -> dslContext - .truncate(t).cascade().execute()); - } - - @Test - void testGetModulesByName() { - //given - String expectedName = "o-ran-smo-teiv-cloud-to-ran"; - String expectedNamespace = "urn:o-ran:smo-teiv-cloud-to-ran"; - String expectedDomain = "CLOUD_TO_RAN"; - List expectedIncludedModules = List.of("o-ran-smo-teiv-cloud", "o-ran-smo-teiv-ran"); - //when - Module logicalToCloud = SchemaRegistry.getModuleByName("o-ran-smo-teiv-cloud-to-ran"); - //then - assertEquals(9, SchemaRegistry.getModuleRegistry().size()); - assertTrue(SchemaRegistry.getModuleRegistry().containsValue(logicalToCloud)); - assertEquals(expectedName, logicalToCloud.getName()); - assertEquals(expectedNamespace, logicalToCloud.getNamespace()); - assertEquals(expectedDomain, logicalToCloud.getDomain()); - assertEquals(expectedIncludedModules, logicalToCloud.getIncludedModuleNames()); - assertThrows(TiesException.class, () -> SchemaRegistry.getModuleByName("invalid-module")); - } - - @Test - void testGetDomainsForModules() { - //given - - Set expectedDomains = Set.of(TEIV_DOMAIN, "OAM_TO_CLOUD", "EQUIPMENT_TO_RAN", "RAN", "OAM", "CLOUD", - "EQUIPMENT", "CLOUD_TO_RAN", "OAM_TO_RAN"); - //when - Set actualDomains = SchemaRegistry.getDomains(); - //then - assertEquals(expectedDomains, actualDomains); - } - - @Test - void testRootDomainIncludesAllAvailableDomains() { - //given - Set availableDomains = SchemaRegistry.getDomains(); - availableDomains.remove(TEIV_DOMAIN); - //when - List rootIncludedDomains = SchemaRegistry.getIncludedDomains(TEIV_DOMAIN); - //then - assertEquals(availableDomains.size(), rootIncludedDomains.size()); - assertTrue(availableDomains.containsAll(rootIncludedDomains)); - } - - @Test - void testGetModuleByDomainTrowsUnknownDomainException() { - assertThrows(TiesException.class, () -> SchemaRegistry.getModuleByDomain("throwError")); - } - - //Entities - @Test - void testGetEntityNames() { - //given - Set expectedEntityName = Set.of("Site", "ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt", - "ENodeBFunction", "CloudNativeApplication", "AntennaModule", "Sector", - "Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "NRCellDU", "LTESectorCarrier", - "ManagedElement", "NRCellCU", "NRSectorCarrier", "PhysicalNetworkAppliance", "Namespace", "GNBCUUPFunction", - "NodeCluster", "CloudNativeSystem", "NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU", - "CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", - "CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE", "GNBDUFunction", "CloudSite", - "EUtranCell", "GNBCUCPFunction", "AntennaCapability", "TestEntityA", "TestEntityB"); - //when - Set actualEntityName = SchemaRegistry.getEntityNames(); - //then - assertEquals(expectedEntityName.size(), actualEntityName.size()); - assertEquals(expectedEntityName, actualEntityName); - } - - @Test - void testGetTableNameForEntity() { - //given - EntityType gnbduFunction = SchemaRegistry.getEntityTypeByName("GNBDUFunction"); - //then - assertEquals("ties_data.\"GNBDUFunction\"", gnbduFunction.getTableName()); - } - - @Test - void testGetFieldsForEntity() { - //given - EntityType gnbduFunction = SchemaRegistry.getEntityTypeByName("GNBDUFunction"); - //then - assertEquals(Set.of(field("dUpLMNId", JSONB.class).as("dUpLMNId"), field("gNBDUId").as("gNBDUId"), field("gNBId") - .as("gNBId"), field("gNBIdLength").as("gNBIdLength"), field("cmId", JSONB.class).as("cmId"), field("fdn") - .as("fdn"), field("id").as("id"), field("CD_sourceIds").as("CD_sourceIds")), new HashSet<>( - gnbduFunction.getAllFieldsWithId())); - } - - @Test - void testGetAttrColumnsForEntity() { - //given - List expectedColumns = List.of("ties_data.\"GNBDUFunction\".\"gNBDUId\"", - "ties_data.\"GNBDUFunction\".\"gNBId\"", "ties_data.\"GNBDUFunction\".\"gNBIdLength\"", - "ties_data.\"GNBDUFunction\".\"dUpLMNId\"", "ties_data.\"GNBDUFunction\".\"cmId\"", - "ties_data.\"GNBDUFunction\".\"fdn\"", "ties_data.\"GNBDUFunction\".\"id\""); - EntityType gnbduFunction = SchemaRegistry.getEntityTypeByName("GNBDUFunction"); - //then - List columns = gnbduFunction.getAttributeColumnsWithId(); - assertEquals(expectedColumns.size(), columns.size()); - assertTrue(expectedColumns.containsAll(columns)); - } - - @Test - void testGetAttrColumnsForEntityWithLongNames() { - //given - List expectedColumns = List.of("ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"gNBDUId\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"gNBId\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"gNBIdLength\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"dUpLMNId\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"cmId\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"3786A6CA64C9422F9E7FC35B7B039F345BBDDA65\"", - "ties_data.\"7D7AACEBB0E4E4732835BA4BFE708DDD3738962D\".\"id\""); - EntityType gnbduFunction = SchemaRegistry.getEntityTypeByName( - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"); - //then - List columns = gnbduFunction.getAttributeColumnsWithId(); - assertEquals(expectedColumns.size(), columns.size()); - assertTrue(expectedColumns.containsAll(columns)); - } - - @Test - void testGetEntityTypesByDomain() { - //given - List expectedEntities = List.of("Site", "ENodeBFunction", "AntennaModule", "Sector", "NRCellDU", - "LTESectorCarrier", "NRCellCU", "NRSectorCarrier", "PhysicalNetworkAppliance", "GNBCUUPFunction", - "GNBDUFunction", "EUtranCell", "GNBCUCPFunction", "AntennaCapability", - "GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", - "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE", - "NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU", "TestEntityA", "TestEntityB"); - //when - List ranLogicalToEquipmentEntityTypes = SchemaRegistry.getEntityNamesByDomain("EQUIPMENT_TO_RAN"); - //then - assertEquals(expectedEntities.size(), ranLogicalToEquipmentEntityTypes.size()); - assertTrue(expectedEntities.containsAll(ranLogicalToEquipmentEntityTypes)); - } - - //Relations - @Test - void getRelationNames() { - //when - SchemaRegistry.getRelationNames(); - //then - assertEquals(41, SchemaRegistry.getRelationNames().size()); - } - - @Test - void testGetRelationTypeByName() { - //when - RelationType managedElementManagesEnodebfunction = SchemaRegistry.getRelationTypeByName( - "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION"); - //then - assertTrue(SchemaRegistry.getRelationTypes().contains(managedElementManagesEnodebfunction)); - Association expectedAssociation = new Association("managed-enodebFunction", 1, 1); - assertEquals(expectedAssociation.toString(), managedElementManagesEnodebfunction.getASideAssociation().toString()); - - } - - @Test - void testGetRelationTypesByEntityType() { - //given - List expectedRelationsList = new ArrayList<>(); - expectedRelationsList.add(SchemaRegistry.getRelationTypeByName( - "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")); - expectedRelationsList.add(SchemaRegistry.getRelationTypeByName("GNBCUCPFUNCTION_PROVIDES_NRCELLCU")); - expectedRelationsList.add(SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION")); - //then - assertEquals(3, SchemaRegistry.getRelationTypesByEntityName("GNBCUCPFunction").size()); - assertTrue(SchemaRegistry.getRelationTypesByEntityName("GNBCUCPFunction").containsAll(expectedRelationsList)); - } - - @Test - void testGetFullyQualifiedNameForRelation() { - //given - RelationType gnbduFunctionRealisedByCloudnativeapplication = SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - //then - assertEquals("o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", - gnbduFunctionRealisedByCloudnativeapplication.getFullyQualifiedName()); - } - - @Test - void testGetTableNameForRelation() { - //given - String expectedManyToMany = "ties_data.\"GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\""; - String expectedOneToOne = "ties_data.\"ManagedElement\""; - String expectedOneToMany = "ties_data.\"GNBDUFunction\""; - String expectedManyToOne = "ties_data.\"NodeCluster\""; - String expectedRelConnectingSameEntity = "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\""; - //when - RelationType manyToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - RelationType oneToOne = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - RelationType manyToOne = SchemaRegistry.getRelationTypeByName("NODECLUSTER_LOCATED_AT_CLOUDSITE"); - RelationType relConnectingSameEntity = SchemaRegistry.getRelationTypeByName( - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - //then - assertEquals(expectedManyToMany, manyToMany.getTableName()); - assertEquals(expectedOneToOne, oneToOne.getTableName()); - assertEquals(expectedOneToMany, oneToMany.getTableName()); - assertEquals(expectedManyToOne, manyToOne.getTableName()); - assertEquals(expectedRelConnectingSameEntity, relConnectingSameEntity.getTableName()); - } - - @Test - void testGetRelationshipDataLocationForRelation() { - //when - RelationType manyToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - RelationType oneToOne = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - RelationType manyToOne = SchemaRegistry.getRelationTypeByName("NODECLUSTER_LOCATED_AT_CLOUDSITE"); - RelationType relConnectingSameEntity = SchemaRegistry.getRelationTypeByName( - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); - //then - assertEquals(RELATION, manyToMany.getRelationshipStorageLocation()); - assertEquals(A_SIDE, oneToOne.getRelationshipStorageLocation()); - assertEquals(B_SIDE, oneToMany.getRelationshipStorageLocation()); - assertEquals(A_SIDE, manyToOne.getRelationshipStorageLocation()); - assertEquals(RELATION, relConnectingSameEntity.getRelationshipStorageLocation()); - } - - @Test - void testGetIdColumnNameRelationTest() { - //given - String expectedManyToManyId = "id"; - String expectedOneToManyId = "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"; - //when - RelationType manyToManyRelation = SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - //then - assertEquals(expectedManyToManyId, manyToManyRelation.getIdColumnName()); - assertEquals(expectedOneToManyId, oneToMany.getIdColumnName()); - } - - @Test - void testGetASideColumnNameForRelationType() { - //given - String expectedManyToMAny = "aSide_GNBDUFunction"; - String expectedOneToOne = "id"; - String expectedOneToMany = "REL_FK_managed-by-managedElement"; - //when - RelationType manyToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - RelationType oneToOne = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - //then - assertEquals(expectedManyToMAny, manyToMany.aSideColumnName()); - assertEquals(expectedOneToOne, oneToOne.aSideColumnName()); - assertEquals(expectedOneToMany, oneToMany.aSideColumnName()); - } - - @Test - void testGetBSideColumnNameForRelationType() { - //given - String expectedManyToMAny = "bSide_CloudNativeApplication"; - String expectedOneToOne = "REL_FK_deployed-as-cloudNativeSystem"; - String expectedOneToMany = "id"; - //when - RelationType manyToMany = SchemaRegistry.getRelationTypeByName("GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - RelationType oneToOne = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM"); - RelationType oneToMany = SchemaRegistry.getRelationTypeByName("MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); - //then - assertEquals(expectedManyToMAny, manyToMany.bSideColumnName()); - assertEquals(expectedOneToOne, oneToOne.bSideColumnName()); - assertEquals(expectedOneToMany, oneToMany.bSideColumnName()); - } - - @Test - void testGetFieldsForRelationType() { - //given - RelationType gnbduFunctionRealisedByCloudnativeapplication = SchemaRegistry.getRelationTypeByName( - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); - //then - assertEquals(List.of(field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format(QUOTED_STRING, - "aSide_GNBDUFunction")), field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format(QUOTED_STRING, - "bSide_CloudNativeApplication")), field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format( - QUOTED_STRING, "id")), field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String - .format(QUOTED_STRING, "CD_sourceIds"))), - gnbduFunctionRealisedByCloudnativeapplication.getAllFieldsWithId()); - } - - @Test - void testGetRelationTypesByDomain() { - //given - List expectedRelations = List.of("CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", - "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE", "NRCELLDU_USES_NRSECTORCARRIER", - "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "ENODEBFUNCTION_PROVIDES_EUTRANCELL", - "NRSECTORCARRIER_USES_ANTENNACAPABILITY", "GNBDUFUNCTION_PROVIDES_NRCELLDU", - "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "EUTRANCELL_USES_LTESECTORCARRIER", - "NODECLUSTER_LOCATED_AT_CLOUDSITE", "NAMESPACE_DEPLOYED_ON_NODECLUSTER", - "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", - "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", - "LTESECTORCARRIER_USES_ANTENNACAPABILITY", - "GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU", - "GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", - "CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE", "TESTENTITYA_GROUPS_TESTENTITYB", - "TESTENTITYA_USES_TESTENTITYB", "TESTENTITYA_PROVIDES_TESTENTITYB", "SECTOR_GROUPS_NRCELLDU"); - //when - List ranLogicalToCloudRelations = SchemaRegistry.getRelationNamesByDomain("CLOUD_TO_RAN"); - //then - assertEquals(expectedRelations.size(), ranLogicalToCloudRelations.size()); - assertTrue(expectedRelations.containsAll(ranLogicalToCloudRelations)); - } - - @Test - void testGetIncludedModules() { - //when - Module module = SchemaRegistry.getModuleByName("o-ran-smo-teiv-oam-to-ran"); - //then - assertEquals(2, module.getIncludedModuleNames().size()); - assertTrue(List.of("o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran").containsAll(module.getIncludedModuleNames())); - } - - @Test - void testGetIncludedDomains() { - //when - List includedDomains = SchemaRegistry.getIncludedDomains("CLOUD_TO_RAN"); - //then - assertEquals(2, includedDomains.size()); - assertTrue(List.of("RAN", "CLOUD").containsAll(includedDomains)); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryTest.java b/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryTest.java new file mode 100644 index 0000000..22bd34c --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/schema/SchemaRegistryTest.java @@ -0,0 +1,496 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.schema; + +import static org.oran.smo.teiv.exposure.tiespath.refiner.AliasMapper.hashAlias; +import static org.oran.smo.teiv.schema.RelationshipDataLocation.A_SIDE; +import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; +import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.ENTITY_NOT_FOUND_IN_DOMAIN; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.RELATIONSHIP_NOT_FOUND_IN_DOMAIN; +import static org.oran.smo.teiv.schema.SchemaRegistryErrorCode.RELATIONSHIP_NOT_FOUND_IN_MODULE; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; +import static org.oran.smo.teiv.utils.TiesConstants.TEIV_DOMAIN; +import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA; +import static org.jooq.impl.DSL.field; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jooq.JSONB; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.oran.smo.teiv.exception.TiesException; +import org.oran.smo.teiv.exposure.spi.Module; + +class SchemaRegistryTest { + + @BeforeAll + public static void beforeAll() throws UnsupportedOperationException, SchemaLoaderException { + MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); + mockSchemaLoader.loadSchemaRegistry(); + } + + @Test + void testGetModulesName() { + //given + Set expectedModuleNames = Set.of("o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran", "o-ran-smo-teiv-equipment", + "o-ran-smo-teiv-rel-oam-ran", "o-ran-smo-teiv-rel-equipment-ran", TEIV_DOMAIN, + "_3gpp-common-yang-extensions", "_3gpp-common-yang-types", "ietf-geo-location", "ietf-inet-types", + "ietf-yang-types", "o-ran-smo-teiv-common-yang-extensions", "o-ran-smo-teiv-common-yang-types"); + //when + Set moduleNames = SchemaRegistry.getModuleRegistry().keySet(); + //then + assertEquals(expectedModuleNames.size(), moduleNames.size()); + assertEquals(expectedModuleNames, moduleNames); + } + + @Test + void testGetModulesByName() { + //given + String expectedName = "o-ran-smo-teiv-rel-oam-ran"; + String expectedNamespace = "urn:o-ran:smo-teiv-rel-oam-ran"; + String expectedDomain = "REL_OAM_RAN"; + List expectedIncludedModules = List.of("o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran"); + //when + Module oamToRanModule = SchemaRegistry.getModuleByName("o-ran-smo-teiv-rel-oam-ran"); + //then + assertEquals(expectedName, oamToRanModule.getName()); + assertEquals(expectedNamespace, oamToRanModule.getNamespace()); + assertEquals(expectedDomain, oamToRanModule.getDomain()); + assertEquals(expectedIncludedModules, oamToRanModule.getIncludedModuleNames()); + + assertThrows(TiesException.class, () -> SchemaRegistry.getModuleByName("invalid-module")); + } + + @Test + void testGetAllDomainsIncludingRootDomain() { + //given + Set expectedDomains = Set.of(TEIV_DOMAIN, "EQUIPMENT", "REL_EQUIPMENT_RAN", "OAM", "REL_OAM_RAN", "RAN"); + //when + Set actualDomains = SchemaRegistry.getDomains(); + //then + assertEquals(expectedDomains, actualDomains); + } + + @Test + void testRootDomainIncludesAllAvailableDomains() { + //given + Set availableDomains = SchemaRegistry.getDomains(); + availableDomains.remove(TEIV_DOMAIN); + //when + List rootIncludedDomains = SchemaRegistry.getIncludedDomains(TEIV_DOMAIN); + //then + assertEquals(availableDomains.size(), rootIncludedDomains.size()); + assertTrue(availableDomains.containsAll(rootIncludedDomains)); + } + + @Test + void testGetModuleByDomainThrowsUnknownDomainException() { + assertThrows(TiesException.class, () -> SchemaRegistry.getModuleByDomain("throwError")); + } + + //Entities + + @Test + void testGetEntityTypeByDomainAndName() throws SchemaRegistryException { + //when + List entityTypes = SchemaRegistry.getEntityTypeByDomainAndName("RAN", "GNBDUFunction"); + //then + assertEquals(1, entityTypes.size()); + EntityType entityType = entityTypes.get(0); + assertEquals("GNBDUFunction", entityType.getName()); + assertEquals("RAN", entityType.getModule().getDomain()); + + final SchemaRegistryException exception = assertThrows(SchemaRegistryException.class, () -> SchemaRegistry + .getEntityTypeByDomainAndName("OAM", "GNBDUFunction")); + assertEquals(ENTITY_NOT_FOUND_IN_DOMAIN, exception.getErrorCode()); + } + + @Test + void testGetEntityTypeByModuleAndName() throws SchemaRegistryException { + //when + EntityType entityType = SchemaRegistry.getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction"); + //then + assertEquals("GNBDUFunction", entityType.getName()); + assertEquals("RAN", entityType.getModule().getDomain()); + + final SchemaRegistryException exception = assertThrows(SchemaRegistryException.class, () -> SchemaRegistry + .getEntityTypeByDomainAndName("o-ran-smo-teiv-oam", "GNBDUFunction")); + assertEquals(ENTITY_NOT_FOUND_IN_DOMAIN, exception.getErrorCode()); + } + + @Test + void testGetEntityNames() { + //given + List expectedEntityName = List.of("AntennaCapability", "AntennaModule", "ENodeBFunction", "EUtranCell", + "GNBCUCPFunction", "GNBCUUPFunction", "GNBDUFunction", "LTESectorCarrier", "ManagedElement", "NRCellCU", + "NRCellDU", "NRSectorCarrier", "Sector", "Site"); + //when + List actualEntityNames = SchemaRegistry.getEntityNames(); + //then + assertEquals(expectedEntityName.size(), actualEntityNames.size()); + assertTrue(actualEntityNames.containsAll(expectedEntityName)); + } + + @Test + void testGetTableNameForEntity() throws SchemaRegistryException { + //given + EntityType gnbduFunction = SchemaRegistry.getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction"); + //then + assertEquals("ties_data.\"o-ran-smo-teiv-ran_GNBDUFunction\"", gnbduFunction.getTableName()); + } + + @Test + void testGetClassifiersColumnNameForEntity() throws SchemaRegistryException { + //given + EntityType gnbduFunction = SchemaRegistry.getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction"); + //then + assertEquals("CD_classifiers", gnbduFunction.getClassifiersColumnName()); + } + + @Test + void testGetDecoratorsColumnNameForEntity() throws SchemaRegistryException { + //given + EntityType gnbduFunction = SchemaRegistry.getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction"); + //then + assertEquals("CD_decorators", gnbduFunction.getDecoratorsColumnName()); + } + + @Test + void testGetFieldsForEntity() throws SchemaRegistryException { + //given + EntityType gnbduFunction = SchemaRegistry.getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction"); + //then + assertEquals(Set.of(field("dUpLMNId", JSONB.class).as("o-ran-smo-teiv-ran:GNBDUFunction.attr.dUpLMNId"), field( + "gNBDUId").as("o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBDUId"), field("gNBId").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBId"), field("gNBIdLength").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.gNBIdLength"), field("id").as( + "o-ran-smo-teiv-ran:GNBDUFunction.id"), field("CD_sourceIds").as( + "o-ran-smo-teiv-ran:GNBDUFunction.sourceIds"), field("CD_classifiers").as( + "o-ran-smo-teiv-ran:GNBDUFunction.classifiers"), field( + "CD_decorators").as( + "o-ran-smo-teiv-ran:GNBDUFunction.decorators")), + new HashSet<>(gnbduFunction.getAllFieldsWithId())); + } + + @Test + void testGetEntityTypesByDomain() { + //given + List expectedEntities = List.of("AntennaCapability", "AntennaModule", "ENodeBFunction", "EUtranCell", + "GNBCUCPFunction", "GNBCUUPFunction", "GNBDUFunction", "LTESectorCarrier", "NRCellCU", "NRCellDU", + "NRSectorCarrier", "Sector", "Site"); + //when + List equipmentToRanEntityTypes = SchemaRegistry.getEntityNamesByDomain("REL_EQUIPMENT_RAN"); + //then + assertEquals(expectedEntities.size(), equipmentToRanEntityTypes.size()); + assertTrue(expectedEntities.containsAll(equipmentToRanEntityTypes)); + } + + //Relations + @Test + void getRelationNames() { + List expectedRelationNames = List.of("ANTENNAMODULE_SERVES_ANTENNACAPABILITY", + "NRSECTORCARRIER_USES_ANTENNACAPABILITY", "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "EUTRANCELL_USES_LTESECTORCARRIER", "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", "SECTOR_GROUPS_EUTRANCELL", + "NRCELLDU_USES_NRSECTORCARRIER", "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", + "SECTOR_GROUPS_ANTENNAMODULE", "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "SECTOR_GROUPS_NRCELLDU", + "ENODEBFUNCTION_PROVIDES_EUTRANCELL", "ANTENNAMODULE_INSTALLED_AT_SITE", + "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", + "LTESECTORCARRIER_USES_ANTENNACAPABILITY"); + //when + List relationNames = SchemaRegistry.getRelationNames(); + //then + assertEquals(expectedRelationNames.size(), relationNames.size()); + assertTrue(relationNames.containsAll(expectedRelationNames)); + } + + @Test + void testGetRelationTypeByName() { + //given + Association expectedASideAssociation = new Association("managed-gnbcucpFunction", 1, 1); + Association expectedBSideAssociation = new Association("managed-by-managedElement", 0, 9223372036854775807L); + //when + RelationType managedElementManagesGnbcucpfunction = SchemaRegistry.getRelationTypeByName( + "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); + //then + assertEquals(expectedASideAssociation.toString(), managedElementManagesGnbcucpfunction.getASideAssociation() + .toString()); + assertEquals(expectedBSideAssociation.toString(), managedElementManagesGnbcucpfunction.getBSideAssociation() + .toString()); + } + + @Test + void testGetRelationTypeByModuleAndName() throws SchemaRegistryException { + //given + Association expectedASideAssociation = new Association("managed-gnbcucpFunction", 1, 1); + Association expectedBSideAssociation = new Association("managed-by-managedElement", 0, 9223372036854775807L); + //when + RelationType managedElementManagesGnbcucpfunction = SchemaRegistry.getRelationTypeByModuleAndName( + "o-ran-smo-teiv-rel-oam-ran", "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); + //then + assertEquals(expectedASideAssociation.toString(), managedElementManagesGnbcucpfunction.getASideAssociation() + .toString()); + assertEquals(expectedBSideAssociation.toString(), managedElementManagesGnbcucpfunction.getBSideAssociation() + .toString()); + + final SchemaRegistryException exception = assertThrows(SchemaRegistryException.class, () -> SchemaRegistry + .getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION")); + assertEquals(RELATIONSHIP_NOT_FOUND_IN_MODULE, exception.getErrorCode()); + } + + @Test + void testGetRelationTypeByDomainAndName() throws SchemaRegistryException { + //given + Association expectedASideAssociation = new Association("managed-gnbcucpFunction", 1, 1); + Association expectedBSideAssociation = new Association("managed-by-managedElement", 0, 9223372036854775807L); + //when + List relationTypes = SchemaRegistry.getRelationTypeByDomainAndName("REL_OAM_RAN", + "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); + //then + assertEquals(1, relationTypes.size()); + RelationType managedElementManagesGnbcucpfunction = relationTypes.get(0); + assertEquals(expectedASideAssociation.toString(), managedElementManagesGnbcucpfunction.getASideAssociation() + .toString()); + assertEquals(expectedBSideAssociation.toString(), managedElementManagesGnbcucpfunction.getBSideAssociation() + .toString()); + + final SchemaRegistryException exception = assertThrows(SchemaRegistryException.class, () -> SchemaRegistry + .getRelationTypeByDomainAndName("OAM", "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION")); + assertEquals(RELATIONSHIP_NOT_FOUND_IN_DOMAIN, exception.getErrorCode()); + } + + @Test + void testGetRelationTypesByEntityType() throws SchemaRegistryException { + //given + List expectedRelationsList = new ArrayList<>(); + expectedRelationsList.add(SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY")); + expectedRelationsList.add(SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "SECTOR_GROUPS_ANTENNAMODULE")); + expectedRelationsList.add(SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-equipment", + "ANTENNAMODULE_INSTALLED_AT_SITE")); + //when + List relationTypes = SchemaRegistry.getRelationTypesByEntityName("AntennaModule"); + //then + assertEquals(3, relationTypes.size()); + assertTrue(relationTypes.containsAll(expectedRelationsList)); + } + + @Test + void testGetFullyQualifiedNameForRelation() throws SchemaRegistryException { + //given + RelationType gnbduFunctionRealisedByCloudnativeapplication = SchemaRegistry.getRelationTypeByModuleAndName( + "o-ran-smo-teiv-equipment", "ANTENNAMODULE_INSTALLED_AT_SITE"); + //then + assertEquals("o-ran-smo-teiv-equipment:ANTENNAMODULE_INSTALLED_AT_SITE", + gnbduFunctionRealisedByCloudnativeapplication.getFullyQualifiedName()); + } + + @Test + void testGetTableNameForRelation() throws SchemaRegistryException { + //given + String expectedManyToMany = "ties_data.\"CFC235E0404703D1E4454647DF8AAE2C193DB402\""; + String expectedOneToMany = "ties_data.\"o-ran-smo-teiv-ran_NRCellDU\""; + String expectedManyToOne = "ties_data.\"o-ran-smo-teiv-equipment_AntennaModule\""; + //when + RelationType manyToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + RelationType oneToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + RelationType manyToOne = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-equipment", + "ANTENNAMODULE_INSTALLED_AT_SITE"); + //then + assertEquals(expectedManyToMany, manyToMany.getTableName()); + assertEquals(expectedOneToMany, oneToMany.getTableName()); + assertEquals(expectedManyToOne, manyToOne.getTableName()); + } + + @Test + void testGetRelationshipDataLocationForRelation() throws SchemaRegistryException { + //when + RelationType manyToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + RelationType oneToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + RelationType manyToOne = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-equipment", + "ANTENNAMODULE_INSTALLED_AT_SITE"); + //then + assertEquals(RELATION, manyToMany.getRelationshipStorageLocation()); + assertEquals(B_SIDE, oneToMany.getRelationshipStorageLocation()); + assertEquals(A_SIDE, manyToOne.getRelationshipStorageLocation()); + } + + @Test + void testGetClassifiersColumnNameForRelationType() throws SchemaRegistryException { + //when + RelationType relationType = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + //then + assertEquals("REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU", relationType.getClassifiersColumnName()); + } + + @Test + void testGetDecoratorsColumnNameForRelationType() throws SchemaRegistryException { + //when + RelationType relationType = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + //then + assertEquals("REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU", relationType.getDecoratorsColumnName()); + } + + @Test + void testGetIdColumnNameRelationTest() throws SchemaRegistryException { + //given + String expectedManyToManyId = "id"; + String expectedOneToManyId = "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU"; + //when + RelationType manyToManyRelation = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + RelationType oneToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + //then + assertEquals(expectedManyToManyId, manyToManyRelation.getIdColumnName()); + assertEquals(expectedOneToManyId, oneToMany.getIdColumnName()); + } + + @Test + void testGetASideColumnNameForRelationType() throws SchemaRegistryException { + //given + String expectedManyToMany = "aSide_AntennaModule"; + String expectedOneToMany = "REL_FK_provided-by-gnbduFunction"; + //when + RelationType manyToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + RelationType oneToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + //then + assertEquals(expectedManyToMany, manyToMany.aSideColumnName()); + assertEquals(expectedOneToMany, oneToMany.aSideColumnName()); + } + + @Test + void testGetBSideColumnNameForRelationType() throws SchemaRegistryException { + //given + String expectedManyToMAny = "bSide_AntennaCapability"; + String expectedOneToMany = "id"; + //when + RelationType manyToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-rel-equipment-ran", + "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + RelationType oneToMany = SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRCELLDU"); + //then + assertEquals(expectedManyToMAny, manyToMany.bSideColumnName()); + assertEquals(expectedOneToMany, oneToMany.bSideColumnName()); + } + + @Test + void testGetFieldsForRelationType() throws SchemaRegistryException { + //given + RelationType antennamoduleServesAntennacapability = SchemaRegistry.getRelationTypeByModuleAndName( + "o-ran-smo-teiv-rel-equipment-ran", "ANTENNAMODULE_SERVES_ANTENNACAPABILITY"); + //then + assertEquals(Set.of(field(String.format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String + .format(QUOTED_STRING, "aSide_AntennaModule")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.aSide")), field(String + .format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String.format( + QUOTED_STRING, "bSide_AntennaCapability")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.bSide")), + field(String.format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String.format( + QUOTED_STRING, "id")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.id")), field(String + .format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String + .format(QUOTED_STRING, "CD_sourceIds")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.sourceIds")), + field(String.format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String.format( + QUOTED_STRING, "CD_decorators")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.decorators")), + field(String.format(TIES_DATA, "CFC235E0404703D1E4454647DF8AAE2C193DB402") + "." + String.format( + QUOTED_STRING, "CD_classifiers")).as(hashAlias( + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY.classifiers"))), + new HashSet<>(antennamoduleServesAntennacapability.getAllFieldsWithId())); + } + + @Test + void testGetRelationTypesByDomain() { + //given + List expectedRelations = List.of("ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", + "ENODEBFUNCTION_PROVIDES_EUTRANCELL", "LTESECTORCARRIER_USES_ANTENNACAPABILITY", "SECTOR_GROUPS_EUTRANCELL", + "SECTOR_GROUPS_NRCELLDU", "NRCELLDU_USES_NRSECTORCARRIER", "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", + "GNBDUFUNCTION_PROVIDES_NRCELLDU", "NRSECTORCARRIER_USES_ANTENNACAPABILITY", + "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", "EUTRANCELL_USES_LTESECTORCARRIER", + "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); + //when + List oamToRanRelations = SchemaRegistry.getRelationNamesByDomain("REL_OAM_RAN"); + //then + assertEquals(expectedRelations.size(), oamToRanRelations.size()); + assertTrue(expectedRelations.containsAll(oamToRanRelations)); + } + + @Test + void getAttributeColumnsWithFilterTest() throws SchemaRegistryException { + Assertions.assertEquals(Map.of(field("ties_data.\"GNBDUFunction\".\"dUpLMNId\"").as( + "o-ran-smo-teiv-ran:GNBDUFunction.attr.dUpLMNId"), DataType.CONTAINER), SchemaRegistry + .getEntityTypeByModuleAndName("o-ran-smo-teiv-ran", "GNBDUFunction").getSpecificAttributeColumns( + List.of("dUpLMNId"))); + Assertions.assertEquals(Map.of(field("ties_data.\"AntennaModule\".\"geo-location\"").as( + "o-ran-smo-teiv-equipment:AntennaModule.attr.geo-location"), DataType.GEOGRAPHIC), SchemaRegistry + .getEntityTypeByModuleAndName("o-ran-smo-teiv-equipment", "AntennaModule") + .getSpecificAttributeColumns(List.of("geo-location"))); + Assertions.assertEquals(Map.of(), SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").getSpecificAttributeColumns(List.of())); + } + + @Test + void testGetAttributeNamesForRelation() throws SchemaRegistryException { + Assertions.assertEquals(Collections.emptyList(), SchemaRegistry.getRelationTypeByModuleAndName("o-ran-smo-teiv-ran", + "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER").getAttributeNames()); + } + + @Test + void testGetIncludedModules() { + //when + Module module = SchemaRegistry.getModuleByName("o-ran-smo-teiv-rel-oam-ran"); + //then + assertEquals(2, module.getIncludedModuleNames().size()); + assertTrue(List.of("o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran").containsAll(module.getIncludedModuleNames())); + } + + @Test + void testGetIncludedDomains() { + //when + List includedDomains = SchemaRegistry.getIncludedDomains("REL_OAM_RAN"); + //then + assertEquals(2, includedDomains.size()); + assertTrue(List.of("OAM", "RAN").containsAll(includedDomains)); + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndApiTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndApiTest.java deleted file mode 100644 index 2b10333..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndApiTest.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.service; - -import static org.oran.smo.teiv.utils.TiesConstants.REQUEST_MAPPING; -import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.io.IOException; -import java.time.Duration; -import java.util.List; - -import org.awaitility.Awaitility; -import org.jooq.DSLContext; -import org.jooq.JSONB; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.http.HttpStatusCode; -import org.springframework.kafka.test.EmbeddedKafkaBroker; -import org.springframework.kafka.test.context.EmbeddedKafka; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.springframework.web.client.HttpClientErrorException; - -import org.oran.smo.teiv.CustomMetrics; -import org.oran.smo.teiv.db.TestPostgresqlContainer; -import org.oran.smo.teiv.service.kafka.KafkaTopicService; -import org.oran.smo.teiv.startup.AppInit; -import org.oran.smo.teiv.availability.DependentServiceAvailabilityKafka; -import org.oran.smo.teiv.config.KafkaConfig; -import org.oran.smo.teiv.listener.ListenerStarter; -import org.oran.smo.teiv.utils.CloudEventTestUtil; -import org.oran.smo.teiv.utils.EndToEndExpectedResults; -import org.oran.smo.teiv.utils.EndToEndTestUtil; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; - -@EmbeddedKafka -@SpringBootTest(properties = { - "kafka.server.bootstrap-server-host:#{environment.getProperty(\"spring.embedded.kafka.brokers\").split(\":\")[0]}", - "kafka.server.bootstrap-server-port:#{environment.getProperty(\"spring.embedded.kafka.brokers\").split(\":\")[1]}", - "kafka.availability.retryIntervalMs:10", - "kafka.topic.replicas:1" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "test", "ingestion" }) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) -class EndToEndApiTest { - private static final TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); - - @Autowired - private DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka; - - @Autowired - private KafkaTopicService kafkaTopicService; - - @Autowired - private ListenerStarter listenerStarter; - - @Autowired - private EmbeddedKafkaBroker embeddedKafkaBroker; - - @Autowired - private CustomMetrics customMetrics; - - @LocalServerPort - private int port; - - private AppInit appInit; - - private static String URI; - - @Autowired - private KafkaConfig kafkaConfig; - - @Autowired - private DSLContext writeDataDslContext; - - @DynamicPropertySource - static void setProperties(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.read.jdbc-url", () -> postgreSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.read.username", () -> postgreSQLContainer.getUsername()); - registry.add("spring.datasource.read.password", () -> postgreSQLContainer.getPassword()); - - registry.add("spring.datasource.write.jdbc-url", () -> postgreSQLContainer.getJdbcUrl()); - registry.add("spring.datasource.write.username", () -> postgreSQLContainer.getUsername()); - registry.add("spring.datasource.write.password", () -> postgreSQLContainer.getPassword()); - } - - @BeforeEach - void setUp() { - writeDataDslContext.meta().filterSchemas(s -> s.getName().equals(TIES_DATA_SCHEMA)).getTables().forEach( - t -> writeDataDslContext.truncate(t).cascade().execute()); - appInit = new AppInit(dependentServiceAvailabilityKafka, kafkaTopicService, listenerStarter); - appInit.startUpHandler(); - URI = String.format("http://localhost:%s%s/domains/", port, REQUEST_MAPPING); - } - - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) - @Test - void testEndToEndApi() { - final String TEST_EVENT_FOLDER = "src/test/resources/cloudeventdata/end-to-end/"; - final String EXPECTED_RESULTS_FOLDER = "src/test/resources/cloudeventdata/end-to-end/expected-results/api/"; - - final String CREATE_MANY_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-create-many-to-many.json"; - final String CREATE_MANY_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-create-many-to-one.json"; - final String CREATE_ONE_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-create-one-to-many.json"; - final String CREATE_SECOND_CASE_PATH = TEST_EVENT_FOLDER + "ce-create-second-case.json"; - final String CREATE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH = TEST_EVENT_FOLDER + "ce-create-relationship-connecting-same-entity.json"; - - final String MERGE_ONE_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-merge-one-to-many-deprecated-structure.json"; - - final String DELETE_MANY_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-delete-many-to-many.json"; - final String DELETE_MANY_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-delete-many-to-one.json"; - final String DELETE_ONE_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-delete-one-to-many.json"; - final String DELETE_EVENT_CMHANDLE_PATH = TEST_EVENT_FOLDER + "ce-source-entity-delete-cm-handle.json"; - final String DELETE_EVENT_CMHANDLE_PATH_2 = TEST_EVENT_FOLDER + "ce-source-entity-delete-cm-handle2.json"; - final String DELETE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH = TEST_EVENT_FOLDER + "ce-delete-relationship-connecting-same-entity.json"; - - final String EXP_CREATE_MANY_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-many-to-many.json"; - final String EXP_CREATE_MANY_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-many-to-one.json"; - final String EXP_CREATE_ONE_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-one-to-many.json"; - final String EXP_CREATE_SECOND_CASE_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-second-case.json"; - final String EXP_CREATE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-relationship-connecting-same-entity.json"; - - final String EXP_MERGE_ONE_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-merge-one-to-many.json"; - - final String EXP_DELETE_MANY_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-delete-many-to-many.json"; - final String EXP_DELETE_ONE_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-delete-one-to-many.json"; - final String EXP_DELETE_MANY_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "exp-delete-many-to-one.json"; - final String EXP_SOURCE_ENTITY_DELETE_CM_HANDLE = EXPECTED_RESULTS_FOLDER + "exp-source-entity-delete-cm-handle.json"; - final String EXP_DELETE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH = EXPECTED_RESULTS_FOLDER + "exp-delete-relationship-connecting-same-entity.json"; - - validateReceivedCloudEventMetrics(0, 0, 0, 0); - - sendEventFromFile(CREATE_MANY_TO_MANY_PATH); - sendEventFromFile(CREATE_ONE_TO_MANY_PATH); - sendEventFromFile(CREATE_MANY_TO_ONE_PATH); - sendEventFromFile(CREATE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - validateApiResultsWithValues(EXP_CREATE_MANY_TO_MANY_PATH); - validateApiResultsWithValues(EXP_CREATE_ONE_TO_MANY_PATH); - validateApiResultsWithValues(EXP_CREATE_MANY_TO_ONE_PATH); - validateApiResultsWithValues(EXP_CREATE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH); - validateReceivedCloudEventMetrics(4, 0, 0, 0); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Create many to many event: " + e - .getMessage(), e); - } - }); - - sendEventFromFile(MERGE_ONE_TO_MANY_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - validateApiResultsWithValues(EXP_MERGE_ONE_TO_MANY_PATH); - validateReceivedCloudEventMetrics(4, 1, 0, 0); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Merge one to many event: " + e.getMessage(), - e); - } - - }); - - sendEventFromFile(CREATE_SECOND_CASE_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - validateApiResultsWithValues(EXP_CREATE_SECOND_CASE_PATH); - validateReceivedCloudEventMetrics(5, 1, 0, 0); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Create with CmHandle event: " + e - .getMessage(), e); - } - }); - - sendEventFromFile(DELETE_MANY_TO_MANY_PATH); - sendEventFromFile(DELETE_ONE_TO_MANY_PATH); - sendEventFromFile(DELETE_MANY_TO_ONE_PATH); - sendEventFromFile(DELETE_EVENT_CMHANDLE_PATH); - sendEventFromFile(DELETE_EVENT_CMHANDLE_PATH_2); - sendEventFromFile(DELETE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - validateApiResultsAfterDelete(EXP_DELETE_MANY_TO_MANY_PATH); - validateApiResultsAfterDelete(EXP_DELETE_ONE_TO_MANY_PATH); - validateApiResultsAfterDelete(EXP_DELETE_MANY_TO_ONE_PATH); - validateApiResultsAfterDelete(EXP_SOURCE_ENTITY_DELETE_CM_HANDLE); - validateApiResultsAfterDelete(EXP_DELETE_RELATIONSHIP_CONNECTING_SAME_ENTITY_PATH); - validateReceivedCloudEventMetrics(5, 1, 4, 2); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Delete event: " + e.getMessage(), e); - } - }); - } - - private void validateReceivedCloudEventMetrics(final int create, final int merge, final int delete, - final int sourceDelete) { - assertEquals(create, customMetrics.getNumReceivedCloudEventCreate().count()); - assertEquals(merge, customMetrics.getNumReceivedCloudEventMerge().count()); - assertEquals(delete, customMetrics.getNumReceivedCloudEventDelete().count()); - assertEquals(sourceDelete, customMetrics.getNumReceivedCloudEventSourceEntityDelete().count()); - } - - private void validateApiResultsWithValues(final String expectedValuesCollectionPath) throws JsonMappingException, - JsonProcessingException, IOException { - EndToEndExpectedResults values = getExpectedResults(expectedValuesCollectionPath); - values.getAll().forEach((requestSubUri, responseResult) -> { - String apiRes = processApiCall(URI + requestSubUri); - String expectedRes = responseResult.toString(); - assertEquals(JSONB.jsonb(expectedRes), JSONB.jsonb(apiRes)); - }); - } - - private void validateApiResultsAfterDelete(String requestUrlCollectionPath) { - EndToEndExpectedResults values = getExpectedResults(requestUrlCollectionPath); - assertDoesNotThrow(() -> values.getAll(), "Reading expected results resulted in error.").keySet().forEach((key) -> { - assertResponseNotContainId(URI + key); - }); - }; - - private void assertResponseNotContainId(final String requestUri) { - HttpClientErrorException e = assertThrows(HttpClientErrorException.class, () -> EndToEndTestUtil.processApiCall( - requestUri)); - assertEquals(HttpStatusCode.valueOf(404), e.getStatusCode(), "API Response status is not 404, but it should"); - } - - private void sendEventFromFile(final String path) { - assertDoesNotThrow(() -> EndToEndTestUtil.sendEventList(List.of(CloudEventTestUtil.getCloudEventFromJsonFile(path)), - embeddedKafkaBroker, kafkaConfig), "Sending cloud event from file resulted in error."); - } - - private EndToEndExpectedResults getExpectedResults(final String path) { - return assertDoesNotThrow(() -> new EndToEndExpectedResults(path), "Reading expected values resulted in error."); - - } - - private String processApiCall(final String uri) { - return assertDoesNotThrow(() -> EndToEndTestUtil.processApiCall(uri), "Processing api call resulted in error."); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndDbTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndDbTest.java index 720447a..7537ed5 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndDbTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/service/EndToEndDbTest.java @@ -26,16 +26,31 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; -import java.io.IOException; +import java.io.File; import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import io.cloudevents.CloudEvent; +import io.cloudevents.kafka.CloudEventSerializer; +import org.apache.kafka.clients.admin.Admin; +import org.apache.kafka.clients.admin.ConsumerGroupDescription; +import org.apache.kafka.clients.admin.DescribeConsumerGroupsOptions; +import org.apache.kafka.clients.admin.DescribeConsumerGroupsResult; +import org.apache.kafka.clients.producer.Producer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.serialization.StringSerializer; import org.awaitility.Awaitility; import org.jooq.DSLContext; import org.jooq.Record; import org.jooq.Result; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.oran.smo.teiv.CustomMetrics; @@ -47,11 +62,13 @@ import org.oran.smo.teiv.service.kafka.KafkaTopicService; import org.oran.smo.teiv.startup.AppInit; import org.oran.smo.teiv.utils.CloudEventTestUtil; import org.oran.smo.teiv.utils.EndToEndExpectedResults; -import org.oran.smo.teiv.utils.EndToEndTestUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaAdmin; import org.springframework.kafka.test.EmbeddedKafkaBroker; import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.kafka.test.utils.KafkaTestUtils; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; @@ -61,10 +78,11 @@ import org.springframework.test.context.DynamicPropertySource; @SpringBootTest(properties = { "kafka.server.bootstrap-server-host:#{environment.getProperty(\"spring.embedded.kafka.brokers\").split(\":\")[0]}", "kafka.server.bootstrap-server-port:#{environment.getProperty(\"spring.embedded.kafka.brokers\").split(\":\")[1]}", - "kafka.availability.retryIntervalMs:10", "kafka.topic.replicas:1" }) + "kafka.availability.retryIntervalMs:10", "kafka.topic.replicas:1", + "kafka.topology-ingestion.consumer.concurrency:2" }) @ActiveProfiles({ "test", "ingestion" }) public class EndToEndDbTest { - public static TestPostgresqlContainer postgresqlContainer = TestPostgresqlContainer.getInstance(); + private static TestPostgresqlContainer postgresqlContainer = TestPostgresqlContainer.getInstance(); @Autowired private DependentServiceAvailabilityKafka dependentServiceAvailabilityKafka; @@ -81,37 +99,27 @@ public class EndToEndDbTest { @Autowired private CustomMetrics customMetrics; - @Autowired - private TiesDbService tiesDbService; - private AppInit appInit; @Autowired private KafkaConfig kafkaConfig; + @Autowired + private KafkaAdmin kafkaAdmin; + @Autowired private DSLContext writeDataDslContext; - private final static String CNA_TABLE = "CloudNativeApplication"; - private final static String CNS_TABLE = "CloudNativeSystem"; - private final static String ME_TABLE = "ManagedElement"; - private final static String GNBDU_TABLE = "GNBDUFunction"; - private final static String GNBCUUP_TABLE = "GNBCUUPFunction"; - private final static String GNBCUCP_TABLE = "GNBCUCPFunction"; - private final static String NRCELLDU_TABLE = "NRCellDU"; - private final static String GNBDU_CNA_TABLE = "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; - private final static String GNBCUUP_CNA_TABLE = "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; - private final static String GNBCUCP_CNA_TABLE = "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; + static Producer producer; private static final String TEST_EVENT_FOLDER = "src/test/resources/cloudeventdata/end-to-end/"; - private static final String EXPECTED_RESULTS_FOLDER = "src/test/resources/cloudeventdata/end-to-end/expected-results/db/"; + private static final String EXPECTED_RESULTS_FOLDER = "src/test/resources/cloudeventdata/end-to-end/expected-results/"; @DynamicPropertySource static void setProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.read.jdbc-url", () -> postgresqlContainer.getJdbcUrl()); registry.add("spring.datasource.read.username", () -> postgresqlContainer.getUsername()); registry.add("spring.datasource.read.password", () -> postgresqlContainer.getPassword()); - registry.add("spring.datasource.write.jdbc-url", () -> postgresqlContainer.getJdbcUrl()); registry.add("spring.datasource.write.username", () -> postgresqlContainer.getUsername()); registry.add("spring.datasource.write.password", () -> postgresqlContainer.getPassword()); @@ -123,89 +131,135 @@ public class EndToEndDbTest { t -> writeDataDslContext.truncate(t).cascade().execute()); appInit = new AppInit(dependentServiceAvailabilityKafka, kafkaTopicService, listenerStarter); appInit.startUpHandler(); + producer = new DefaultKafkaProducerFactory<>(new HashMap<>(KafkaTestUtils.producerProps(embeddedKafkaBroker)), + new StringSerializer(), new CloudEventSerializer()).createProducer(); + } + + @AfterEach + void tearDown() { + embeddedKafkaBroker.destroy(); } @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) @Test - void testEndToEndDb() throws InterruptedException, IOException { + void testEndToEndDb() { + final String CREATE_ONE_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-create-one-to-one.json"; final String CREATE_MANY_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-create-many-to-many.json"; final String CREATE_SECOND_CASE_PATH = TEST_EVENT_FOLDER + "ce-create-second-case.json"; - final String MERGE_ONE_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-merge-one-to-many-deprecated-structure.json"; - final String DELETE_EVENT_PATH = TEST_EVENT_FOLDER + "ce-delete-many-to-many.json"; - final String DELETE_EVENT_ONE_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-delete-one-to-one.json"; - final String DELETE_EVENT_CMHANDLE_PATH = TEST_EVENT_FOLDER + "ce-source-entity-delete-cm-handle.json"; - final String CREATE_ONE_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-create-one-to-one.json"; + final String MERGE_ONE_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-merge-one-to-many.json"; + final String DELETE_MANY_TO_MANY_PATH = TEST_EVENT_FOLDER + "ce-delete-many-to-many.json"; + final String DELETE_ONE_TO_ONE_PATH = TEST_EVENT_FOLDER + "ce-delete-one-to-one.json"; + final String DELETE_CMHANDLE_PATH = TEST_EVENT_FOLDER + "ce-source-entity-delete-cm-handle.json"; + final String EXP_CREATE_ONE_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-one-to-one.json"; final String EXP_CREATE_MANY_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-many-to-many.json"; - final String EXP_MERGE_ONE_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-merge-one-to-many.json"; final String EXP_CREATE_SECOND_CASE_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-second-case.json"; - final String EXP_CREATE_ONE_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "exp-create-one-to-one.json"; - final String EXP_ONE_TO_ONE_PATH_AFTER_DELETE = EXPECTED_RESULTS_FOLDER + "exp-delete-one-to-one.json"; + final String EXP_MERGE_ONE_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "exp-merge-one-to-many.json"; + final String EXP_DELETE_ONE_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "exp-delete-one-to-one.json"; + final String NOT_EXP_DELETE_ONE_TO_ONE_PATH = EXPECTED_RESULTS_FOLDER + "not-exp-delete-one-to-one.json"; + final String NOT_EXP_DELETE_MANY_TO_MANY_PATH = EXPECTED_RESULTS_FOLDER + "not-exp-delete-many-to-many.json"; + final String NOT_EXP_DELETE_CMHANDLE_PATH = EXPECTED_RESULTS_FOLDER + "not-exp-source-entity-delete-cm-handle.json"; validateReceivedCloudEventMetrics(0, 0, 0, 0); sendEventFromFile(CREATE_ONE_TO_ONE_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - EndToEndExpectedResults values = getExpectedResults(EXP_CREATE_ONE_TO_ONE_PATH); - validateDbResultsAfterOneToOneCE(values); - validateReceivedCloudEventMetrics(1, 0, 0, 0); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Create one to one event: " + e.getMessage(), - e); - } + validateWithTimeout(999999, () -> { + EndToEndExpectedResults expected = getExpectedResults(EXP_CREATE_ONE_TO_ONE_PATH); + assertDbContainsExpectedValues(expected); + validateReceivedCloudEventMetrics(1, 0, 0, 0); }); sendEventFromFile(CREATE_MANY_TO_MANY_PATH); - Awaitility.await().atMost(10, TimeUnit.SECONDS).pollDelay(Duration.ofSeconds(5)).untilAsserted( - () -> assertWithErrorMessage(() -> { - EndToEndExpectedResults values = getExpectedResults(EXP_CREATE_MANY_TO_MANY_PATH); - validateDbResultsAfterCreate(values); - validateReceivedCloudEventMetrics(2, 0, 0, 0); - }, "Assertion failed during validation of Create many to many event")); + validateWithTimeout(20, () -> { + EndToEndExpectedResults expected = getExpectedResults(EXP_CREATE_MANY_TO_MANY_PATH); + assertDbContainsExpectedValues(expected); + validateReceivedCloudEventMetrics(2, 0, 0, 0); + }); sendEventFromFile(MERGE_ONE_TO_MANY_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> assertWithErrorMessage(() -> { - EndToEndExpectedResults values = getExpectedResults(EXP_MERGE_ONE_TO_MANY_PATH); - validateDbResultsAfterMerge(values); + + validateWithTimeout(20, () -> { + EndToEndExpectedResults expected = getExpectedResults(EXP_MERGE_ONE_TO_MANY_PATH); + assertDbContainsExpectedValues(expected); validateReceivedCloudEventMetrics(2, 1, 0, 0); - }, "Assertion failed during validation of Merge one to many event")); + }); sendEventFromFile(CREATE_SECOND_CASE_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> assertWithErrorMessage(() -> { - EndToEndExpectedResults values = getExpectedResults(EXP_CREATE_SECOND_CASE_PATH); - validateDbResultsAfterCmHandle(values); + validateWithTimeout(20, () -> { + EndToEndExpectedResults expected = getExpectedResults(EXP_CREATE_SECOND_CASE_PATH); + assertDbContainsExpectedValues(expected); validateReceivedCloudEventMetrics(3, 1, 0, 0); - }, "Assertion failed during validation of Create with CmHandle event")); + }); - sendEventFromFile(DELETE_EVENT_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> assertWithErrorMessage(() -> { - validateDbResultsAfterDelete(); + sendEventFromFile(DELETE_MANY_TO_MANY_PATH); + validateWithTimeout(20, () -> { + EndToEndExpectedResults notExpected = getExpectedResults(NOT_EXP_DELETE_MANY_TO_MANY_PATH); + assertDbNotContainsExpectedValues(notExpected); validateReceivedCloudEventMetrics(3, 1, 1, 0); - }, "Assertion failed during validation of Delete event")); + }); - sendEventFromFile(DELETE_EVENT_ONE_TO_ONE_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - EndToEndExpectedResults values = getExpectedResults(EXP_ONE_TO_ONE_PATH_AFTER_DELETE); - validateDbResultsAfterDeleteOneToOne(values); - validateReceivedCloudEventMetrics(3, 1, 2, 0); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Delete one to one relationship event: " + e - .getMessage(), e); - } + sendEventFromFile(DELETE_ONE_TO_ONE_PATH); + validateWithTimeout(20, () -> { + EndToEndExpectedResults expected = getExpectedResults(EXP_DELETE_ONE_TO_ONE_PATH); + assertDbContainsExpectedValues(expected); + EndToEndExpectedResults notExpected = getExpectedResults(NOT_EXP_DELETE_ONE_TO_ONE_PATH); + assertDbNotContainsExpectedValues(notExpected); + validateReceivedCloudEventMetrics(3, 1, 2, 0); }); - sendEventFromFile(DELETE_EVENT_CMHANDLE_PATH); - Awaitility.await().pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { - try { - validateDbResultsAfterDeleteCmHandle(); - validateReceivedCloudEventMetrics(3, 1, 2, 1); - } catch (AssertionError e) { - throw new AssertionError("Assertion failed during validation of Delete with CmHandle event: " + e - .getMessage(), e); - } + sendEventFromFile(DELETE_CMHANDLE_PATH); + validateWithTimeout(20, () -> { + EndToEndExpectedResults notExpected = getExpectedResults(NOT_EXP_DELETE_CMHANDLE_PATH); + assertDbNotContainsExpectedValues(notExpected); + validateReceivedCloudEventMetrics(3, 1, 2, 1); }); + } + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) + @Test + void testTopologyIngestionConcurrentListeners() { + final String COMMON_EVENT_FOLDER = "src/test/resources/cloudeventdata/common/"; + + List commonPartition0 = List.of("ce-invalid-entity-attribute.json", "ce-one-entity.json", + "ce-relationship-invalid-module.json", "ce-relationship-invalid-module-type-pair.json", + "ce-create-geo-location.json", "ce-create-many-to-many.json"); + List commonPartition1 = List.of("ce-relationship-invalid-type.json", "ce-relationship-missing-a-side.json", + "ce-relationship-missing-b-side.json", "ce-relationship-missing-both-sides.json", + "ce-create-many-to-one.json", "ce-create-one-to-many.json"); + List partition2 = List.of("ce-create-one-to-one.json", "ce-create-relationship-connecting-same-entity.json", + "ce-create-second-case.json", "ce-delete-many-to-many.json", "ce-delete-many-to-one.json", + "ce-delete-one-to-many.json"); + List partition3 = List.of("ce-delete-one-to-one.json", "ce-delete-relationship-connecting-same-entity.json", + "ce-merge-long-names.json", "ce-merge-one-to-many2.json", "ce-source-entity-delete-cm-handle.json"); + + List cloudEventsForPartition0 = new ArrayList<>(); + cloudEventsForPartition0.addAll(getMultipleFilesInDirectory(COMMON_EVENT_FOLDER, commonPartition0)); + cloudEventsForPartition0.addAll(getMultipleFilesInDirectory(TEST_EVENT_FOLDER, commonPartition0)); + + List cloudEventsForPartition1 = new ArrayList<>(); + cloudEventsForPartition1.addAll(getMultipleFilesInDirectory(COMMON_EVENT_FOLDER, commonPartition1)); + cloudEventsForPartition1.addAll(getMultipleFilesInDirectory(TEST_EVENT_FOLDER, commonPartition1)); + + List cloudEventsForPartition2 = getMultipleFilesInDirectory(TEST_EVENT_FOLDER, partition2); + List cloudEventsForPartition3 = getMultipleFilesInDirectory(TEST_EVENT_FOLDER, partition3); + + List> cloudEventPathLists = List.of(cloudEventsForPartition0, cloudEventsForPartition1, + cloudEventsForPartition2, cloudEventsForPartition3); + + produceKafkaMessages(cloudEventPathLists, List.of(0, 1, 2, 3)); + validateWithTimeout(10, () -> { + assertEquals(2, assertDoesNotThrow(() -> getActiveConsumers(kafkaConfig.getTopologyIngestion().getGroupId()))); + validateReceivedCloudEventMetrics(15, 2, 5, 1); + validatePersistedCloudEventMetrics(8, 2, 5, 1); + }); + } + + private void validatePersistedCloudEventMetrics(final int createEventQuantity, final int mergeEventQuantity, + final int deleteEventQuantity, final int sourceEntityDeleteEventQuantity) { + assertEquals(createEventQuantity, customMetrics.getNumSuccessfullyPersistedCreateCloudEvents().count()); + assertEquals(deleteEventQuantity, customMetrics.getNumSuccessfullyPersistedDeleteCloudEvents().count()); + assertEquals(mergeEventQuantity, customMetrics.getNumSuccessfullyPersistedMergeCloudEvents().count()); + assertEquals(sourceEntityDeleteEventQuantity, customMetrics + .getNumSuccessfullyPersistedSourceEntityDeleteCloudEvents().count()); } private void validateReceivedCloudEventMetrics(final int create, final int merge, final int delete, @@ -216,124 +270,97 @@ public class EndToEndDbTest { assertEquals(sourceDelete, customMetrics.getNumReceivedCloudEventSourceEntityDelete().count()); } - private void validateDbResultsAfterCreate(final EndToEndExpectedResults values) { - assertDatabaseContainsValues(CNA_TABLE, values.get("entity_map_CNA_1")); - assertDatabaseContainsValues(CNA_TABLE, values.get("entity_map_CNA_2")); - assertDatabaseContainsValues(CNA_TABLE, values.get("entity_map_CNA_3")); - assertDatabaseContainsValues(GNBCUUP_TABLE, values.get("entity_map_GNBCUUP_1")); - assertDatabaseContainsValues(GNBCUCP_TABLE, values.get("entity_map_GNBCUCP_1")); - assertDatabaseContainsValues(GNBDU_TABLE, values.get("entity_map_GNBDU_1")); - - assertDatabaseContainsValues(GNBDU_CNA_TABLE, values.get("relation_map_GNBDU_CNA_1")); - assertDatabaseContainsValues(GNBDU_CNA_TABLE, values.get("relation_map_GNBDU_CNA_4")); - assertDatabaseContainsValues(GNBCUUP_CNA_TABLE, values.get("relation_map_GNBCUUP_CNA_2")); - assertDatabaseContainsValues(GNBCUUP_CNA_TABLE, values.get("relation_map_GNBCUUP_CNA_5")); - assertDatabaseContainsValues(GNBCUCP_CNA_TABLE, values.get("relation_map_GNBCUCP_CNA_3")); - assertDatabaseContainsValues(GNBCUCP_CNA_TABLE, values.get("relation_map_GNBCUCP_CNA_6")); - + private void assertDbContainsExpectedValues(EndToEndExpectedResults expectedResults) { + expectedResults.getTables().forEach(tableName -> expectedResults.getTableData(tableName).forEach( + attributes -> assertDatabaseContainsValues(tableName, attributes))); } - private void validateDbResultsAfterOneToOneCE(final EndToEndExpectedResults values) throws IOException { - assertDatabaseContainsValues(CNS_TABLE, values.get("entity_map_CNS_1")); - assertDatabaseContainsValues(ME_TABLE, values.get("entity_map_ME_1")); - assertDatabaseContainsValues(CNS_TABLE, values.get("entity_map_CNS_2")); - assertDatabaseContainsValues(ME_TABLE, values.get("entity_map_ME_2")); + private void assertDbNotContainsExpectedValues(EndToEndExpectedResults expectedResults) { + expectedResults.getTables().forEach(tableName -> expectedResults.getTableEntryIds(tableName).forEach( + ids -> assertDatabaseDoesNotContainRecord(tableName, ids))); } - private void validateDbResultsAfterMerge(final EndToEndExpectedResults values) { - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_1")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_2")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_3")); - - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_1")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_2")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_3")); + private void assertDatabaseContainsValues(final String table, final Map attributes) { + Result results = TiesDbServiceContainerizedTest.selectAllRowsFromTable(writeDataDslContext, + "ties_data.\"" + table + "\""); + boolean containsExpectedData = results.stream().anyMatch(row -> attributes.entrySet().stream().allMatch(attr -> { + if (attr.getValue() != null) { + return Objects.equals(attr.getValue().toString(), row.get(attr.getKey()).toString()); + } + return row.get(attr.getKey()) == null; + })); + assertTrue(containsExpectedData, String.format( + "Database table \"%s\" does not contain expected data, but it should.", table)); } - private void validateDbResultsAfterCmHandle(final EndToEndExpectedResults values) { - assertDatabaseContainsValues(CNA_TABLE, values.get("entity_map_CNA_4")); - assertDatabaseContainsValues(GNBDU_TABLE, values.get("entity_map_GNBDU_1")); - assertDatabaseContainsValues(GNBDU_TABLE, values.get("entity_map_GNBDU_2")); - assertDatabaseContainsValues(GNBCUUP_TABLE, values.get("entity_map_GNBCUUP_1")); - assertDatabaseContainsValues(GNBCUCP_TABLE, values.get("entity_map_GNBCUCP_1")); - assertDatabaseContainsValues(GNBCUCP_TABLE, values.get("entity_map_GNBCUCP_2")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_1")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_2")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("entity_map_NRCellDU_3")); - assertDatabaseContainsValues(GNBDU_CNA_TABLE, values.get("relation_map_GNBDU_CNA_1")); - assertDatabaseContainsValues(GNBCUUP_CNA_TABLE, values.get("relation_map_GNBCUUP_CNA_2")); - assertDatabaseContainsValues(GNBCUCP_CNA_TABLE, values.get("relation_map_GNBCUCP_CNA_3")); - assertDatabaseContainsValues(GNBDU_CNA_TABLE, values.get("relation_map_GNBDU_CNA_4")); - assertDatabaseContainsValues(GNBCUUP_CNA_TABLE, values.get("relation_map_GNBCUUP_CNA_5")); - assertDatabaseContainsValues(GNBCUCP_CNA_TABLE, values.get("relation_map_GNBCUCP_CNA_6")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_1")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_2")); - assertDatabaseContainsValues(NRCELLDU_TABLE, values.get("relation_map_GNBDU_NRCellDU_3")); + private void assertDatabaseDoesNotContainRecord(final String table, final String id) { + Result results = TiesDbServiceContainerizedTest.selectAllRowsFromTable(writeDataDslContext, + "ties_data.\"" + table + "\""); + if (results.isNotEmpty()) { + boolean containsRecord = results.stream().map(row -> row.get("id").toString()).anyMatch(id::equals); + assertFalse(containsRecord, String.format("Database table \"%s\" contains record: \"%s\", but it should not.", + table, id)); + } } - private void validateDbResultsAfterDelete() { - assertDatabaseDoesNotContainRecord(CNA_TABLE, "CloudNativeApplication_3"); - assertDatabaseDoesNotContainRecord(GNBCUCP_TABLE, "GNBCUCP_1"); - assertDatabaseDoesNotContainRecord(GNBDU_CNA_TABLE, "relation_1"); - assertDatabaseDoesNotContainRecord(GNBCUUP_CNA_TABLE, "relation_5"); - assertDatabaseDoesNotContainRecord(GNBCUCP_CNA_TABLE, "relation_3"); - assertDatabaseDoesNotContainRecord(GNBCUCP_CNA_TABLE, "relation_6"); + private int getActiveConsumers(String consumerGroupId) throws InterruptedException, ExecutionException { + try (Admin adminClient = Admin.create(kafkaAdmin.getConfigurationProperties())) { + DescribeConsumerGroupsOptions options = new DescribeConsumerGroupsOptions().includeAuthorizedOperations(false); + DescribeConsumerGroupsResult consumerGroupsResult = adminClient.describeConsumerGroups(List.of(consumerGroupId), + options); + ConsumerGroupDescription description = consumerGroupsResult.describedGroups().get(consumerGroupId).get(); + return description.members().size(); + } } - private void validateDbResultsAfterDeleteCmHandle() { - assertDatabaseDoesNotContainRecord(GNBDU_TABLE, "GNBDU_SED_1"); - assertDatabaseDoesNotContainRecord(GNBCUCP_TABLE, "GNBCUCP_SED_1"); - assertDatabaseDoesNotContainRecord(GNBCUCP_TABLE, "GNBCUCP_SED_2"); - assertDatabaseDoesNotContainRecord(GNBCUCP_CNA_TABLE, "relation_sed_1"); - assertDatabaseDoesNotContainRecord(GNBDU_CNA_TABLE, "relation_sed_2"); + private List getMultipleFilesInDirectory(String directoryName, List filenames) { + File[] files = new File(directoryName).listFiles(); + return files == null ? + List.of() : + Stream.of(files).map(File::getName).filter(filenames::contains).map(filename -> String.format("%s%s", + directoryName, filename)).toList(); } - private void validateDbResultsAfterDeleteOneToOne(final EndToEndExpectedResults values) { - // Test case 1: Delete an entity - relationship removed from an existing entity - assertDatabaseDoesNotContainRecord(CNS_TABLE, "relation_11"); - assertDatabaseDoesNotContainRecord(ME_TABLE, "relation_11"); - assertDatabaseDoesNotContainRecord(ME_TABLE, "ManagedElement_2"); - assertDatabaseContainsValues(CNS_TABLE, values.get("entity_map_CNS_1")); - // Test case 2: Delete a relationship - relationship removed from both existing - // entities - assertDatabaseDoesNotContainRecord(CNS_TABLE, "relation_12"); - assertDatabaseDoesNotContainRecord(ME_TABLE, "relation_12"); - assertDatabaseContainsValues(CNS_TABLE, values.get("entity_map_CNS_2")); - assertDatabaseContainsValues(ME_TABLE, values.get("entity_map_ME_2")); + private void produceKafkaMessages(List> cloudEventPathLists, List partitions) { + if (cloudEventPathLists.size() != partitions.size()) { + throw new RuntimeException("A partition is needed for every CloudEvent list"); + } + int maxLength = cloudEventPathLists.stream().mapToInt(List::size).max().orElse(0); + for (int i = 0; i < maxLength; i++) { + for (int j = 0; j < cloudEventPathLists.size(); j++) { + if (cloudEventPathLists.get(j).size() > i) { + sendEventFromFile(cloudEventPathLists.get(j).get(i), partitions.get(j)); + } + } + } } - private void assertDatabaseContainsValues(final String table, final Map attributes) { - Result results = tiesDbService.selectAllRowsFromTable("ties_data.\"" + table + "\""); - assertTrue(results.isNotEmpty(), String.format("Database table \"%s\" is empty, but it should not.", table)); - assertTrue(results.stream().anyMatch(row -> attributes.keySet().stream().allMatch(attr -> Objects.equals(attributes - .get(attr), row.get(attr)))), String.format( - "Database table \"%s\" does not contain expected data, but it should.", table)); + private void sendEventFromFile(final String path) { + final int partition_0 = 0; + sendEventFromFile(path, partition_0); } - private void assertDatabaseDoesNotContainRecord(final String table, final String id) { - Result results = tiesDbService.selectAllRowsFromTable("ties_data.\"" + table + "\""); - if (results.isNotEmpty()) { - boolean contains = results.stream().map(row -> row.get("id")).filter(Objects::nonNull).map(Object::toString) - .anyMatch(id::equals); - assertFalse(contains, String.format("Database table \"%s\" contains record: \"%s\", but it should not.", table, - id)); - } - } + private void sendEventFromFile(final String path, int partition) { + assertDoesNotThrow(() -> { + CloudEvent event = CloudEventTestUtil.getCloudEventFromJsonFile(path); + ProducerRecord producerRecord = new ProducerRecord(kafkaConfig + .getTopologyIngestion().getTopicName(), partition, null, event); + producer.send(producerRecord); + }); - private void sendEventFromFile(final String path) { - assertDoesNotThrow(() -> EndToEndTestUtil.sendEventList(List.of(CloudEventTestUtil.getCloudEventFromJsonFile(path)), - embeddedKafkaBroker, kafkaConfig)); } private EndToEndExpectedResults getExpectedResults(final String path) { return assertDoesNotThrow(() -> new EndToEndExpectedResults(path)); } - private void assertWithErrorMessage(Runnable assertion, String errorMessage) { - try { - assertion.run(); - } catch (Error e) { - throw new AssertionError(errorMessage + ": " + e.getMessage(), e); - } + private void validateWithTimeout(int timeout, Runnable runnable) { + Awaitility.await().atMost(timeout, TimeUnit.SECONDS).pollDelay(Duration.ofSeconds(5)).untilAsserted(() -> { + try { + runnable.run(); + } catch (AssertionError e) { + throw new AssertionError("Assertion failed during validation of CloudEvent: " + e.getMessage(), e); + } + }); } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/ModelSchemaServiceTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/ModelSchemaServiceTest.java deleted file mode 100644 index 6a57c1e..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/service/ModelSchemaServiceTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.service; - -import org.oran.smo.teiv.api.model.OranTeivSchema; -import org.oran.smo.teiv.api.model.OranTeivSchemaList; -import org.oran.smo.teiv.exception.TiesException; -import org.oran.smo.teiv.exposure.model.api.impl.ModelSchemaServiceImpl; -import org.oran.smo.teiv.exposure.spi.DataPersistanceService; -import org.oran.smo.teiv.exposure.spi.impl.DataPersistanceServiceImpl; -import org.oran.smo.teiv.exposure.spi.impl.StoredSchema; -import org.oran.smo.teiv.exposure.spi.mapper.MapperUtility; -import org.oran.smo.teiv.exposure.spi.mapper.PageMetaData; -import org.oran.smo.teiv.exposure.spi.mapper.PaginationMetaData; -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockMultipartFile; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.oran.smo.teiv.utils.TiesConstants.IN_USAGE; -import static org.oran.smo.teiv.utils.exposure.PaginationVerifierTestUtil.verifyResponse; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class ModelSchemaServiceTest { - - private static final DataPersistanceService dataPersistanceService = mock(DataPersistanceServiceImpl.class); - private static final MapperUtility mapperUtility = new MapperUtility(); - private final ModelSchemaServiceImpl service = new ModelSchemaServiceImpl(dataPersistanceService); - - @BeforeAll - static void beforeAll() { - StoredSchema ranLogicalToCloud = new StoredSchema(); - ranLogicalToCloud.setName("o-ran-smo-teiv-cloud-to-ran"); - ranLogicalToCloud.setNamespace("urn:o-ran:smo-teiv-cloud-to-ran"); - ranLogicalToCloud.setDomain("CLOUD_TO_RAN"); - ranLogicalToCloud.setRevision("2023-10-24"); - ranLogicalToCloud.setStatus(IN_USAGE); - - StoredSchema ranEquipment = new StoredSchema(); - ranEquipment.setName("o-ran-smo-teiv-equipment"); - ranEquipment.setNamespace("urn:o-ran:smo-teiv-equipment"); - ranEquipment.setDomain("EQUIPMENT"); - ranEquipment.setRevision("2023-06-26"); - ranEquipment.setStatus(IN_USAGE); - - StoredSchema ranOamToCloud = new StoredSchema(); - ranOamToCloud.setName("o-ran-smo-teiv-oam-to-cloud"); - ranOamToCloud.setNamespace("urn:o-ran:smo-teiv-oam-to-cloud"); - ranOamToCloud.setDomain("OAM_TO_CLOUD"); - ranOamToCloud.setRevision("2023-10-24"); - ranOamToCloud.setStatus(IN_USAGE); - - StoredSchema ranOamToLogical = new StoredSchema(); - ranOamToLogical.setName("o-ran-smo-teiv-oam-to-ran"); - ranOamToLogical.setNamespace("urn:o-ran:smo-teiv-oam-to-ran"); - ranOamToLogical.setDomain("OAM_TO_RAN"); - ranOamToLogical.setRevision("2023-10-24"); - ranOamToLogical.setStatus(IN_USAGE); - - StoredSchema ranCloud = new StoredSchema(); - ranCloud.setName("o-ran-smo-teiv-cloud"); - ranCloud.setNamespace("urn:o-ran:smo-teiv-cloud"); - ranCloud.setDomain("CLOUD"); - ranCloud.setRevision("2023-06-26"); - ranCloud.setStatus(IN_USAGE); - - StoredSchema ranOam = new StoredSchema(); - ranOam.setName("o-ran-smo-teiv-oam"); - ranOam.setNamespace("urn:o-ran:smo-teiv-oam"); - ranOam.setDomain("OAM"); - ranOam.setRevision("2023-06-26"); - ranOam.setContent("yang model o-ran-smo-teiv-oam {}"); - ranOam.setStatus(IN_USAGE); - ranOam.setOwnerAppId("BUILT_IN_MODULE"); - - when(dataPersistanceService.getSchemas(PaginationDTO.builder().offset(0).limit(8).build())).thenReturn(mapperUtility - .wrapSchema(Arrays.asList(ranLogicalToCloud, ranEquipment, ranOamToCloud, ranOamToLogical, ranCloud, - ranOam), PaginationDTO.builder().offset(0).limit(8).build())); - when(dataPersistanceService.getSchema("o-ran-smo-teiv-oam")).thenReturn(ranOam); - when(dataPersistanceService.getSchema("o-ran-smo-teiv")).thenReturn(null); - - when(dataPersistanceService.getSchemas("ties_logical", PaginationDTO.builder().basePath("/schemas/ties_logical") - .offset(0).limit(8).build())).thenReturn(mapperUtility.wrapSchema(new ArrayList<>(), PaginationDTO.builder() - .basePath("/schemas/ties_logical").offset(0).limit(8).build())); - when(dataPersistanceService.getSchemas("CLOUD", PaginationDTO.builder().basePath("/schemas/CLOUD").offset(0).limit( - 8).build())).thenReturn(mapperUtility.wrapSchema(List.of(ranCloud), PaginationDTO.builder().basePath( - "/schemas/CLOUD").offset(0).limit(8).build())); - when(dataPersistanceService.getSchemas("ran*", PaginationDTO.builder().basePath("/schemas/ran*").offset(0).limit(8) - .build())).thenReturn(mapperUtility.wrapSchema(Arrays.asList(ranLogicalToCloud, ranEquipment, ranOamToCloud, - ranOamToLogical, ranCloud, ranOam), PaginationDTO.builder().basePath("/schemas/ran*").offset(0) - .limit(8).build())); - } - - @Test - void testGetSchemas() throws IOException { - //when - OranTeivSchemaList schemaItems = service.getSchemas(PaginationDTO.builder().offset(0).limit(8).build()); - //then - List schemasMetaData = schemaItems.getItems(); - Assertions.assertEquals(6, schemasMetaData.size()); - - MapperUtility mapperUtility = new MapperUtility(); - List resultException = new ArrayList<>(schemasMetaData); - PaginationDTO paginationDTO = PaginationDTO.builder().basePath("/schemas").offset(100).limit(5).build(); - paginationDTO.setTotalSize(5); - Assertions.assertThrows(TiesException.class, () -> mapperUtility.wrapList(resultException, paginationDTO)); - - Map fullResult = new HashMap<>(); - fullResult.put("items", schemasMetaData); - - PaginationMetaData pmd = new PaginationMetaData(); - - PaginationDTO paginationDTO2 = PaginationDTO.builder().basePath("/schemas").offset(0).limit(15).build(); - paginationDTO2.setTotalSize(6); - fullResult.putAll(pmd.getObjectList(paginationDTO2)); - - verifyResponse(fullResult, mapperUtility.wrapList(resultException, PaginationDTO.builder().basePath("/schemas") - .offset(0).limit(15).build())); - - Map fullResult2 = new HashMap<>(); - fullResult2.put("items", schemasMetaData.subList(0, 5)); - - PageMetaData pageMetaDataSelf2 = new PageMetaData(0, PaginationDTO.builder().limit(5).basePath("/schemas").build()); - PageMetaData pageMetaDataFirst2 = new PageMetaData(0, PaginationDTO.builder().limit(5).basePath("/schemas") - .build()); - PageMetaData pageMetaDataPrev2 = new PageMetaData(0, PaginationDTO.builder().limit(5).basePath("/schemas").build()); - PageMetaData pageMetaDataNext2 = new PageMetaData(5, PaginationDTO.builder().limit(5).basePath("/schemas").build()); - PageMetaData pageMetaDataLast2 = new PageMetaData(5, PaginationDTO.builder().limit(5).basePath("/schemas").build()); - - fullResult2.put("self", pageMetaDataSelf2); - fullResult2.put("first", pageMetaDataFirst2); - fullResult2.put("prev", pageMetaDataPrev2); - fullResult2.put("next", pageMetaDataNext2); - fullResult2.put("last", pageMetaDataLast2); - - verifyResponse(fullResult2, mapperUtility.wrapList(resultException, PaginationDTO.builder().basePath("/schemas") - .offset(0).limit(5).build())); - } - - @Test - void testGetSchemasByName() { - //when - String incorrectSchemaName = "o-ran-smo-teiv"; - String responseForCorrectSchemaName = service.getSchemaByName("o-ran-smo-teiv-oam"); - //then - Assertions.assertThrowsExactly(TiesException.class, () -> service.getSchemaByName(incorrectSchemaName)); - Assertions.assertTrue(responseForCorrectSchemaName.contains("o-ran-smo-teiv-oam")); - } - - @Test - void testGetSchemasInDomain() { - //when - List schemasInIncorrectDomain = (List) service.getSchemasInDomain("ties_logical", - PaginationDTO.builder().basePath("/schemas/ties_logical").offset(0).limit(8).build()).getItems(); - List schemasInDomainRanCloud = (List) service.getSchemasInDomain("CLOUD", - PaginationDTO.builder().basePath("/schemas/CLOUD").offset(0).limit(8).build()).getItems(); - List schemasInDomainPartiallyMatchingRan = (List) service.getSchemasInDomain("ran*", - PaginationDTO.builder().basePath("/schemas/ran*").offset(0).limit(8).build()).getItems(); - //then - Assertions.assertEquals(List.of(), schemasInIncorrectDomain); - Assertions.assertEquals(1, schemasInDomainRanCloud.size()); - Assertions.assertEquals(6, schemasInDomainPartiallyMatchingRan.size()); - } - - @Test - void testCreateSchema() { - service.createSchema(new MockMultipartFile("yangModule.yang", "yangContent".getBytes(StandardCharsets.UTF_8))); - } - - @Test - void testDeleteSchema() { - Assertions.assertEquals("Invalid schema name", Assertions.assertThrowsExactly(TiesException.class, () -> service - .deleteSchema("schemaToDelete")).getMessage()); - - Assertions.assertEquals("Forbidden", Assertions.assertThrowsExactly(TiesException.class, () -> service.deleteSchema( - "o-ran-smo-teiv-oam")).getMessage()); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/SchemaCleanUpServiceTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/SchemaCleanUpServiceTest.java new file mode 100644 index 0000000..4228b71 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/service/SchemaCleanUpServiceTest.java @@ -0,0 +1,112 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.service; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.Set; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.oran.smo.teiv.api.model.OranTeivClassifier; +import org.oran.smo.teiv.api.model.OranTeivDecorator; +import org.oran.smo.teiv.exposure.consumerdata.ConsumerDataOperationRegistry; +import org.oran.smo.teiv.exposure.consumerdata.operation.ClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DecoratorsOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteClassifiersOperation; +import org.oran.smo.teiv.exposure.consumerdata.operation.DeleteDecoratorsOperation; +import org.oran.smo.teiv.exposure.spi.DataRepository; +import org.oran.smo.teiv.exposure.spi.ModelRepository; +import org.oran.smo.teiv.exposure.spi.impl.DataRepositoryImpl; +import org.oran.smo.teiv.exposure.spi.impl.ModelRepositoryImpl; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; +import org.oran.smo.teiv.schema.SchemaRegistry; + +class SchemaCleanUpServiceTest { + + private static final ModelRepository MODEL_REPOSITORY = mock(ModelRepositoryImpl.class); + private static final DataRepository DATA_REPOSITORY = mock(DataRepositoryImpl.class); + private static final ConsumerDataOperationRegistry consumerDataOperationRegistry = mock( + ConsumerDataOperationRegistry.class); + private static final SchemaCleanUpService schemaCleanUpService = new SchemaCleanUpService(MODEL_REPOSITORY, + DATA_REPOSITORY, consumerDataOperationRegistry); + private static final ClassifiersOperation deleteClassifiersOperation = mock(DeleteClassifiersOperation.class); + private static final DecoratorsOperation deleteDecoratorsOperation = mock(DeleteDecoratorsOperation.class); + + @BeforeAll + static void setUp() throws SchemaLoaderException { + new MockSchemaLoader().loadSchemaRegistry(); + + when(DATA_REPOSITORY.getDecoratorsForSchema("gnbcucp-gnbcuup-model")).thenReturn(Collections.singleton( + "gnbcucp-gnbcuup-model:metadata")); + when(DATA_REPOSITORY.getClassifiersForSchema("gnbcucp-gnbcuup-model")).thenReturn(Collections.singleton( + "gnbcucp-gnbcuup-model:Weekend")); + + when(DATA_REPOSITORY.getRelationshipIdsForClassifierDeletion(any(), any())).thenReturn(Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getRelationshipIdsForDecoratorDeletion(any(), any())).thenReturn(Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getEntityIdsForClassifierDeletion(any(), any())).thenReturn(Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getEntityIdsForDecoratorDeletion(any(), any())).thenReturn(Collections.EMPTY_LIST); + + when(DATA_REPOSITORY.getRelationshipIdsForClassifierDeletion(SchemaRegistry.getRelationTypeByName( + "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"), Set.of("gnbcucp-gnbcuup-model:Weekend"))).thenReturn( + Collections.singletonList( + "urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc="), + Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getRelationshipIdsForDecoratorDeletion(SchemaRegistry.getRelationTypeByName( + "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"), Set.of("gnbcucp-gnbcuup-model:metadata"))) + .thenReturn(Collections.singletonList( + "urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc="), + Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getRelationshipIdsForClassifierDeletion(SchemaRegistry.getRelationTypeByName( + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"), Set.of("gnbcucp-gnbcuup-model:Weekend"))).thenReturn(Collections + .singletonList( + "urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU="), + Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getRelationshipIdsForDecoratorDeletion(SchemaRegistry.getRelationTypeByName( + "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"), Set.of("gnbcucp-gnbcuup-model:metadata"))).thenReturn(Collections + .singletonList( + "urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU="), + Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getEntityIdsForClassifierDeletion(SchemaRegistry.getEntityTypeByName("NRSectorCarrier"), Set + .of("gnbcucp-gnbcuup-model:Weekend"))).thenReturn(Collections.singletonList( + "E49D942C16E0364E1E0788138916D70C"), Collections.EMPTY_LIST); + when(DATA_REPOSITORY.getEntityIdsForDecoratorDeletion(SchemaRegistry.getEntityTypeByName("NRSectorCarrier"), Set.of( + "gnbcucp-gnbcuup-model:metadata"))).thenReturn(Collections.singletonList( + "E49D942C16E0364E1E0788138916D70C"), Collections.EMPTY_LIST); + + when(consumerDataOperationRegistry.getClassifiersOperation(OranTeivClassifier.OperationEnum.DELETE)).thenReturn( + deleteClassifiersOperation); + when(consumerDataOperationRegistry.getDecoratorsOperation(OranTeivDecorator.OperationEnum.DELETE)).thenReturn( + deleteDecoratorsOperation); + } + + @Test + void cleanUpModuleTest() { + schemaCleanUpService.cleanUpModule("gnbcucp-gnbcuup-model"); + + verify(MODEL_REPOSITORY).deleteModuleByName("gnbcucp-gnbcuup-model"); + } +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbOperationResultsTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbOperationResultsTest.java index d44e3ab..8485db9 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbOperationResultsTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbOperationResultsTest.java @@ -20,8 +20,6 @@ */ package org.oran.smo.teiv.service; -import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_A_SIDE; -import static org.oran.smo.teiv.utils.TiesConstants.PROPERTY_B_SIDE; import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -39,7 +37,6 @@ import java.util.Optional; import javax.sql.DataSource; -import org.oran.smo.teiv.exception.TiesException; import org.jooq.DSLContext; import org.jooq.JSONB; import org.jooq.Record; @@ -49,6 +46,7 @@ import org.jooq.impl.DSL; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.oran.smo.teiv.service.models.OperationResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.test.context.SpringBootTest; @@ -56,12 +54,18 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ActiveProfiles; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.cloudevents.CloudEvent; + import org.oran.smo.teiv.db.TestPostgresqlContainer; import org.oran.smo.teiv.exception.InvalidFieldInYangDataException; +import org.oran.smo.teiv.exception.TiesException; import org.oran.smo.teiv.ingestion.DeadlockRetryPolicy; import org.oran.smo.teiv.ingestion.validation.IngestionOperationValidatorFactory; import org.oran.smo.teiv.ingestion.validation.MaximumCardinalityViolationException; -import org.oran.smo.teiv.service.models.OperationResult; +import org.oran.smo.teiv.schema.EntityType; +import org.oran.smo.teiv.schema.BidiDbNameMapper; + import org.oran.smo.teiv.schema.PostgresSchemaLoader; import org.oran.smo.teiv.schema.RelationType; import org.oran.smo.teiv.schema.SchemaLoaderException; @@ -71,14 +75,12 @@ import org.oran.smo.teiv.service.cloudevent.data.ParsedCloudEventData; import org.oran.smo.teiv.service.cloudevent.data.Relationship; import org.oran.smo.teiv.startup.SchemaHandler; import org.oran.smo.teiv.utils.CloudEventTestUtil; -import org.oran.smo.teiv.utils.ConvertToJooqTypeUtil; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.cloudevents.CloudEvent; +import org.oran.smo.teiv.utils.JooqTypeConverter; @Configuration @SpringBootTest @ActiveProfiles({ "test", "ingestion" }) -public class TiesDbOperationResultsTest { +class TiesDbOperationResultsTest { public static TestPostgresqlContainer postgresqlContainer = TestPostgresqlContainer.getInstance(); private static TiesDbService tiesDbService; private static TiesDbOperations tiesDbOperations; @@ -122,16 +124,18 @@ public class TiesDbOperationResultsTest { assertEquals(3, mergeResult.size()); assertEquals("ManagedElement_1", mergeResult.get(0).getId()); - assertEquals("ManagedElement", mergeResult.get(0).getEntryType()); - assertEquals(Map.of(), mergeResult.get(0).getContent()); + assertEquals("ManagedElement", mergeResult.get(0).getType()); + assertEquals(Map.of(), mergeResult.get(0).getAttributes()); assertEquals("ENodeBFunction_1", mergeResult.get(1).getId()); - assertEquals("ENodeBFunction", mergeResult.get(1).getEntryType()); - assertEquals(Map.of(), mergeResult.get(1).getContent()); + assertEquals("ENodeBFunction", mergeResult.get(1).getType()); + assertEquals(Map.of(), mergeResult.get(1).getAttributes()); assertEquals("relation_1", mergeResult.get(2).getId()); - assertEquals("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", mergeResult.get(2).getEntryType()); - assertEquals(Map.of("aSide", "ManagedElement_1", "bSide", "ENodeBFunction_1"), mergeResult.get(2).getContent()); + assertEquals("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", mergeResult.get(2).getType()); + assertEquals("ManagedElement_1", mergeResult.get(2).getASide()); + assertEquals("ENodeBFunction_1", mergeResult.get(2).getBSide()); + } @Test @@ -140,14 +144,15 @@ public class TiesDbOperationResultsTest { managedElementEntity.put("id", "managed_element_entity_id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity); // Delete operation - expected to succeed List deleteResultMatch = tiesDbOperations.deleteEntity(dslContext, SchemaRegistry .getEntityTypeByName("ManagedElement"), "managed_element_entity_id1"); assertFalse(deleteResultMatch.isEmpty(), "Delete operation should return a non-empty list"); - assertTrue(deleteResultMatch.contains(new OperationResult("managed_element_entity_id1", "ManagedElement", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createEntityOperationResult("managed_element_entity_id1", + "ManagedElement")), "The list should contain the delete operation result with id: 'managed_element_entity_id1'"); // Delete operation with the same EIID - expected to fail @@ -169,11 +174,13 @@ public class TiesDbOperationResultsTest { Map cloudNativeSystemEntity = new HashMap<>(); cloudNativeSystemEntity.put("id", "cloud_native_system_entity_id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity); cloudNativeSystemEntity.put("name", "CloudNativeSystem"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity); // Delete operation for aSide - expected to succeed Optional deleteASideResultMatch = tiesDbOperations.deleteRelationFromEntityTableByRelationId( @@ -181,8 +188,9 @@ public class TiesDbOperationResultsTest { "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); assertTrue(deleteASideResultMatch.isPresent(), "Delete operation should return a present Optional"); - assertEquals(new OperationResult("relation_eiid1", "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", null), - deleteASideResultMatch.get(), "The delete operation result should be present for: 'relation_eiid1'"); + assertEquals(OperationResult.createRelationshipOperationResult("relation_eiid1", + "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM"), deleteASideResultMatch.get(), + "The delete operation result should be present for: 'relation_eiid1'"); // Delete operation with the same EIID - expected to fail Optional deleteResultNoMatch = tiesDbOperations.deleteRelationFromEntityTableByRelationId( @@ -191,8 +199,10 @@ public class TiesDbOperationResultsTest { assertTrue(deleteResultNoMatch.isEmpty(), "Delete operation should return an empty list for already deleted/non existing ID"); - Result rows = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); - Result rowsOnBSide = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rows = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); + Result rowsOnBSide = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals("managed_element_entity_id1", rows.get(0).get("id")); assertEquals("fdn1", rows.get(0).get("fdn")); assertEquals("cloud_native_system_entity_id1", rowsOnBSide.get(0).get("id")); @@ -200,7 +210,7 @@ public class TiesDbOperationResultsTest { assertNull(rows.get(0).get("REL_FK_deployed-as-cloudNativeSystem")); assertNull(rows.get(0).get("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); assertNull(rowsOnBSide.get(0).get("REL_FK_deployed-managedElement")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of()), rows.get(0).get( + assertEquals(JooqTypeConverter.toJsonb(List.of()), rows.get(0).get( "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); } @@ -217,8 +227,8 @@ public class TiesDbOperationResultsTest { cna1.put("REL_FK_realised-managedElement", "managed_element_entity_id1"); cna1.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_eiid1"); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElement1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna1); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElement1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna1); // Delete operation with existing relationship List deleteResultMatch = tiesDbOperations.deleteRelationshipByManySideEntityId(dslContext, @@ -226,8 +236,8 @@ public class TiesDbOperationResultsTest { "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")); assertFalse(deleteResultMatch.isEmpty(), "Delete operation should return a non-empty list"); - assertTrue(deleteResultMatch.contains(new OperationResult("relation_eiid1", - "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("relation_eiid1", + "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'relation_eiid1'"); // Delete operation with the same entity ID - expected to return an empty list @@ -264,10 +274,10 @@ public class TiesDbOperationResultsTest { cna3.put("REL_FK_realised-managedElement", "managed_element_entity_id1"); cna3.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_eiid3"); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElement1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna2); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna3); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElement1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna2); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna3); // Delete operation for managed_element_entity_id1 List deleteResultMatch = tiesDbOperations.deleteEntity(dslContext, SchemaRegistry @@ -276,21 +286,23 @@ public class TiesDbOperationResultsTest { // Check if all expected IDs are present in the deletion result assertEquals(4, deleteResultMatch.size(), "Delete operation should match expected size"); - assertTrue(deleteResultMatch.contains(new OperationResult("managed_element_entity_id1", "ManagedElement", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createEntityOperationResult("managed_element_entity_id1", + "ManagedElement")), "The list should contain the delete operation result with id: 'managed_element_entity_id1'"); - assertTrue(deleteResultMatch.contains(new OperationResult("relation_eiid1", - "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("relation_eiid1", + "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'relation_eiid1'"); - assertTrue(deleteResultMatch.contains(new OperationResult("relation_eiid2", - "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("relation_eiid2", + "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'relation_eiid2'"); - assertTrue(deleteResultMatch.contains(new OperationResult("relation_eiid3", - "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("relation_eiid3", + "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'relation_eiid3'"); // Verify all related entities have their relationships deleted - Result rows = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeApplication\""); + Result rows = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\""); assertEquals(3, rows.size()); for (Record row : rows) { assertNull(row.get("REL_FK_realised-managedElement"), @@ -329,30 +341,35 @@ public class TiesDbOperationResultsTest { rel2.put("aSide_GNBCUCPFunction", "gnbcucp_id1"); rel2.put("bSide_CloudNativeApplication", "cloud_native_id2"); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFunction\"", gnbcucp1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna2); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", rel1); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", rel2); + tiesDbOperations.merge(dslContext, "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\"", gnbcucp1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna2); + tiesDbOperations.merge(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"", rel1); + tiesDbOperations.merge(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"", rel2); - Result row1 = tiesDbService.selectAllRowsFromTable("ties_data.\"GNBCUCPFunction\""); + Result row1 = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\""); assertEquals(1, row1.size()); - Result row2 = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeApplication\""); + Result row2 = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\""); assertEquals(2, row2.size()); - Result row3 = tiesDbService.selectAllRowsFromTable( - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\""); + Result row3 = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\""); assertEquals(2, row3.size()); + RelationType relType = SchemaRegistry.getRelationTypeByName("GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); + // Test deletion of a relationship by ID (expected success) Optional deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByRelationId(dslContext, - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", "rel_id1"); + relType, "rel_id1"); assertTrue(deleteResultMatch.isPresent(), "Delete operation should return a present Optional"); - assertEquals(new OperationResult("rel_id1", "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", null), - deleteResultMatch.get(), "Deleted relationship ID should match 'rel_id1'"); + assertEquals(OperationResult.createRelationshipOperationResult("rel_id1", + "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"), deleteResultMatch.get(), + "Deleted relationship ID should match 'rel_id1'"); // Test deletion of the same relationship ID again (expected failure) Optional deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByRelationId(dslContext, - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", "rel_id1"); + relType, "rel_id1"); assertTrue(deleteResultNoMatch.isEmpty(), "Delete operation should not return a present Optional"); } @@ -385,38 +402,40 @@ public class TiesDbOperationResultsTest { rel2.put("aSide_GNBCUCPFunction", "gnbcucp_id1"); rel2.put("bSide_CloudNativeApplication", "cloud_native_id2"); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFunction\"", gnbcucp1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna2); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", rel1); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", rel2); + tiesDbOperations.merge(dslContext, "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\"", gnbcucp1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna1); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cna2); + tiesDbOperations.merge(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"", rel1); + tiesDbOperations.merge(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"", rel2); - assertEquals(1, tiesDbService.selectAllRowsFromTable("ties_data.\"GNBCUCPFunction\"").size(), - "Expected one GNBCUCPFunction record"); - assertEquals(2, tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeApplication\"").size(), + assertEquals(1, TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\"").size(), "Expected one GNBCUCPFunction record"); + assertEquals(2, TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"").size(), "Expected two CloudNativeApplication records"); - assertEquals(2, tiesDbService.selectAllRowsFromTable( - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"").size(), + assertEquals(2, TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"").size(), "Expected two GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION relations"); + RelationType relType = SchemaRegistry.getRelationTypeByName("GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"); + // Test deletion of relations by entity ID (expected to delete two relations) - List deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", "gnbcucp_id1", "aSide_GNBCUCPFunction", - "bSide_CloudNativeApplication"); + List deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, relType, + "gnbcucp_id1", "aSide_GNBCUCPFunction", "bSide_CloudNativeApplication"); + assertEquals(2, deleteResultMatch.size(), "Expected two relations to be deleted"); - assertTrue(deleteResultMatch.contains(new OperationResult("rel_id1", - "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("rel_id1", + "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'rel_id1'"); - assertTrue(deleteResultMatch.contains(new OperationResult("rel_id2", - "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", null)), + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("rel_id2", + "GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")), "The list should contain the delete operation result with id: 'rel_id2'"); // Test deletion of relations by the same entity ID again (expected to find no // relations to delete) - List deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", "gnbcucp_id1", "aSide_GNBCUCPFunction", - "bSide_CloudNativeApplication"); + List deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, relType, + "gnbcucp_id1", "aSide_GNBCUCPFunction", "bSide_CloudNativeApplication"); assertTrue(deleteResultNoMatch.isEmpty(), "Delete operation should return an empty list for already deleted/non existing ID"); } @@ -455,26 +474,32 @@ public class TiesDbOperationResultsTest { rel2.put("bSide_AntennaModule", "module_id2"); rel2.put("aSide_AntennaModule", "module_id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"AntennaModule\"", antennaModule1); - tiesDbOperations.merge(dslContext, "ties_data.\"AntennaModule\"", antennaModule2); - tiesDbOperations.merge(dslContext, "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", rel1); - tiesDbOperations.merge(dslContext, "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", rel2); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule1); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule2); + tiesDbOperations.merge(dslContext, "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\"", rel1); + tiesDbOperations.merge(dslContext, "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\"", rel2); - Result row1 = tiesDbService.selectAllRowsFromTable("ties_data.\"AntennaModule\""); + Result row1 = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\""); assertEquals(2, row1.size()); - Result row2 = tiesDbService.selectAllRowsFromTable("ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\""); + Result row2 = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\""); assertEquals(2, row2.size()); + RelationType antennaRelType1 = SchemaRegistry.getRelationTypeByName("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); + // Test deletion of a relationship by ID (expected success) Optional deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByRelationId(dslContext, - "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", "rel_id1"); + antennaRelType1, "rel_id1"); + assertTrue(deleteResultMatch.isPresent(), "Delete operation should return a present Optional"); - assertEquals(new OperationResult("rel_id1", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", null), deleteResultMatch - .get(), "Deleted relationship ID should match 'rel_id1'"); + assertEquals(OperationResult.createRelationshipOperationResult("rel_id1", + "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"), deleteResultMatch.get(), + "Deleted relationship ID should match 'rel_id1'"); // Test deletion of the same relationship ID again (expected failure) Optional deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByRelationId(dslContext, - "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", "rel_id1"); + antennaRelType1, "rel_id1"); assertTrue(deleteResultNoMatch.isEmpty(), "Delete operation should not return a present Optional"); } @@ -513,32 +538,35 @@ public class TiesDbOperationResultsTest { rel2.put("bSide_AntennaModule", "module_id2"); rel2.put("aSide_AntennaModule", "module_id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"AntennaModule\"", antennaModule1); - tiesDbOperations.merge(dslContext, "ties_data.\"AntennaModule\"", antennaModule2); - tiesDbOperations.merge(dslContext, "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", rel1); - tiesDbOperations.merge(dslContext, "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", rel2); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule1); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule2); + tiesDbOperations.merge(dslContext, "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\"", rel1); + tiesDbOperations.merge(dslContext, "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\"", rel2); + + assertEquals(2, TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"").size(), "Expected two AntennaModule records"); + assertEquals(2, TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, + "ties_data.\"5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6\"").size(), + "Expected two ANTENNAMODULE_REALISED_BY_ANTENNAMODULE relations"); - assertEquals(2, tiesDbService.selectAllRowsFromTable("ties_data.\"AntennaModule\"").size(), - "Expected two AntennaModule records"); - assertEquals(2, tiesDbService.selectAllRowsFromTable("ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"") - .size(), "Expected two ANTENNAMODULE_REALISED_BY_ANTENNAMODULE relations"); + RelationType relType = SchemaRegistry.getRelationTypeByName("ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"); // Test deletion of relations by entity ID (expected to delete two relations) - List deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, - "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", "module_id1", "aSide_AntennaModule", - "bSide_AntennaModule"); + List deleteResultMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, relType, + "module_id1", "aSide_AntennaModule", "bSide_AntennaModule"); assertEquals(2, deleteResultMatch.size(), "Expected two relations to be deleted"); - assertTrue(deleteResultMatch.contains(new OperationResult("rel_id1", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", - null)), "The list should contain the delete operation result with id: 'rel_id1'"); + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("rel_id1", + "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE")), + "The list should contain the delete operation result with id: 'rel_id1'"); - assertTrue(deleteResultMatch.contains(new OperationResult("rel_id2", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", - null)), "The list should contain the delete operation result with id: 'rel_id2'"); + assertTrue(deleteResultMatch.contains(OperationResult.createRelationshipOperationResult("rel_id2", + "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE")), + "The list should contain the delete operation result with id: 'rel_id2'"); // Test deletion of relations by the same entity ID again (expected to find no // relations to delete) - List deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, - "ties_data.\"ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\"", "module_id1", "aSide_AntennaModule", - "bSide_AntennaModule"); + List deleteResultNoMatch = tiesDbOperations.deleteManyToManyRelationByEntityId(dslContext, relType, + "module_id1", "aSide_AntennaModule", "bSide_AntennaModule"); assertTrue(deleteResultNoMatch.isEmpty(), "Delete operation should return an empty list for already deleted/non existing ID"); @@ -669,8 +697,8 @@ public class TiesDbOperationResultsTest { parsedCloudEventData); assertEquals(40, mergeResult.size()); - //One_To_One Relationship - Relationship oneToOneRelationship = new Relationship("o-ran-smo-teiv-oam-to-cloud", + // One_To_One Relationship + Relationship oneToOneRelationship = new Relationship("o-ran-smo-teiv-ran-oam-to-cloud", "MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM", "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_relation_3", "ManagedElement_3", "CloudNativeSystem_3", List .of()); @@ -679,8 +707,8 @@ public class TiesDbOperationResultsTest { .deleteRelationFromEntityTableByRelationId(dslContext, oneToOneRelationship.getId(), oneToOneRelationType); assertTrue(deleteOneToOneRelationshipResult.isPresent(), "Delete operation should return a present Optional"); - //One_To_Many Relationship - Relationship oneToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + // One_To_Many Relationship + Relationship oneToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU", "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_2", "GNBDUFunction_1", "NRCellDU_2", List.of()); RelationType oneToManyRelationType = SchemaRegistry.getRelationTypeByName(oneToManyRelationship.getType()); @@ -689,8 +717,8 @@ public class TiesDbOperationResultsTest { oneToManyRelationType); assertTrue(deleteOneToManyRelationshipResult.isPresent(), "Delete operation should return a present Optional"); - //Many_To_One Relationship - Relationship manyToOneRelationship = new Relationship("o-ran-smo-teiv-cloud", + // Many_To_One Relationship + Relationship manyToOneRelationship = new Relationship("o-ran-smo-teiv-ran-cloud", "CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE", "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE_relation_3", "CloudNativeApplication_3", "Namespace_3", List .of()); @@ -700,37 +728,36 @@ public class TiesDbOperationResultsTest { manyToOneRelationType); assertTrue(deleteManyToOneRelationshipResult.isPresent(), "Delete operation should return a present Optional"); - //Many_To_Many Relationship - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-cloud-to-ran", + // Many_To_Many Relationship + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical-to-cloud", "GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN", "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_1", "GNBDUFunction_1", "CloudNativeApplication_1", List.of()); RelationType manyToManyRelationType = SchemaRegistry.getRelationTypeByName(manyToManyRelationship.getType()); Optional deleteManyToManyRelationshipResult = tiesDbOperations - .deleteManyToManyRelationByRelationId(dslContext, manyToManyRelationType.getTableName(), - manyToManyRelationship.getId()); + .deleteManyToManyRelationByRelationId(dslContext, manyToManyRelationType, manyToManyRelationship.getId()); assertTrue(deleteManyToManyRelationshipResult.isPresent(), "Delete operation should return a present Optional"); - //One_To_One Relationship ConnectingSameEntity - Relationship connectingSameEntityOneToOneRelationship = new Relationship("o-ran-smo-teiv-equipment", + // One_To_One Relationship ConnectingSameEntity + Relationship connectingSameEntityOneToOneRelationship = new Relationship("o-ran-smo-teiv-ran-equipment", "ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE", "ANTENNAMODULE_DEPLOYED_ON_ANTENNAMODULE_relation_1", "AntennaModule_5", "AntennaModule_6", List.of()); RelationType connectingSameEntityType = SchemaRegistry.getRelationTypeByName( connectingSameEntityOneToOneRelationship.getType()); Optional deleteConnectingSameEntityOneToOneRelationshipResult = tiesDbOperations - .deleteManyToManyRelationByRelationId(dslContext, connectingSameEntityType.getTableName(), + .deleteManyToManyRelationByRelationId(dslContext, connectingSameEntityType, connectingSameEntityOneToOneRelationship.getId()); assertTrue(deleteConnectingSameEntityOneToOneRelationshipResult.isPresent(), "Delete operation should return a present Optional"); - //One_To_Many Relationship ConnectingSameEntity - Relationship connectingSameEntityOneToManyRelationship = new Relationship("o-ran-smo-teiv-equipment", + // One_To_Many Relationship ConnectingSameEntity + Relationship connectingSameEntityOneToManyRelationship = new Relationship("o-ran-smo-teiv-ran-equipment", "ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_relation_1", "AntennaModule_1", "AntennaModule_2", List.of()); connectingSameEntityType = SchemaRegistry.getRelationTypeByName(connectingSameEntityOneToManyRelationship .getType()); Optional deleteConnectingSameEntityOneToManyRelationshipResult = tiesDbOperations - .deleteManyToManyRelationByRelationId(dslContext, connectingSameEntityType.getTableName(), + .deleteManyToManyRelationByRelationId(dslContext, connectingSameEntityType, connectingSameEntityOneToManyRelationship.getId()); assertTrue(deleteConnectingSameEntityOneToManyRelationshipResult.isPresent(), "Delete operation should return a present Optional"); @@ -738,24 +765,22 @@ public class TiesDbOperationResultsTest { @Test void testSelectByCmHandleFormSourceIds() { - Map cna1 = new HashMap<>(); - cna1.put("id", "cloud_native_id1"); - cna1.put("name", "CloudNativeApplication"); - cna1.put("CD_sourceIds", JSONB.jsonb( - "[\"urn:3gpp:dn:/fdn\"," + "\"urn:cmHandle:/395221E080CCF0FD1924103B15873814\"]")); + Map antennaModule1 = new HashMap<>(); + antennaModule1.put("id", "module_id1"); + antennaModule1.put("CD_sourceIds", JSONB.jsonb( + "[\"urn:3gpp:dn:fdn\"," + "\"urn:cmHandle:395221E080CCF0FD1924103B15873814\"]")); - Map cna2 = new HashMap<>(); - cna2.put("id", "cloud_native_id2"); - cna2.put("name", "CloudNativeApplication"); - cna2.put("CD_sourceIds", JSONB.jsonb( - "[\"urn:3gpp:dn:/fdn\"," + "\"urn:cmHandle:/395221E080CCF0FD1924103B15873815\"]")); + Map antennaModule2 = new HashMap<>(); + antennaModule2.put("id", "module_id2"); + antennaModule2.put("CD_sourceIds", JSONB.jsonb( + "[\"urn:3gpp:dn:fdn\"," + "\"urn:cmHandle:395221E080CCF0FD1924103B15873815\"]")); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cna2); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule1); + tiesDbOperations.merge(dslContext, "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", antennaModule2); List ids = tiesDbOperations.selectByCmHandleFormSourceIds(dslContext, - "ties_data.\"CloudNativeApplication\"", "395221E080CCF0FD1924103B15873814"); - assertEquals(List.of("cloud_native_id1"), ids); + "ties_data.\"f8caf5ebe876c3001d67efe06e4d83abf0babe31\"", "395221E080CCF0FD1924103B15873814"); + assertEquals(List.of("module_id1"), ids); } @Test @@ -767,7 +792,7 @@ public class TiesDbOperationResultsTest { parsedCloudEventData); assertEquals(12, mergeResult.size()); - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_2", "GNBCUUP_1", "CloudNativeApplication_3", new ArrayList<>()); final ParsedCloudEventData finalParsedCloudEventData = new ParsedCloudEventData(new ArrayList<>(), List.of( @@ -785,7 +810,7 @@ public class TiesDbOperationResultsTest { parsedCloudEventData); assertEquals(12, mergeResult.size()); - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_2", "GNBCUUP_1", "CloudNativeApplication_2", new ArrayList<>()); final ParsedCloudEventData finalParsedCloudEventData = new ParsedCloudEventData(new ArrayList<>(), List.of( @@ -805,7 +830,7 @@ public class TiesDbOperationResultsTest { parsedCloudEventData); assertEquals(12, mergeResult.size()); - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_4", "GNBCUUP_3", "CloudNativeApplication_4", new ArrayList<>()); parsedCloudEventData = new ParsedCloudEventData(new ArrayList<>(), List.of(manyToManyRelationship)); @@ -823,13 +848,14 @@ public class TiesDbOperationResultsTest { parsedCloudEventData); assertEquals(12, mergeResult.size()); - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_4", "GNBCUUP_1", "CloudNativeApplication_4", new ArrayList<>()); parsedCloudEventData = new ParsedCloudEventData(new ArrayList<>(), List.of(manyToManyRelationship)); List result = tiesDbOperations.executeEntityAndRelationshipMergeOperations(parsedCloudEventData); assertEquals(2, result.size()); + } @Test // Both endpoints exist, and a new relationship ID is received. @@ -867,9 +893,12 @@ public class TiesDbOperationResultsTest { oneToManyResult = mergeSingleTestEvent(VALIDATE_ONE_TO_MANY_DIR + "ce-create-one-to-many.json"); oneToOneResult = mergeSingleTestEvent(VALIDATE_ONE_TO_ONE_DIR + "ce-create-one-to-one.json"); - assertEquals(3, manyToOneResult.size()); - assertEquals(3, oneToManyResult.size()); - assertEquals(3, oneToOneResult.size()); + // If an entity already exists with the given id and there's no attribute to + // merge in the json, then the entity is not updated. + // If it's not updated, then it shouldn't be in the OperationResult list + assertEquals(2, manyToOneResult.size()); + assertEquals(1, oneToManyResult.size()); + assertEquals(1, oneToOneResult.size()); assertDbContainsOperationResults(manyToOneResult); assertDbContainsOperationResults(oneToManyResult); @@ -1029,25 +1058,23 @@ public class TiesDbOperationResultsTest { VALIDATE_ONE_TO_ONE_DIR + "ce-create-one-to-one8.json")); } - @Test - void testOperationResultFromRelationship() { - Relationship relationship = new Relationship("o-ran-smo-teiv-equipment", "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE", - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_relation_1", "AntennaModule_1", "AntennaModule_2", List.of()); + @Test // Missing "many" side endpoint with an existing relationship ID. + void testMergeWithMissingManySideAndExistingRelationshipIdInCaseOfGeoLocation() + throws MaximumCardinalityViolationException, InvalidFieldInYangDataException { + List manyToOneResult = mergeSingleTestEvent( + VALIDATE_MANY_TO_ONE_DIR + "ce-create-many-to-one-geolocation.json"); - Map relationshipSides = new HashMap<>(); - relationshipSides.put("aSide", relationship.getASide()); - relationshipSides.put("bSide", relationship.getBSide()); + assertEquals(3, manyToOneResult.size()); + assertDbContainsOperationResults(manyToOneResult); - OperationResult result = OperationResult.createFromRelationship(relationship); - assertEquals(result.getId(), relationship.getId()); - assertEquals(result.getEntryType(), relationship.getType()); - assertEquals(result.getContent(), relationshipSides); + assertThrows(MaximumCardinalityViolationException.class, () -> mergeSingleTestEvent( + VALIDATE_MANY_TO_ONE_DIR + "ce-create-many-to-one-geolocation2.json")); } @Test void testRelationRelatedMethodsWhenRelationshipIsStoredInSeparateTable() { - Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran", + Relationship manyToManyRelationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION", "relation_4", "GNBCUUP_1", "CloudNativeApplication_4", new ArrayList<>()); @@ -1066,15 +1093,15 @@ public class TiesDbOperationResultsTest { @Test void testRelationRelatedMethodsWhenRelationshipIsStoredOnBSide() { - Relationship relationship = new Relationship("o-ran-smo-teiv-ran", "GNBDUFUNCTION_PROVIDES_NRCELLDU", "relation_2", - "GNBDUFunction_1", "NRCellDU_5", new ArrayList<>()); + Relationship relationship = new Relationship("o-ran-smo-teiv-ran-logical", "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "relation_2", "GNBDUFunction_1", "NRCellDU_5", new ArrayList<>()); assertEquals("NRCellDU_5", relationship.getStoringSideEntityId()); assertEquals("GNBDUFunction_1", relationship.getNotStoringSideEntityId()); RelationType relationType = SchemaRegistry.getRelationTypeByName(relationship.getType()); - assertEquals("ties_data.\"GNBDUFunction\"", relationType.getNotStoringSideTableName()); + assertEquals("ties_data.\"o-ran-smo-teiv-ran-logical_GNBDUFunction\"", relationType.getNotStoringSideTableName()); assertEquals("REL_FK_provided-by-gnbduFunction", relationType .getNotStoringSideEntityIdColumnNameInStoringSideTable()); assertEquals("NRCellDU", relationType.getStoringSideEntityType()); @@ -1091,19 +1118,19 @@ public class TiesDbOperationResultsTest { private void assertDbContainsOperationResults(List results) { for (OperationResult result : results) { - boolean isRelation = result.getContent().containsKey(PROPERTY_A_SIDE) && result.getContent().containsKey( - PROPERTY_B_SIDE); - if (isRelation) { - RelationType relationType = SchemaRegistry.getRelationTypeByName(result.getEntryType()); - tableContainsId(relationType.getTableName(), relationType.getIdColumnName(), result); + if (result.isRelationship()) { + RelationType relationType = SchemaRegistry.getRelationTypeByName(result.getType()); + tableContainsId(BidiDbNameMapper.getDbName(relationType.getTableName()), relationType.getIdColumnName(), + result); } else { - tableContainsId("ties_data.\"" + result.getEntryType() + "\"", "id", result); + final EntityType entityType = SchemaRegistry.getEntityTypeByName(result.getType()); + tableContainsId(BidiDbNameMapper.getDbName(entityType.getTableName()), "id", result); } } } private void tableContainsId(String tableName, String idColumn, OperationResult result) { - Result dbResults = tiesDbService.selectAllRowsFromTable(tableName); + Result dbResults = TiesDbServiceContainerizedTest.selectAllRowsFromTable(dslContext, tableName); final boolean contains = dbResults.stream().map(row -> row.get(idColumn)).filter(Objects::nonNull).map( Object::toString).anyMatch(result.getId()::equals); assertTrue(contains); diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbServiceContainerizedTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbServiceContainerizedTest.java index 9431880..a1866b9 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbServiceContainerizedTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/service/TiesDbServiceContainerizedTest.java @@ -21,8 +21,10 @@ package org.oran.smo.teiv.service; import static org.oran.smo.teiv.ingestion.DeadlockRetryPolicy.POSTGRES_DEADLOCK_ERROR_CODE; +import static org.oran.smo.teiv.utils.TiesConstants.QUOTED_STRING; import static org.oran.smo.teiv.utils.TiesConstants.TIES_DATA_SCHEMA; import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.table; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,12 +43,14 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.oran.smo.teiv.utils.ConvertToJooqTypeUtil; import org.jooq.DSLContext; +import org.jooq.Field; import org.jooq.JSONB; import org.jooq.Record; import org.jooq.Result; +import org.jooq.Table; import org.jooq.exception.DataAccessException; +import org.jooq.util.xml.jaxb.Column; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -60,11 +64,13 @@ import org.springframework.test.context.DynamicPropertySource; import org.oran.smo.teiv.db.TestPostgresqlContainer; import org.oran.smo.teiv.exception.TiesException; import org.oran.smo.teiv.schema.SchemaRegistry; +import org.oran.smo.teiv.utils.JooqTypeConverter; +import org.oran.smo.teiv.utils.TiesConstants; import org.oran.smo.teiv.utils.schema.Geography; @Configuration @SpringBootTest -public class TiesDbServiceContainerizedTest { +class TiesDbServiceContainerizedTest { public static TestPostgresqlContainer postgreSQLContainer = TestPostgresqlContainer.getInstance(); @Autowired @@ -103,9 +109,9 @@ public class TiesDbServiceContainerizedTest { map1.put("id", "id1"); map1.put("fdn", "fdn1"); map1.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map1); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map1); - Result rows = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rows = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); for (Entry e : map1.entrySet()) { assertEquals(e.getValue(), rows.get(0).get(e.getKey())); } @@ -114,9 +120,9 @@ public class TiesDbServiceContainerizedTest { map2.put("id", "id1"); map2.put("fdn", "fdn2"); map2.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann2\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map2); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map2); - Result rows2 = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rows2 = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); for (Entry e : map2.entrySet()) { assertEquals(e.getValue(), rows2.get(0).get(e.getKey())); } @@ -129,10 +135,11 @@ public class TiesDbServiceContainerizedTest { map.put("sectorId", 7); map.put("geo-location", new Geography("{\"latitude\": 47.497913,\"longitude\": 19.040236}")); map.put("azimuth", 7.3); - tiesDbOperations.merge(dslContext, "ties_data.\"Sector\"", map); + tiesDbOperations.merge(dslContext, "ties_data.\"22174a23af5d5a96143c83ddfa78654df0acb697\"", map); Result rows = dslContext.select(field("id"), field("\"sectorId\"").as("sectorId"), field( - "ST_AsText(\"geo-location\")"), field("azimuth")).from(table("ties_data.\"Sector\"")).fetch(); + "ST_AsText(\"geo-location\")"), field("azimuth")).from(table( + "ties_data.\"22174a23af5d5a96143c83ddfa78654df0acb697\"")).fetch(); assertEquals("id1", rows.get(0).get("id")); assertEquals(7L, rows.get(0).get("sectorId")); @@ -147,20 +154,20 @@ public class TiesDbServiceContainerizedTest { map1.put("id", "id1"); map1.put("fdn", "fdn1"); map1.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map1); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map1); Map map2 = new HashMap<>(); map2.put("id", "id2"); map2.put("fdn", "fdn2"); map2.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann2\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map2); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map2); - Result row1 = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result row1 = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(2, row1.size()); tiesDbOperations.deleteEntity(dslContext, SchemaRegistry.getEntityTypeByName("ManagedElement"), "id1"); - Result row2 = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result row2 = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, row2.size()); } @@ -175,25 +182,24 @@ public class TiesDbServiceContainerizedTest { map1.put("gNBIdLength", 1); map1.put("pLMNId", JSONB.jsonb("{\"name\":\"pLMNId1\"}")); map1.put("cmId", JSONB.jsonb("{\"name\":\"cmId1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFunction\"", map1); + tiesDbOperations.merge(dslContext, "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\"", map1); Map map2 = new HashMap<>(); map2.put("id", "id1"); map2.put("name", "CloudNativeApplication"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", map2); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", map2); Map map3 = new HashMap<>(); map3.put("id", "id1"); map3.put("aSide_GNBCUCPFunction", "id1"); map3.put("bSide_CloudNativeApplication", "id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\"", map3); + tiesDbOperations.merge(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\"", map3); - Result row1 = tiesDbService.selectAllRowsFromTable("ties_data.\"GNBCUCPFunction\""); + Result row1 = selectAllRowsFromTable(dslContext, "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\""); assertEquals(1, row1.size()); - Result row2 = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeApplication\""); + Result row2 = selectAllRowsFromTable(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\""); assertEquals(1, row2.size()); - Result row3 = tiesDbService.selectAllRowsFromTable( - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\""); + Result row3 = selectAllRowsFromTable(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\""); assertEquals(1, row3.size()); dbOperations.add(dslContext -> tiesDbOperations.deleteEntity(dslContext, SchemaRegistry.getEntityTypeByName( @@ -201,12 +207,11 @@ public class TiesDbServiceContainerizedTest { assertDoesNotThrow(() -> tiesDbService.execute(dbOperations)); - Result row4 = tiesDbService.selectAllRowsFromTable("ties_data.\"GNBCUCPFunction\""); + Result row4 = selectAllRowsFromTable(dslContext, "ties_data.\"c4a425179d3089b5288fdf059079d0ea26977f0f\""); assertEquals(0, row4.size()); - Result row5 = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeApplication\""); + Result row5 = selectAllRowsFromTable(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\""); assertEquals(1, row5.size()); - Result row6 = tiesDbService.selectAllRowsFromTable( - "ties_data.\"GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\""); + Result row6 = selectAllRowsFromTable(dslContext, "ties_data.\"7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7\""); assertEquals(0, row6.size()); } @@ -218,22 +223,22 @@ public class TiesDbServiceContainerizedTest { map1.put("id", "id1"); map1.put("fdn", "fdn1"); map1.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map1); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map1); Map map2 = new HashMap<>(); map2.put("id", "id1"); map2.put("name", "CloudNativeSystem"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", map2); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", map2); Map map3 = new HashMap<>(); map3.put("id", "id1"); map3.put("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "relId"); map3.put("REL_FK_deployed-as-cloudNativeSystem", "id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", map3); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", map3); - Result row2 = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result row2 = selectAllRowsFromTable(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(1, row2.size()); - Result row1 = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result row1 = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, row1.size()); dbOperations.add(dslContext -> tiesDbOperations.deleteEntity(dslContext, SchemaRegistry.getEntityTypeByName( @@ -241,12 +246,14 @@ public class TiesDbServiceContainerizedTest { assertDoesNotThrow(() -> tiesDbService.execute(dbOperations)); - Result meRecords = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result meRecords = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals("id1", meRecords.get(0).get("id")); assertEquals("fdn1", meRecords.get(0).get("fdn")); assertNull(meRecords.get(0).get("REL_FK_deployed-as-cloudNativeSystem")); assertNull(meRecords.get(0).get("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - Result cnsRecords = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result cnsRecords = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(0, cnsRecords.size()); } @@ -256,24 +263,24 @@ public class TiesDbServiceContainerizedTest { managedElementEntity1.put("id", "managedelement_id1"); managedElementEntity1.put("fdn", "managedelement_fdn1"); managedElementEntity1.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity1); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity1); Map cloudNativeAppEntity = new HashMap<>(); cloudNativeAppEntity.put("id", "cna-1"); cloudNativeAppEntity.put("name", "CloudNativeApp1"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cloudNativeAppEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cloudNativeAppEntity); Map meToCnaRelationship = new HashMap<>(); meToCnaRelationship.put("id", "cna-1"); meToCnaRelationship.put("REL_FK_realised-managedElement", "managedelement_id1"); meToCnaRelationship.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "rel_id1"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", meToCnaRelationship); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", meToCnaRelationship); Result rowsBeforeMerge = dslContext.select(field("id"), field("name"), field( "\"REL_FK_realised-managedElement\"").as("REL_FK_realised-managedElement"), field( "\"REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION\"").as( "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")).from(table( - "ties_data.\"CloudNativeApplication\"")).fetch(); + "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"")).fetch(); assertEquals("cna-1", rowsBeforeMerge.get(0).get("id")); assertEquals("CloudNativeApp1", rowsBeforeMerge.get(0).get("name")); assertEquals("managedelement_id1", rowsBeforeMerge.get(0).get("REL_FK_realised-managedElement")); @@ -282,18 +289,19 @@ public class TiesDbServiceContainerizedTest { Map cloudNativeAppEntity2 = new HashMap<>(); cloudNativeAppEntity2.put("id", "cna-2"); cloudNativeAppEntity2.put("name", "CloudNativeApp2"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", cloudNativeAppEntity2); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", cloudNativeAppEntity2); Map modifiedMeToCnaRelationship = new HashMap<>(); modifiedMeToCnaRelationship.put("id", "cna-2"); modifiedMeToCnaRelationship.put("REL_FK_realised-managedElement", "managedelement_id1"); modifiedMeToCnaRelationship.put("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "rel_id2"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeApplication\"", modifiedMeToCnaRelationship); + tiesDbOperations.merge(dslContext, "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"", + modifiedMeToCnaRelationship); Result rowsAfterMerge = dslContext.select(field("id"), field("name"), field("\"REL_FK_realised-managedElement\"") .as("REL_FK_realised-managedElement"), field("\"REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION\"") .as("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION")).from(table( - "ties_data.\"CloudNativeApplication\"")).fetch(); + "ties_data.\"e01fcb87ad2c34ce66c34420255e25aaca270e5e\"")).fetch(); assertEquals("cna-1", rowsAfterMerge.get(0).get("id")); assertEquals("CloudNativeApp1", rowsAfterMerge.get(0).get("name")); @@ -311,30 +319,31 @@ public class TiesDbServiceContainerizedTest { managedElementEntity.put("id", "me-id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity); Map enodeBFunctionEntity = new HashMap<>(); enodeBFunctionEntity.put("id", "enodeb-id1"); enodeBFunctionEntity.put("eNBId", 1L); - tiesDbOperations.merge(dslContext, "ties_data.\"ENodeBFunction\"", enodeBFunctionEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-logical_ENodeBFunction\"", enodeBFunctionEntity); Map meToEnodeBFuncRelation = new HashMap<>(); meToEnodeBFuncRelation.put("id", "enodeb-id1"); meToEnodeBFuncRelation.put("REL_FK_managed-by-managedElement", "me-id1"); meToEnodeBFuncRelation.put("REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "eiid1"); - meToEnodeBFuncRelation.put("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", ConvertToJooqTypeUtil.toJsonb( - List.of("fdn1", "cmHandleId1"))); - tiesDbOperations.merge(dslContext, "ties_data.\"ENodeBFunction\"", meToEnodeBFuncRelation); + meToEnodeBFuncRelation.put("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", JooqTypeConverter.toJsonb(List + .of("fdn1", "cmHandleId1"))); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-logical_ENodeBFunction\"", + meToEnodeBFuncRelation); tiesDbOperations.deleteRelationFromEntityTableByRelationId(dslContext, "eiid1", SchemaRegistry .getRelationTypeByName("MANAGEDELEMENT_MANAGES_ENODEBFUNCTION")); - Result rows = tiesDbService.selectAllRowsFromTable("ties_data.\"ENodeBFunction\""); + Result rows = selectAllRowsFromTable(dslContext, "ties_data.\"o-ran-smo-teiv-ran-logical_ENodeBFunction\""); assertEquals("enodeb-id1", rows.get(0).get("id")); assertEquals(1L, rows.get(0).get("eNBId")); //assertNull(rows.get(0).get("REL_FK_managed-by-managedElement")); assertNull(rows.get(0).get("REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of()), rows.get(0).get( + assertEquals(JooqTypeConverter.toJsonb(List.of()), rows.get(0).get( "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION")); } @@ -344,36 +353,38 @@ public class TiesDbServiceContainerizedTest { Map cloudNativeSystemEntity = new HashMap<>(); cloudNativeSystemEntity.put("id", "cloudnative_id1"); cloudNativeSystemEntity.put("name", "CloudNativeSystem"); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"CloudNativeSystem\"", - cloudNativeSystemEntity)); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", cloudNativeSystemEntity)); Map managedElementEntity = new HashMap<>(); managedElementEntity.put("id", "managed_element_id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"ManagedElement\"", - managedElementEntity)); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity)); Map meTocnsRelationship = new HashMap<>(); meTocnsRelationship.put("id", "managed_element_id1"); meTocnsRelationship.put("REL_FK_deployed-as-cloudNativeSystem", "cloudnative_id1"); meTocnsRelationship.put("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "eiid1"); - meTocnsRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", ConvertToJooqTypeUtil - .toJsonb(List.of("fdn1", "cmHandleId1"))); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"ManagedElement\"", - meTocnsRelationship)); + meTocnsRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", JooqTypeConverter.toJsonb( + List.of("fdn1", "cmHandleId1"))); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", meTocnsRelationship)); assertDoesNotThrow(() -> tiesDbService.execute(dbOperations)); - Result rowsFromManagedElementTable = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rowsFromManagedElementTable = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, rowsFromManagedElementTable.size()); assertEquals("cloudnative_id1", rowsFromManagedElementTable.get(0).get("REL_FK_deployed-as-cloudNativeSystem")); assertEquals("eiid1", rowsFromManagedElementTable.get(0).get( "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementTable.get(0).get( + assertEquals(JooqTypeConverter.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementTable.get(0).get( "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - Result rowsFromCloudNativeSystem = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystem = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(1, rowsFromCloudNativeSystem.size()); } @@ -384,15 +395,15 @@ public class TiesDbServiceContainerizedTest { managedElementEntity.put("id", "managed_element_id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"ManagedElement\"", - managedElementEntity)); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity)); Map cloudNativeSystemEntity = new HashMap<>(); cloudNativeSystemEntity.put("id", "cloudnative_id1"); cloudNativeSystemEntity.put("name", "CloudNativeSystem"); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"CloudNativeSystem\"", - cloudNativeSystemEntity)); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", cloudNativeSystemEntity)); // Create a faulty relationship map to trigger the rollback Map faultyCloudNativeSystemRelationship = new HashMap<>(); @@ -400,15 +411,17 @@ public class TiesDbServiceContainerizedTest { faultyCloudNativeSystemRelationship.put("REL_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_BAAAD", "managed_element_id1"); faultyCloudNativeSystemRelationship.put("REL_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_EIID", "eiid1"); - dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, "ties_data.\"CloudNativeSystem\"", - faultyCloudNativeSystemRelationship)); + dbOperations.add(wrDSLContext -> tiesDbOperations.merge(wrDSLContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", faultyCloudNativeSystemRelationship)); assertThrows(TiesException.class, () -> tiesDbService.execute(dbOperations)); - Result rowsFromManagedElementTable = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rowsFromManagedElementTable = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(0, rowsFromManagedElementTable.size()); - Result rowsFromCloudNativeSystem = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystem = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(0, rowsFromCloudNativeSystem.size()); } @@ -418,35 +431,36 @@ public class TiesDbServiceContainerizedTest { Map cloudNativeSystemEntity = new HashMap<>(); cloudNativeSystemEntity.put("id", "cloudnative_id1"); cloudNativeSystemEntity.put("name", "CloudNativeSystem"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity); Map managedElementEntity = new HashMap<>(); managedElementEntity.put("id", "managed_element_id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity); Map meToCnsRelationship = new HashMap<>(); meToCnsRelationship.put("id", "managed_element_id1"); meToCnsRelationship.put("REL_FK_deployed-as-cloudNativeSystem", "cloudnative_id1"); meToCnsRelationship.put("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "eiid1"); - meToCnsRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", ConvertToJooqTypeUtil - .toJsonb(List.of("fdn1", "cmHandleId1"))); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", meToCnsRelationship); + meToCnsRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", JooqTypeConverter.toJsonb( + List.of("fdn1", "cmHandleId1"))); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", meToCnsRelationship); - Result rowsFromCloudNativeSystemBeforeDelete = tiesDbService.selectAllRowsFromTable( - "ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystemBeforeDelete = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(1, rowsFromCloudNativeSystemBeforeDelete.size()); - Result rowsFromManagedElementBeforeDelete = tiesDbService.selectAllRowsFromTable( - "ties_data.\"ManagedElement\""); + Result rowsFromManagedElementBeforeDelete = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, rowsFromManagedElementBeforeDelete.size()); assertEquals("cloudnative_id1", rowsFromManagedElementBeforeDelete.get(0).get( "REL_FK_deployed-as-cloudNativeSystem")); assertEquals("eiid1", rowsFromManagedElementBeforeDelete.get(0).get( "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementBeforeDelete.get( - 0).get("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); + assertEquals(JooqTypeConverter.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementBeforeDelete.get(0) + .get("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); dbOperations.add(wrDSLContext -> tiesDbOperations.deleteEntity(wrDSLContext, SchemaRegistry.getEntityTypeByName( "ManagedElement"), "managed_element_id1")); @@ -462,10 +476,12 @@ public class TiesDbServiceContainerizedTest { assertDoesNotThrow(() -> tiesDbService.execute(dbOperations)); - Result rowsFromManagedElementTable = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rowsFromManagedElementTable = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(0, rowsFromManagedElementTable.size()); - Result rowsFromCloudNativeSystem = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystem = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(0, rowsFromCloudNativeSystem.size()); } @@ -475,35 +491,37 @@ public class TiesDbServiceContainerizedTest { Map cloudNativeSystemEntity = new HashMap<>(); cloudNativeSystemEntity.put("id", "cloudnative_id1"); cloudNativeSystemEntity.put("name", "CloudNativeSystem"); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity); Map managedElementEntity = new HashMap<>(); managedElementEntity.put("id", "managed_element_id1"); managedElementEntity.put("fdn", "fdn1"); managedElementEntity.put("cmId", JSONB.jsonb("{\"name\":\"Hellmann1\"}")); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", managedElementEntity); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", managedElementEntity); Map cloudNativeSystemRelationship = new HashMap<>(); cloudNativeSystemRelationship.put("id", "managed_element_id1"); cloudNativeSystemRelationship.put("REL_FK_deployed-as-cloudNativeSystem", "cloudnative_id1"); cloudNativeSystemRelationship.put("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", "eiid1"); - cloudNativeSystemRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", - ConvertToJooqTypeUtil.toJsonb(List.of("fdn1", "cmHandleId1"))); - tiesDbOperations.merge(dslContext, "ties_data.\"ManagedElement\"", cloudNativeSystemRelationship); + cloudNativeSystemRelationship.put("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM", JooqTypeConverter + .toJsonb(List.of("fdn1", "cmHandleId1"))); + tiesDbOperations.merge(dslContext, "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\"", + cloudNativeSystemRelationship); - Result rowsFromCloudNativeSystemBeforeDelete = tiesDbService.selectAllRowsFromTable( - "ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystemBeforeDelete = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(1, rowsFromCloudNativeSystemBeforeDelete.size()); - Result rowsFromManagedElementBeforeDelete = tiesDbService.selectAllRowsFromTable( - "ties_data.\"ManagedElement\""); + Result rowsFromManagedElementBeforeDelete = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, rowsFromManagedElementBeforeDelete.size()); assertEquals("cloudnative_id1", rowsFromManagedElementBeforeDelete.get(0).get( "REL_FK_deployed-as-cloudNativeSystem")); assertEquals("eiid1", rowsFromManagedElementBeforeDelete.get(0).get( "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementBeforeDelete.get( - 0).get("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); + assertEquals(JooqTypeConverter.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementBeforeDelete.get(0) + .get("REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); dbOperations.add(wrDSLContext -> tiesDbOperations.deleteEntity(wrDSLContext, SchemaRegistry.getEntityTypeByName( "ManagedElement"), "managed_element_id1")); @@ -516,14 +534,16 @@ public class TiesDbServiceContainerizedTest { assertThrows(TiesException.class, () -> tiesDbService.execute(dbOperations)); - Result rowsFromCloudNativeSystem = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystem = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(1, rowsFromCloudNativeSystem.size()); - Result rowsFromManagedElementTable = tiesDbService.selectAllRowsFromTable("ties_data.\"ManagedElement\""); + Result rowsFromManagedElementTable = selectAllRowsFromTable(dslContext, + "ties_data.\"o-ran-smo-teiv-ran-oam_ManagedElement\""); assertEquals(1, rowsFromManagedElementTable.size()); assertEquals("cloudnative_id1", rowsFromManagedElementTable.get(0).get("REL_FK_deployed-as-cloudNativeSystem")); assertEquals("eiid1", rowsFromManagedElementTable.get(0).get( "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); - assertEquals(ConvertToJooqTypeUtil.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementTable.get(0).get( + assertEquals(JooqTypeConverter.toJsonb(List.of("fdn1", "cmHandleId1")), rowsFromManagedElementTable.get(0).get( "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM")); } @@ -551,12 +571,15 @@ public class TiesDbServiceContainerizedTest { final CountDownLatch firstTransactionCompletedMergeEntity1 = new CountDownLatch(1); final CountDownLatch secondTransactionCompletedMergeEntity2 = new CountDownLatch(1); dbOperations1.add(dslContext -> { - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity1); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity1); firstTransactionCompletedMergeEntity1.countDown(); try { secondTransactionCompletedMergeEntity2.await(); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity2); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity3); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity2); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity3); } catch (InterruptedException e) { throw new RuntimeException(e); } @@ -564,11 +587,14 @@ public class TiesDbServiceContainerizedTest { //Try to add the same rows in another transaction in another order. dbOperations2.add(dslContext -> { try { - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity2); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity2); secondTransactionCompletedMergeEntity2.countDown(); firstTransactionCompletedMergeEntity1.await(); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity1); - tiesDbOperations.merge(dslContext, "ties_data.\"CloudNativeSystem\"", cloudNativeSystemEntity4); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity1); + tiesDbOperations.merge(dslContext, "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\"", + cloudNativeSystemEntity4); } catch (InterruptedException e) { throw new RuntimeException(e); } @@ -580,7 +606,8 @@ public class TiesDbServiceContainerizedTest { t2.start(); t1.join(); t2.join(); - Result rowsFromCloudNativeSystem = tiesDbService.selectAllRowsFromTable("ties_data.\"CloudNativeSystem\""); + Result rowsFromCloudNativeSystem = selectAllRowsFromTable(dslContext, + "ties_data.\"163276fa439cdfccabb80f7acacb6fa638e8d314\""); assertEquals(4, rowsFromCloudNativeSystem.size()); } @@ -596,4 +623,31 @@ public class TiesDbServiceContainerizedTest { assertThrows(TiesException.class, () -> tiesDbService.execute(dbOperations)); assertEquals(maxRetryAttemptsForDeadlock, attempts.get()); } + + /** + * The out of the box binding for geography is available in the commercial jOOQ distribution only. Because of this, + * a select * from tableName; query fails if the table has a column with geography type. Even if the value in that + * column is null. + * + * @param readDataDslContext + * @param tableName + * For example: ties_data."AntennaModule" + * @return the fetched rows. Values of geography type are represented as String values. + */ + public static Result selectAllRowsFromTable(DSLContext readDataDslContext, final String tableName) { + String unqualifiedName = tableName.split("\\.")[1].split("\"")[1]; + Table table = readDataDslContext.meta().getTables().stream().filter(t -> t.getName().equals(unqualifiedName)) + .toList().get(0); + List columns = readDataDslContext.meta(table).informationSchema().getColumns(); + List> columnsToSelect = columns.stream().map(c -> { + if ("geography".equals(c.getDataType())) { + return field(String.format(TiesConstants.ST_TO_STRING, String.format(QUOTED_STRING, c.getColumnName()))); + } else if ("jsonb".equals(c.getDataType())) { + return field(name(c.getColumnName()), JSONB.class); + } else { + return field(name(c.getColumnName())); + } + }).toList(); + return readDataDslContext.select(columnsToSelect).from(table(tableName)).fetch(); + } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/CloudEventParserTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/CloudEventParserTest.java index 9623be0..73c0053 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/CloudEventParserTest.java +++ b/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/CloudEventParserTest.java @@ -20,13 +20,20 @@ */ package org.oran.smo.teiv.service.cloudevent; +import java.io.IOException; import java.util.List; import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.oran.smo.teiv.exception.YangModelException; +import org.oran.smo.teiv.schema.MockSchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoader; +import org.oran.smo.teiv.schema.SchemaLoaderException; import org.oran.smo.teiv.startup.SchemaHandler; import io.cloudevents.CloudEvent; import org.junit.jupiter.api.Assertions; +import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -40,7 +47,6 @@ import org.oran.smo.teiv.service.cloudevent.data.Relationship; import org.oran.smo.teiv.utils.CloudEventTestUtil; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.annotation.DirtiesContext; @SpringBootTest class CloudEventParserTest { @@ -51,8 +57,13 @@ class CloudEventParserTest { @MockBean private SchemaHandler schemaHandler; + @BeforeEach + public void setup() throws SchemaLoaderException, YangModelException, IOException { + SchemaLoader mockSchemaLoader = new MockSchemaLoader(); + mockSchemaLoader.loadSchemaRegistry(); + } + @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) void testParseCloudEventData() { final CloudEvent cloudEvent = cloudEventFromJson("src/test/resources/cloudeventdata/common/ce-with-data.json"); final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); @@ -75,26 +86,63 @@ class CloudEventParserTest { Relationship relationship = parsedCloudEventData.getRelationships().get(0); assertEquals("o-ran-smo-teiv-ran", relationship.getModule()); assertEquals("NRCELLDU_USES_NRSECTORCARRIER", relationship.getType()); - assertEquals("entityId_1", relationship.getASide()); + assertEquals("relationshipId", relationship.getId()); + assertEquals( + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR004,ManagedElement=me04,GNBDUFunction=gnbdu04,NRCellDU=NR-Cell-07", + relationship.getASide()); assertEquals("entityId_2", relationship.getBSide()); + assertEquals(null, relationship.getSourceIds()); relationship = parsedCloudEventData.getRelationships().get(1); assertEquals("o-ran-smo-teiv-ran", relationship.getModule()); assertEquals("NRCELLDU_USES_NRSECTORCARRIER", relationship.getType()); + assertEquals("relationshipId2", relationship.getId()); assertEquals("entityId_3", relationship.getASide()); assertEquals("entityId_4", relationship.getBSide()); + assertEquals(List.of("source10", "source20"), relationship.getSourceIds()); relationship = parsedCloudEventData.getRelationships().get(2); assertEquals("o-ran-smo-teiv-ran", relationship.getModule()); - assertEquals("GNBDUFunctionRealisedByCloudNativeApplication", relationship.getType()); + assertEquals("GNBDUFUNCTION_PROVIDES_NRCELLDU", relationship.getType()); + assertEquals( + "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=89FE9A4ED8451D779865C389900E247B13E360B0A4175EBA80AA9B384BFA4C688F17865AFD934085B0235BCA66128F2E6D4CE6953EAAB2EDEBD94B3683C1A064", + relationship.getId()); assertEquals("entityId_5", relationship.getASide()); - assertEquals("entityId_6", relationship.getBSide()); + assertEquals( + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR004,ManagedElement=me04,GNBDUFunction=gnbdu04,NRCellDU=NR-Cell-07", + relationship.getBSide()); relationship = parsedCloudEventData.getRelationships().get(3); assertEquals("o-ran-smo-teiv-ran", relationship.getModule()); - assertEquals("GNBDUFunctionRealisedByCloudNativeApplication", relationship.getType()); + assertEquals("GNBDUFUNCTION_PROVIDES_NRCELLDU", relationship.getType()); + assertEquals("relationshipId4", relationship.getId()); assertEquals("entityId_5", relationship.getASide()); - assertEquals("entityId_7", relationship.getBSide()); + assertEquals("entityId_3", relationship.getBSide()); + assertEquals(List.of("source21"), relationship.getSourceIds()); + } + + @Test + void testParseCloudEventDataWithArray() { + final CloudEvent cloudEvent = cloudEventFromJson("src/test/resources/cloudeventdata/common/ce-arrays.json"); + final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + // Parse an array of 3 elements + validateEntity(parsedCloudEventData.getEntities().get(0), "o-ran-smo-teiv-ran", "AntennaCapability", "entityId_0", + Map.of("eUtranFqBands", "[a, b, c]"), null); + + // Parse an array of 2 elements + validateEntity(parsedCloudEventData.getEntities().get(1), "o-ran-smo-teiv-ran", "AntennaCapability", "entityId_1", + Map.of("eUtranFqBands", "[a, b]"), null); + + // Parse an array of 1 element + validateEntity(parsedCloudEventData.getEntities().get(2), "o-ran-smo-teiv-ran", "AntennaCapability", "entityId_2", + Map.of("geranFqBands", "a"), null); + + // Parse an empty array + validateEntity(parsedCloudEventData.getEntities().get(3), "o-ran-smo-teiv-ran", "AntennaCapability", "entityId_3", + Map.of("eUtranFqBands", "q"), null); + + Assertions.assertEquals(0, parsedCloudEventData.getRelationships().size()); } @Test @@ -109,8 +157,8 @@ class CloudEventParserTest { void testNoRelationshipInCloudEvent() { final CloudEvent cloudEvent = cloudEventFromJson("src/test/resources/cloudeventdata/common/ce-one-entity.json"); final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); - validateEntity(parsedCloudEventData.getEntities().get(0), "o-ran-smo-teiv-ran", "NRCellDU", "entityId_1", 3, Map.of( - "cellLocalId", 4589L, "nRPCI", 12L, "nRTAC", 310L)); + validateEntity(parsedCloudEventData.getEntities().get(0), "o-ran-smo-teiv-ran", "NRCellDU", "entityId_1", Map.of( + "cellLocalId", 4589L, "nRPCI", 12L, "nRTAC", 310L), null); Assertions.assertTrue(parsedCloudEventData.getRelationships().isEmpty()); } @@ -118,7 +166,7 @@ class CloudEventParserTest { void testCloudEventDataIsNotAValidJson() { final CloudEvent cloudEvent = CloudEventTestUtil.getCloudEvent("create", "{invalidjson"); final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); } @Test @@ -133,41 +181,142 @@ class CloudEventParserTest { final CloudEvent arrayEntitiesCloudEvent = CloudEventTestUtil.getCloudEvent("create", "{\"entities\":[{\"some_entity_field\": 54321}]}"); ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(arrayEntitiesCloudEvent); - Assertions.assertNull(parsedCloudEventData); - - final CloudEvent objectEntitiesCloudEvent = CloudEventTestUtil.getCloudEvent("create", - "{\"entities\":{\"some_entity_field\": 54321}}"); - parsedCloudEventData = cloudEventParser.getCloudEventData(objectEntitiesCloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); final CloudEvent arrayRelationshipsCloudEvent = CloudEventTestUtil.getCloudEvent("create", "{\"relationships\":[{\"some_relationship_field\": 54321}]}"); parsedCloudEventData = cloudEventParser.getCloudEventData(arrayRelationshipsCloudEvent); - Assertions.assertNull(parsedCloudEventData); - - final CloudEvent objectRelationshipsCloudEvent = CloudEventTestUtil.getCloudEvent("create", - "{\"relationships\":{\"some_relationship_field\": 54321}}"); - parsedCloudEventData = cloudEventParser.getCloudEventData(objectRelationshipsCloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); } @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) void testRelationshipsIsNotAValidYangData() { - CloudEvent cloudEvent = CloudEventTestUtil.getCloudEvent("create", "{\"relationships\":{\"a_field\": 123}}"); + CloudEvent cloudEvent = CloudEventTestUtil.getCloudEvent("create", "{\"relationships\":[{\"a_field\": 123}]}"); ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); - cloudEvent = CloudEventTestUtil.getCloudEvent("merge", "{\"relationships\":{\"a_field\": 123}}"); + cloudEvent = CloudEventTestUtil.getCloudEvent("merge", "{\"relationships\":[{\"a_field\": 123}]}"); parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); - cloudEvent = CloudEventTestUtil.getCloudEvent("delete", "{\"relationships\":{\"a_field\": 123}}"); + cloudEvent = CloudEventTestUtil.getCloudEvent("delete", "{\"relationships\":[{\"a_field\": 123}]}"); parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); - Assertions.assertNull(parsedCloudEventData); + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipMissingASide() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-missing-a-side.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipMissingBSide() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-missing-b-side.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipMissingBothSides() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-missing-both-sides.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipMissingId() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-missing-id.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipInvalidType() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-invalid-type.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipInvalidModule() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-invalid-module.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testRelationshipInvalidModuleTypePair() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-relationship-invalid-module-type-pair.json"); + + ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testParseCloudEventDataWithInvalidRelationshipId() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids.json"); + final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testParseCloudEventDataWithInvalidRelationshipASideId() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids2.json"); + final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + @Test + void testParseCloudEventDataWithInvalidRelationshipBSideId() { + final CloudEvent cloudEvent = cloudEventFromJson( + "src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids3.json"); + final ParsedCloudEventData parsedCloudEventData = cloudEventParser.getCloudEventData(cloudEvent); + + assertNull(parsedCloudEventData); + } + + private void validateEntity(final Entity entity, String expectedModuleReference, String expectedEntityName, + String expectedId, Map expectedAttributes, List expectedSourceIds) { + assertEquals(expectedModuleReference, entity.getModule()); + assertEquals(expectedEntityName, entity.getType()); + assertEquals(expectedId, entity.getId()); + final Map attributes = entity.getAttributes(); + assertEquals(expectedAttributes.size(), attributes.size()); + for (Map.Entry entry : expectedAttributes.entrySet()) { + assertTrue(attributes.containsKey(entry.getKey())); + assertEquals(entry.getValue().getClass(), attributes.get(entry.getKey()).getClass()); + assertEquals(entry.getValue(), attributes.get(entry.getKey())); + } + assertEquals(expectedSourceIds, entity.getSourceIds()); } private void validateEntity(final Entity entity, String expectedModuleReference, String expectedEntityName, diff --git a/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventDataTest.java b/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventDataTest.java new file mode 100644 index 0000000..a8e46a2 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/service/cloudevent/data/ParsedCloudEventDataTest.java @@ -0,0 +1,105 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.service.cloudevent.data; + +import static org.oran.smo.teiv.schema.RelationshipDataLocation.A_SIDE; +import static org.oran.smo.teiv.schema.RelationshipDataLocation.B_SIDE; +import static org.oran.smo.teiv.schema.RelationshipDataLocation.RELATION; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import org.oran.smo.teiv.schema.RelationType; +import org.oran.smo.teiv.schema.SchemaRegistry; + +public class ParsedCloudEventDataTest { + + @Test + void testSortForEntities() { + Entity e1 = new Entity("m", "type3", "id1", Map.of(), List.of()); + Entity e2 = new Entity("a", "type2", "id2", Map.of(), List.of()); + Entity e3 = new Entity("m", "type2", "id1", Map.of(), List.of()); + Entity e4 = new Entity("m", "type5", "id1", null, null); + Entity e5 = new Entity("m", "type1", "id9999", Map.of(), List.of()); + List entities = List.of(e1, e2, e3, e4, e5); + ParsedCloudEventData data = new ParsedCloudEventData(entities, null); + data.sort(); + assertEquals(e5, data.getEntities().get(0)); + assertEquals(e3, data.getEntities().get(1)); + assertEquals(e2, data.getEntities().get(2)); + assertEquals(e1, data.getEntities().get(3)); + assertEquals(e4, data.getEntities().get(4)); + } + + @Test + void testSortForRelationships() { + Relationship r1 = new Relationship("a", "type3", "id1", "a", "b", null); + Relationship r2 = new Relationship("m", "type2", "id2", "y", "a", null); + Relationship r3 = new Relationship("m", "type2", "id3", "a", "c", null); + Relationship r4 = new Relationship("m", "type2", "id4", "z", "b", null); + Relationship r5 = new Relationship("m", "type5", "id5", "a", "b", null); + Relationship r6 = new Relationship("m", "type1", "id9999", "a", "b", null); + List relationships = List.of(r1, r2, r3, r4, r5, r6); + ParsedCloudEventData data = new ParsedCloudEventData(null, relationships); + + try (MockedStatic staticMock = Mockito.mockStatic(SchemaRegistry.class)) { + staticMock.when(() -> SchemaRegistry.getRelationTypeByName("type2")).thenReturn(RelationType.builder() + .relationshipStorageLocation(A_SIDE).build()); + data.sort(); + assertEquals(r6, data.getRelationships().get(0)); + assertEquals(r3, data.getRelationships().get(1)); + assertEquals(r2, data.getRelationships().get(2)); + assertEquals(r4, data.getRelationships().get(3)); + assertEquals(r1, data.getRelationships().get(4)); + assertEquals(r5, data.getRelationships().get(5)); + } + + try (MockedStatic staticMock = Mockito.mockStatic(SchemaRegistry.class)) { + staticMock.when(() -> SchemaRegistry.getRelationTypeByName("type2")).thenReturn(RelationType.builder() + .relationshipStorageLocation(B_SIDE).build()); + data.sort(); + assertEquals(r6, data.getRelationships().get(0)); + assertEquals(r2, data.getRelationships().get(1)); + assertEquals(r4, data.getRelationships().get(2)); + assertEquals(r3, data.getRelationships().get(3)); + assertEquals(r1, data.getRelationships().get(4)); + assertEquals(r5, data.getRelationships().get(5)); + } + + try (MockedStatic staticMock = Mockito.mockStatic(SchemaRegistry.class)) { + staticMock.when(() -> SchemaRegistry.getRelationTypeByName("type2")).thenReturn(RelationType.builder() + .relationshipStorageLocation(RELATION).build()); + data.sort(); + assertEquals(r6, data.getRelationships().get(0)); + assertEquals(r2, data.getRelationships().get(1)); + assertEquals(r3, data.getRelationships().get(2)); + assertEquals(r4, data.getRelationships().get(3)); + assertEquals(r1, data.getRelationships().get(4)); + assertEquals(r5, data.getRelationships().get(5)); + } + } + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/ConvertToJooqTypeUtilTest.java b/teiv/src/test/java/org/oran/smo/teiv/utils/ConvertToJooqTypeUtilTest.java deleted file mode 100644 index d4d28fd..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/utils/ConvertToJooqTypeUtilTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.jooq.JSONB; -import org.junit.Test; - -import org.oran.smo.teiv.exception.InvalidFieldInYangDataException; -import org.oran.smo.teiv.utils.schema.Geography; - -import static org.oran.smo.teiv.utils.ConvertToJooqTypeUtil.*; - -public class ConvertToJooqTypeUtilTest { - - @Test - public void testToJsonb() { - assertEquals(JSONB.jsonb("{}"), toJsonb("{}")); - assertEquals(JSONB.jsonb("{\"key\":\"value\"}"), toJsonb("{\"key\":\"value\"}")); - assertEquals(JSONB.jsonb("[]"), toJsonb("[]")); - assertEquals(JSONB.jsonb("[1]"), toJsonb("[1]")); - assertEquals(JSONB.jsonb("[1,2,3]"), toJsonb("[1,2,3]")); - assertEquals(JSONB.jsonb("[\"value1\",\"value2\"]"), toJsonb("[\"value1\",\"value2\"]")); - assertEquals(JSONB.jsonb("[\"leading\",\"whitespaces\"]"), toJsonb(" [\"leading\",\"whitespaces\"]")); - assertEquals(JSONB.jsonb("[\"a_string\"]"), toJsonb("a_string")); - assertEquals(JSONB.jsonb("[\"23\"]"), toJsonb("23")); - assertEquals(JSONB.jsonb("[54]"), toJsonb(54L)); - assertEquals(JSONB.jsonb("[92.13]"), toJsonb(92.13)); - } - - @Test - public void testToGeography() throws InvalidFieldInYangDataException { - assertEquals(new Geography(47.497913, 19.040236), toGeography( - "{\"latitude\": 47.497913,\"longitude\": 19.040236}")); - assertThrows(InvalidFieldInYangDataException.class, () -> toGeography("{invalidjson")); - assertThrows(InvalidFieldInYangDataException.class, () -> toGeography(9)); - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/EndToEndExpectedResults.java b/teiv/src/test/java/org/oran/smo/teiv/utils/EndToEndExpectedResults.java index f8c1665..df2b5a7 100644 --- a/teiv/src/test/java/org/oran/smo/teiv/utils/EndToEndExpectedResults.java +++ b/teiv/src/test/java/org/oran/smo/teiv/utils/EndToEndExpectedResults.java @@ -23,43 +23,75 @@ package org.oran.smo.teiv.utils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.jooq.JSONB; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Getter; + public class EndToEndExpectedResults { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final JsonNode rootNode; + @Getter + public ArrayList tables; + public EndToEndExpectedResults(final String jsonPath) throws IOException { rootNode = OBJECT_MAPPER.readTree(Files.readString(Paths.get(jsonPath))); + tables = new ArrayList<>(); + rootNode.fields().forEachRemaining(entry -> tables.add(entry.getKey())); } public Map get(final String entryId) { - Map expectedValuesMap = new HashMap<>(); JsonNode attributesNode = rootNode.required(entryId); - attributesNode.fields().forEachRemaining(entry -> { - String key = entry.getKey(); - JsonNode valueNode = entry.getValue(); - if (valueNode.isContainerNode()) { - expectedValuesMap.put(key, JSONB.jsonb(valueNode.toString())); - } else if (valueNode.isTextual()) { - expectedValuesMap.put(key, valueNode.asText()); - } else if (valueNode.isDouble()) { - expectedValuesMap.put(key, valueNode.asDouble()); - } else if (valueNode.isNumber()) { - expectedValuesMap.put(key, valueNode.asLong()); - } else if (valueNode.isBoolean()) { - expectedValuesMap.put(key, valueNode.asBoolean()); + return processData(attributesNode); + } + + public Map processData(JsonNode node) { + Map tableData = new HashMap<>(); + node.fields().forEachRemaining(entry -> tableData.put(entry.getKey(), processNode(entry.getValue()))); + return tableData; + } + + private Object processNode(JsonNode valueNode) { + if (valueNode.isContainerNode()) { + return JSONB.jsonb(valueNode.toString()); + } else if (valueNode.isTextual()) { + return valueNode.asText(); + } else if (valueNode.isDouble()) { + return valueNode.asDouble(); + } else if (valueNode.isNumber()) { + return valueNode.asLong(); + } else if (valueNode.isBoolean()) { + return valueNode.asBoolean(); + } + return null; + } + + public List> getTableData(String tableName) { + List> tableData = new ArrayList<>(); + JsonNode tableArrayNode = rootNode.get(tableName); + if (tableArrayNode != null && tableArrayNode.isArray()) { + for (JsonNode contentNode : tableArrayNode) { + tableData.add(processData(contentNode)); } - }); - return expectedValuesMap; + } + return tableData; } - public Map getAll() { - return EndToEndTestUtil.processNode(rootNode); + public List getTableEntryIds(String tableName) { + List entryIds = new ArrayList<>(); + JsonNode tableArrayNode = rootNode.get(tableName); + if (tableArrayNode != null && tableArrayNode.isArray()) { + for (JsonNode elementNode : tableArrayNode) { + entryIds.add(elementNode.textValue()); + } + } + return entryIds; } } diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/TiesTestConstants.java b/teiv/src/test/java/org/oran/smo/teiv/utils/TiesTestConstants.java new file mode 100644 index 0000000..7079bf5 --- /dev/null +++ b/teiv/src/test/java/org/oran/smo/teiv/utils/TiesTestConstants.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.oran.smo.teiv.utils; + +public class TiesTestConstants { + + public static final String APPLICATION_JSON = "application/json"; + +} diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/exposure/PaginationVerifierTestUtil.java b/teiv/src/test/java/org/oran/smo/teiv/utils/exposure/PaginationVerifierTestUtil.java deleted file mode 100644 index d8d8f55..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/utils/exposure/PaginationVerifierTestUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils.exposure; - -import org.oran.smo.teiv.exposure.spi.mapper.PageMetaData; - -import org.junit.jupiter.api.Assertions; -import org.springframework.http.ResponseEntity; - -import java.util.Arrays; -import java.util.Map; - -public class PaginationVerifierTestUtil { - - public static void verifyResponse(Map expected, Map actual) { - String[] paginationKeys = { "next", "prev", "first", "last", "self" }; - for (String key : expected.keySet()) { - if (Arrays.stream(paginationKeys).anyMatch(paginationKey -> paginationKey.equals(key))) { - Assertions.assertEquals(((PageMetaData) expected.get(key)).getHref(), ((PageMetaData) actual.get(key)) - .getHref()); - } else { - Assertions.assertEquals(expected.get(key), actual.get(key)); - } - } - } - - public static void verifyResponse(ResponseEntity expected, ResponseEntity actual) { - Map expectedBody = (Map) expected.getBody(); - Map actualBody = (Map) actual.getBody(); - String[] paginationKeys = { "next", "prev", "first", "last", "self" }; - for (String key : expectedBody.keySet()) { - if (Arrays.stream(paginationKeys).anyMatch(paginationKey -> paginationKey.equals(key))) { - Assertions.assertEquals(((PageMetaData) expectedBody.get(key)).getHref(), ((PageMetaData) actualBody.get( - key)).getHref()); - } else { - Assertions.assertEquals(expectedBody.get(key), actualBody.get(key)); - } - } - } -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTest.java b/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTest.java deleted file mode 100644 index ccb870e..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTest.java +++ /dev/null @@ -1,1616 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils.query; - -import org.oran.smo.teiv.exposure.utils.PaginationDTO; -import org.oran.smo.teiv.schema.SchemaLoaderException; -import org.oran.smo.teiv.schema.MockSchemaLoader; -import org.oran.smo.teiv.utils.query.exception.TiesPathException; - -import org.jooq.Condition; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.Query; -import org.jooq.Select; -import org.jooq.impl.DSL; -import org.jooq.tools.jdbc.MockConnection; -import org.jooq.tools.jdbc.MockResult; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.util.List; - -import static org.oran.smo.teiv.schema.SchemaRegistry.*; -import static org.oran.smo.teiv.utils.TiesConstants.*; -import static org.oran.smo.teiv.utils.query.QueryMonadTestUtil.*; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.jooq.impl.DSL.condition; -import static org.jooq.impl.DSL.field; - -class QueryMonadTest { - private static DSLContext context; - - @BeforeAll - public static void setUp() throws SchemaLoaderException { - MockSchemaLoader mockSchemaLoader = new MockSchemaLoader(); - mockSchemaLoader.loadSchemaRegistry(); - context = DSL.using(new MockConnection(m -> new MockResult[1])); - } - - @Test - void test1i_noAttributesNorFieldsGood() { - String entityType = "GNBDUFunction"; - String fields = ""; - String attributes = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, attributes, relationships); - - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test2i_attributesGood() { - String entityType = "GNBDUFunction"; - String fields = "/attributes"; - String attributes = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, attributes, relationships); - Select builtWithQM = (Select) underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply( - context); - Select reference = (Select) createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "dUpLMNId")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "dUpLMNId")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "gNBDUId")).as(String - .format(TIES_DATA, - "GNBDUFunction") + "." + String - .format(QUOTED_STRING, - "gNBDUId")), - field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBDUId")).as(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBDUId")), field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBIdLength")).as( - String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "gNBIdLength")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "cmId")).as( - String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "cmId"))).from(String.format( - TIES_DATA, "GNBDUFunction"))); - - List> fieldsActual = builtWithQM.getSelect(); - List> fieldsExpected = reference.getSelect(); - Assertions.assertTrue(fieldsActual.containsAll(fieldsExpected)); - } - - @Test - void test2ii_attributesTypoException() { - String entityType = "GNBDUFunction"; - String fields = "/attribute/fdn; /attributes/id; /attributes/gNBId"; - String filter = "/attributes[contains(@fdn, \"93\")] | /attributes[@gNBId=4000259]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test2iii_attributesMissingSlashException() { - String entityType = "GNBDUFunction"; - String fields = "attributes/fdn; /attributes/id; /attributes/gNBId"; - String filter = "/attributes[contains(@fdn, \"93\")] | /attributes[@gNBId=4000259]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test3i_attributesFdnGood() { - String entityType = "GNBDUFunction"; - String fields = "/attributes(fdn)"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME)).as(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME))) - .from(String.format(TIES_DATA, "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test3ii_attributesFdnGood() { - String entityType = "GNBDUFunction"; - String fields = "/attributes/fdn"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME)).as(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, ID_COLUMN_NAME))) - .from(String.format(TIES_DATA, "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test3iii_attributesFdnMissingSlashException() { - String entityType = "GNBDUFunction"; - String fields = "/attributefdn"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - //should be empty response - @Test - void test3iv_attributesFdnTypoColumm() { - String entityType = "GNBDUFunction"; - String fields = "/attributes/fnd"; - String attributes = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, attributes, relationships); - Select builtWithQM = (Select) underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply( - context); - Select reference = (Select) createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + ".id").as(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "id")), field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")) - .as(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), - field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "dUpLMNId")).as(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "dUpLMNId")), field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBDUId")).as( - String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "gNBDUId")), field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "gNBId")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, - "gNBId")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "gNBIdLength")).as( - String.format(TIES_DATA, - "GNBDUFunction") + "." + String - .format(QUOTED_STRING, - "gNBIdLength")), - field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "cmId")).as(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "cmId"))).from(String - .format(TIES_DATA, "GNBDUFunction"))); - - List> fieldsActual = builtWithQM.getSelect(); - List> fieldsExpected = reference.getSelect(); - Assertions.assertTrue(fieldsActual.containsAll(fieldsExpected)); - } - - @Test - void test3v_attributesFdnMissingOpeningBracketException() { - String entityType = "GNBDUFunction"; - String fields = "/attributefdn)"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test3vi_attributesFdnMissingClosingBracketException() { - String entityType = "GNBDUFunction"; - String fields = "/attribute(fdn"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test4i_attributesFdnIdGood() { - String entityType = "GNBDUFunction"; - String fields = "/attributes(fdn)"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format( - TIES_DATA, "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test4ii_attributesFdnIdGood() { - String entityType = "GNBDUFunction"; - String fields = "/attributes/fdn"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "fdn")), field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format( - TIES_DATA, "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test4iii_attributesFdnIdMissingCommaException() { - String entityType = "GNBDUFunction"; - String fields = "/attribute(fdn id)"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test4iv_attributesFdnIdMissingSemiColonException() { - String entityType = "GNBDUFunction"; - String fields = "/attribute/fdn /attribute/id"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test4v_attributesFdnIdMissingSecondSlashException() { - String entityType = "GNBDUFunction"; - String fields = "/attribute/fdn; attribute/id"; - String filter = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test5i_attributesContainsGood() { - String entityType = "GNBDUFunction"; - String fields = ""; - String attributes = "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, fields, attributes, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).where(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "fdn")).contains("/SubNetwork=Ireland/"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @ParameterizedTest - @ValueSource(strings = { "/attributescontains (@fdn, \"/SubNetwork=Ireland/\")]", - "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\")", - "/attributes[contains (fdn, \"/SubNetwork=Ireland/\")]", - "/attributes[contans (@fdn, \"/SubNetwork=Ireland/\")]", - "/attributes[contains @fdn, \"/SubNetwork=Ireland/\")]", - "/attributes[contains (@fdn, \"/SubNetwork=Ireland/\"]", - "/attributes[contains (@fdn \"/SubNetwork=Ireland/\")]", "/attributes[contains (@fdn, /SubNetwork=Ireland/\")]", - "/attributes[contains (@fdn, \"/SubNetwork=Ireland/)]" }) - void test5ii_ix_attributesException(String scope) { - String entityType = "GNBDUFunction"; - String target = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test5x_attributesColumnTypoEmptyList() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[contains (@fnd, \"/SubNetwork=Ireland/\")]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test5xi_attributesContainsWrongValueEmptyList() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[contains (@fdn, \"/SubNetwork Ireland/\")]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).where(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "fdn")).contains("/SubNetwork Ireland/"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test6i_attributesEqualsGood() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[@gNBIdLength=3]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).where(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "gNBIdLength")).eq(3))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test6iii_attributesMissingEquationSignException() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[@gNBIdLength 3]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test7i_attributesEqualsGood() { - String entityType = "GNBDUFunction"; - String fields = ""; - String attributes = "/attributes[@gNBIdLength=3 and @gNBId=111]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, fields, attributes, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).where((field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "gNBIdLength")).eq(3)).and(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBId")).eq(111)))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test7iii_attributesMissingAndException() { - String entityType = "GNBDUFunction"; - String fields = ""; - String filter = "/attributes[@gNBIdLength=3 @gNBId=-1]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test7iv_attributesTypoAndException() { - String entityType = "GNBDUFunction"; - String fields = ""; - String filter = "/attributes[@gNBIdLength=3 adn @gNBId=111]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test8i_attributesEqualBarEqualGood() { - String entityType = "GNBDUFunction"; - String fields = ""; - String attributes = "/attributes[@gNBIdLength=3 and @gNBId=111] | /attributes[@gNBIdLength=3 and @gNBId=112]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, fields, attributes, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).where(((field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "gNBIdLength")).eq(3)).and(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "gNBId")).eq(111))) - .or((field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "gNBIdLength")).eq(3)).and(field( - String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "gNBId")).eq( - 112))))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test8ii_attributesEqualBarEqualMissingBarException() { - String entityType = "GNBDUFunction"; - String fields = ""; - String filter = "/attributes[@gNBIdLength=3 and @gNBId=111] /attributes[@gNBIdLength=3 and @gNBId=112]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test9i_attributesContainEqualGood() { - String entityType = "GNBDUFunction"; - String fields = ""; - String attributes = "/attributes[contains (@fdn, \"SubNetwork=Ireland\")] ; /attributes[@gNBIdLength=3]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, fields, attributes, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test9ii_attributesMissingSemiColonException() { - String entityType = "GNBDUFunction"; - String fields = ""; - String filter = "/attributes[contains (@fdn, \"SubNetwork=Ireland\")] /attributes[@gNBIdLength=3]"; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, fields, filter, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test10i_targetGood() { - String entityType = "GNBDUFunction"; - String target = "/NRCellDU"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("NRCellDU") - .getField("id", null, null).getType()).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format( - TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id")).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format(TIES_DATA, - "NRCellDU")).on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String - .format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test10ii_targetTypoGood() { - String entityType = "GNBDUFunction"; - String target = "/NRCelldu"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test11i_targetHopsGood() { - String entityType = "GNBDUFunction"; - String target = "/NRCellDU ; /NRSectorCarrier"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()).and(field(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - // spotless:off - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("NRCellDU").getField("id",null,null).getType()).as(String.format( - TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "id")), field("null").cast(getEntityTypeByName("NRSectorCarrier").getField("id",null,null).getType()).as(String.format( - TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")). - leftJoin(String.format(TIES_DATA, "NRCellDU")).on(condition(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .leftJoin(String.format(TIES_DATA, "NRSectorCarrier")).on(condition(field(String.format(TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))).where(joinFilter) - .union(context.select(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, "id")), field( - "null").cast(getEntityTypeByName("NRSectorCarrier").getField("id",null,null).getType()).as(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "id"))).from(String.format(TIES_DATA, "GNBDUFunction")). - leftJoin(String.format(TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))). - leftJoin(String.format(TIES_DATA, "NRSectorCarrier")).on(condition(field(String.format(TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field( - String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter)).union(context.select(field("null").cast(getEntityTypeByName("NRCellDU").getField("id",null,null).getType()).as(String.format( - TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "id")), field(String.format(TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format(QUOTED_STRING, "id"))) - .from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format(TIES_DATA, - "NRCellDU")).on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String - .format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") - + "." + String.format(QUOTED_STRING, "id"))))).leftJoin(String.format(TIES_DATA, - "NRSectorCarrier")).on(condition(field(String.format(TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + - String.format(QUOTED_STRING, "id"))))).where(joinFilter))); - // spotless:on - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test11ii_targetHopTypo() { - String entityType = "GNBDUFunction"; - String target = "/NRCellDU ; /NRSectorCarier"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("NRCellDU") - .getField("id", null, null).getType()).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format( - TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id")).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format(TIES_DATA, - "NRCellDU")).on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String - .format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test12i_TargetGoodWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU"; - String target = ""; - String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Condition relationFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).isNotNull()).and(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "id")).isNotNull()).and(field(String.format( - TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String.format( - TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))) - .where(relationFilter).and(joinFilter).union(context.select(field("null").cast(getEntityTypeByName( - "GNBDUFunction").getField("id", null, null).getType()).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id")))).where(relationFilter).and( - joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test12ii_relationshipWrongException() { - String entityType = "GNBDUFunction"; - String target = "/NRCellDU"; - String scope = ""; - String relationships = "USES"; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Invalid relationship name"); - } - - @Test - void test13i_RelationshipsGoodWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU | /CloudNativeApplication"; - String target = ""; - String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU, GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()).and(field(String.format(TIES_DATA, "CloudNativeApplication") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - - Condition relationFilter1 = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).isNotNull()).and(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "id")).isNotNull()).and(field(String.format( - TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU")).isNotNull()); - - Condition relationFilter2 = condition(field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format(QUOTED_STRING, - "aSide_GNBDUFunction")).isNotNull()).and(field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format(QUOTED_STRING, - "bSide_CloudNativeApplication")).isNotNull()).and(field(String.format(TIES_DATA, - "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - - // spotless:off - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")) - .eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))). - join(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")) - .on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String - .format(QUOTED_STRING, "aSide_GNBDUFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + - String.format(QUOTED_STRING, "id")))).leftJoin(String.format(TIES_DATA, "CloudNativeApplication")) - .on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format( - QUOTED_STRING, "bSide_CloudNativeApplication")).eq(field(String.format(TIES_DATA, "CloudNativeApplication") + "." + String.format(QUOTED_STRING, "id")))) - - .where(relationFilter1).and(relationFilter2).and(joinFilter).union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField("id",null,null).getType()).as(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")). - leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))) - .join(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")) - .on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + - String.format(QUOTED_STRING, "aSide_GNBDUFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "id")))).leftJoin(String.format(TIES_DATA, - "CloudNativeApplication")) - .on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String - .format(QUOTED_STRING, "bSide_CloudNativeApplication")).eq(field(String.format(TIES_DATA, - "CloudNativeApplication") + "." + String - .format(QUOTED_STRING, "id")))) - - .where(relationFilter1).and(relationFilter2).and(joinFilter)).union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField("id",null,null).getType()).as(String.format( - TIES_DATA, "GNBDUFunction") + - "." + String.format(QUOTED_STRING, "id"))) - .from(String.format(TIES_DATA, "GNBDUFunction")) - .leftJoin(String.format(TIES_DATA, "NRCellDU")). - on(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")) - .eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))) - .join(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION")) - .on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String.format(QUOTED_STRING, "aSide_GNBDUFunction")) - .eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))) - .leftJoin(String.format(TIES_DATA, "CloudNativeApplication")).on(field(String.format(TIES_DATA, "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION") + "." + String - .format(QUOTED_STRING, "bSide_CloudNativeApplication")) - .eq(field(String.format(TIES_DATA, "CloudNativeApplication") + "." + String.format(QUOTED_STRING, "id")))) - .where(relationFilter1).and(relationFilter2).and(joinFilter))); - // spotless:on - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test13ii_RelationshipsOnlyOneGoodWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU | /CloudNativeApplication"; - String target = ""; - String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU"; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - Condition relationFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).isNotNull()).and(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, "id")).isNotNull()).and(field(String.format( - TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String.format( - TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")))) - .where(relationFilter).and(joinFilter).union(context.select(field("null").cast(getEntityTypeByName( - "GNBDUFunction").getField("id", null, null).getType()).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id")))).where(relationFilter).and( - joinFilter)).union(context.select(field( - "null").cast(getEntityTypeByName( - "GNBDUFunction").getField( - "id", null, null) - .getType()).as( - String.format( - TIES_DATA, - "GNBDUFunction") + "." + String - .format(QUOTED_STRING, - "id"))) - .from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin( - String.format( - TIES_DATA, - "NRCellDU")) - .on(field(String.format(TIES_DATA, - "NRCellDU") + "." + String - .format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")) - .eq(field( - String.format( - TIES_DATA, - "GNBDUFunction") + "." + String - .format(QUOTED_STRING, - "id")))) - .where(relationFilter).and( - joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test13iii_RelationshipsInvalidWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU | /CloudNativeApplication"; - String target = ""; - String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU_2"; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Invalid relationship name"); - } - - @Test - void test13iv_RelationshipsInvalidWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU | /CloudNativeApplication"; - String target = ""; - String relationships = "GNBDUFUNCTION_PROVIDES_NRCELLDU GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Invalid relationship name"); - } - - @Test - void test14i_ScopeGoodWithHop() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(condition(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField( - "id", null, null).getType()).as(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String - .format(TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test14ii_ScopeInvalidWithHop() { - String entityType = "GNBDUFunction"; - String scope = "/NRCellDU_2"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test14iii_ScopeInvalidWithHop() { - String entityType = "GNBDUFunction"; - String scope = "/AntennaCapability"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test15i_FilterOrGoodWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/NRSectorCarrier | /NRCellDU"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()).and(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - // spotless:off - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))) - .from(String.format(TIES_DATA, "GNBDUFunction")) - .leftJoin(String.format(TIES_DATA, "NRSectorCarrier")) - .on(condition(field(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + - String.format(QUOTED_STRING, "id"))))) - .leftJoin(String.format(TIES_DATA, "NRCellDU")) - .on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter) - .union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField("id",null,null).getType()).as(String.format( - TIES_DATA, "GNBDUFunction") + "." + - String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")) - .leftJoin(String.format(TIES_DATA, "NRSectorCarrier")) - .on(condition(field(String.format(TIES_DATA, "NRSectorCarrier") + "." + String.format( - QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .leftJoin(String.format(TIES_DATA, "NRCellDU")) - .on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + - "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter)) - .union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField("id",null,null).getType()).as(String.format( - TIES_DATA, "GNBDUFunction") + "." + - String.format(QUOTED_STRING, "id"))) - .from(String.format(TIES_DATA, "GNBDUFunction")) - .leftJoin(String.format(TIES_DATA, "NRSectorCarrier")) - .on(condition(field(String.format(TIES_DATA, "NRSectorCarrier") + "." + - String.format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field( - String.format(TIES_DATA, "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .leftJoin(String.format(TIES_DATA, "NRCellDU")) - .on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, "GNBDUFunction") + "." + String - .format(QUOTED_STRING, "id"))))) - .where(joinFilter))); - // spotless:on - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test15ii_ScopeOrOneGoodWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/AntennaCapability | /NRCellDU"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(condition(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField( - "id", null, null).getType()).as(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String - .format(TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test15iii_ScopeTypoWithHops() { - String entityType = "GNBDUFunction"; - String scope = "/AntennaCapability2 | /NRCellDU"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction")).leftJoin(String.format(TIES_DATA, "NRCellDU")).on(condition(field(String - .format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field("null").cast(getEntityTypeByName("GNBDUFunction").getField( - "id", null, null).getType()).as(String.format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String - .format(TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format( - TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - Assertions.assertEquals(reference, builtWithQM); - } - - @ParameterizedTest - @ValueSource(strings = { "//attributes", "///attributes" }) - void test16i_targetSlashes(String target) { - String entityType = "GNBDUFunction"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @ParameterizedTest - @ValueSource(strings = { "//attributes", "///attributes" }) - void test16i_scopeSlashes(String scope) { - String entityType = "GNBDUFunction"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @ParameterizedTest - @ValueSource(strings = { "/attributes[@gNBIdLength>3]", "/attributes[@gNBIdLength<3]" }) - void test17i_scopeConditions(String scope) { - String entityType = "GNBDUFunction"; - String target = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test18i_scopeOr() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attribute[@gNBIdLength=3 or @gNBIdLength=4]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test19i_targetWrongColumn() { - String entityType = "GNBDUFunction"; - String target = "/attribute(gnbidLength)"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test19i_scopeWrongColumn() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attribute[@gnbiLength=3]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test20i_wrongTargetEntity() { - String entityType = "GNBDUFunction"; - String target = "/AntennaCapability"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Objects are not related"); - } - - @Test - void test21_manyToOneTest() { - String entityType = "NRSectorCarrier"; - String target = "/AntennaCapability"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "AntennaCapability") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("NRCellDU") - .getField("id", null, null).getType()).as(String.format(TIES_DATA, "AntennaCapability") + "." + String - .format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "NRSectorCarrier")).leftJoin(String - .format(TIES_DATA, "AntennaCapability")).on(condition(field(String.format(TIES_DATA, - "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "REL_FK_used-antennaCapability")).eq(field(String.format(TIES_DATA, - "AntennaCapability") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field(String.format(TIES_DATA, "AntennaCapability") + "." + String - .format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, "AntennaCapability") + "." + String - .format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "NRSectorCarrier")).leftJoin( - String.format(TIES_DATA, "AntennaCapability")).on(condition(field(String.format( - TIES_DATA, "NRSectorCarrier") + "." + String.format(QUOTED_STRING, - "REL_FK_used-antennaCapability")).eq(field(String.format(TIES_DATA, - "AntennaCapability") + "." + String.format(QUOTED_STRING, - "id"))))).where(joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test22i_processTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/id/fdn"; - String scope = "/attributes[@gNBId=3000696]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test22ii_processTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/fdn"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test22iii_processTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/dummyText/fdn"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test23i_processTargetAttribute() { - String entityType = "GNBDUFunction"; - String target = "/id"; - String scope = ""; - String relationships = ""; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "GNBDUFunction"))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test23ii_processTargetAttribute() { - String entityType = "GNBDUFunction"; - String target = "/NRCellDU/id"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - Query builtWithQM = qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("NRCellDU") - .getField("id", null, null).getType()).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format( - TIES_DATA, "NRCellDU")).on(condition(field(String.format(TIES_DATA, - "NRCellDU") + "." + String.format(QUOTED_STRING, - "REL_FK_provided-by-gnbduFunction")).eq(field(String.format(TIES_DATA, - "GNBDUFunction") + "." + String.format(QUOTED_STRING, "id"))))) - .where(joinFilter).union(context.select(field(String.format(TIES_DATA, "NRCellDU") + "." + String.format( - QUOTED_STRING, "id")).as(String.format(TIES_DATA, "NRCellDU") + "." + String.format(QUOTED_STRING, - "id"))).from(String.format(TIES_DATA, "GNBDUFunction")).leftJoin(String.format(TIES_DATA, - "NRCellDU")).on(condition(field(String.format(TIES_DATA, "NRCellDU") + "." + String - .format(QUOTED_STRING, "REL_FK_provided-by-gnbduFunction")).eq(field(String - .format(TIES_DATA, "GNBDUFunction") + "." + String.format( - QUOTED_STRING, "id"))))).where(joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test24i_addTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/id(fdn)"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test24ii_addTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/attributes(id)"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test24iii_addTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/attributes(notExistingColumn)"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test24iiii_addTargetAttributeError() { - String entityType = "GNBDUFunction"; - String target = "/attr(fdn)"; - String scope = ""; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test25_checkIdAttributesError() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attr[@fdn=\"Solar\"]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test26i_checkIdExpressionsError() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[@id=\"123\"]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test26ii_checkIdExpressionsError() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/id[@gNBId=12]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test26iii_checkIdExpressionsError() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/id[contains (@fdn,\"12\")]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test26iiii_checkIdExpressionsError() { - String entityType = "GNBDUFunction"; - String target = ""; - String scope = "/attributes[contains (@id,\"987\")]"; - String relationships = ""; - - QueryMonad qm = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test27i_getTopologyByTargetFilterError() { - String entityType = null; - String target = "/CloudSite/attributes/"; - String scope = ""; - String relationships = ""; - String domain = "RAN_LOGICAL"; - - QueryMonad qm = getQueryMonadWithDomain(entityType, target, scope, relationships, domain); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test27ii_getTopologyByTargetFilterError() { - String entityType = null; - String target = "/attributes"; - String scope = ""; - String relationships = "SECTOR_GROUPS_ANTENNAMODULE"; - String domain = "RAN"; - - QueryMonad qm = getQueryMonadWithDomain(entityType, target, scope, relationships, domain); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Objects are not related"); - } - - @Test - void test27iii_getTopologyByTargetFilterError() { - String entityType = null; - String target = "/NRCellDU"; - String scope = ""; - String relationships = "SECTOR_GROUPS_ANTENNAMODULE"; - String domain = "RAN"; - - QueryMonad qm = getQueryMonadWithDomain(entityType, target, scope, relationships, domain); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Objects are not related"); - } - - @Test - void test27iiii_getTopologyByTargetFilterError() { - String entityType = null; - String target = "/attributes/name"; - String scope = ""; - String relationships = ""; - String domain = "RAN"; - - QueryMonad qm = getQueryMonadWithDomain(entityType, target, scope, relationships, domain); - - assertThatThrownBy(() -> qm.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar error"); - } - - @Test - void test27iiiii_getTopologyByTargetFilterError() { - String entityType = "CloudNativeApplication"; - String target1 = "/attributes/id"; - String target2 = "/attributes(id)"; - String scope = ""; - String relationships = ""; - String domain = "RAN_LOGICAL"; - - QueryMonad qm1 = getQueryMonadWithDomain(entityType, target1, scope, relationships, domain); - QueryMonad qm2 = getQueryMonadWithDomain(entityType, target2, scope, relationships, domain); - - assertThatThrownBy(() -> qm1.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - - assertThatThrownBy(() -> qm2.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Grammar Error"); - } - - @Test - void test28i_getTopologyByTargetFilter() { - String entityType = null; - String target = "/Sector/id"; - String scope = ""; - String relationships = ""; - String domain = "EQUIPMENT_TO_RAN"; - - QueryMonad underTest = getQueryMonadWithDomain(entityType, target, scope, relationships, domain); - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Query reference = createDistinctQuery(context, context.select(field("null").cast(getEntityTypeByName("Sector") - .getField("id", null, null).getType()).as(String.format(TIES_DATA, "Sector") + "." + String.format( - QUOTED_STRING, "id"))).from("(SELECT '') as dual_table").leftJoin(String.format(TIES_DATA, - "Sector")).on(condition(field(String.format(TIES_DATA, "Sector") + "." + "id").eq(field( - "(SELECT '')")))).where(field(String.format(TIES_DATA, "Sector") + "." + String - .format(QUOTED_STRING, "id")).isNotNull()).union(context.select(field(String - .format(TIES_DATA, "Sector") + "." + String.format(QUOTED_STRING, - "id")).as(String.format(TIES_DATA, "Sector") + "." + String - .format(QUOTED_STRING, "id"))).from( - "(SELECT '') as dual_table").rightJoin( - String.format(TIES_DATA, "Sector")) - .on(condition(field(String.format(TIES_DATA, "Sector") + "." + "id") - .eq(field("(SELECT '')")))).where(field(String.format( - TIES_DATA, "Sector") + "." + String.format( - QUOTED_STRING, "id")).isNotNull())) - - ); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test50_relConnectingSameEntityTest() { - String entityType = "AntennaModule"; - String target = "/AntennaModule"; - String scope = ""; - String relationships = "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE"; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - - Query builtWithQM = underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context); - - Condition joinFilter = condition(field(String.format(TIES_DATA, "AntennaModule") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - - Condition relationFilter = condition(field(String.format(TIES_DATA, - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String.format(QUOTED_STRING, "aSide_AntennaModule")) - .isNotNull()).and(field(String.format(TIES_DATA, - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String.format(QUOTED_STRING, - "bSide_AntennaModule")).isNotNull()).and(field(String.format(TIES_DATA, - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String.format( - QUOTED_STRING, "id")).isNotNull()); - - Query reference = createDistinctQuery(context, context.select(field(String.format(TIES_DATA, - "AntennaModule") + "." + String.format(QUOTED_STRING, "id")).as(String.format(TIES_DATA, - "AntennaModule") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "AntennaModule")).join(String.format(TIES_DATA, "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE")) - .on(field(String.format(TIES_DATA, "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String.format( - QUOTED_STRING, "bSide_AntennaModule")).eq(field(String.format(TIES_DATA, - "AntennaModule") + "." + String.format(QUOTED_STRING, "id")))).or(field(String.format( - TIES_DATA, "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String.format( - QUOTED_STRING, "aSide_AntennaModule")).eq(field(String.format(TIES_DATA, - "AntennaModule") + "." + String.format(QUOTED_STRING, "id")))) - .where(relationFilter).and(joinFilter).union(context.select(field("null").cast(getEntityTypeByName( - "AntennaModule").getField("id", null, null).getType()).as(String.format(TIES_DATA, - "AntennaModule") + "." + String.format(QUOTED_STRING, "id"))).from(String.format(TIES_DATA, - "AntennaModule")).join(String.format(TIES_DATA, - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE")).on(field(String.format( - TIES_DATA, "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String - .format(QUOTED_STRING, "bSide_AntennaModule")).eq(field( - String.format(TIES_DATA, - "AntennaModule") + "." + String.format( - QUOTED_STRING, "id")))).or(field( - String.format(TIES_DATA, - "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE") + "." + String - .format(QUOTED_STRING, - "aSide_AntennaModule")) - .eq(field( - String.format( - TIES_DATA, - "AntennaModule") + "." + String - .format(QUOTED_STRING, - "id")))) - .where(relationFilter).and(joinFilter))); - - Assertions.assertEquals(reference, builtWithQM); - } - - @Test - void test50_relConnectingSameEntityTest_unrelatedEntities() { - String entityType = "AntennaModule"; - String target = "/AntennaModule"; - String scope = ""; - String relationships = "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION"; - - QueryMonad underTest = getQueryMonad(entityType, target, scope, relationships); - - assertThatThrownBy(() -> underTest.withSchema(PaginationDTO.builder().offset(0).limit(5).build()).apply(context)) - .isInstanceOf(TiesPathException.class).hasMessage("Objects are not related"); - } - -} diff --git a/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTestUtil.java b/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTestUtil.java deleted file mode 100644 index a8c02ec..0000000 --- a/teiv/src/test/java/org/oran/smo/teiv/utils/query/QueryMonadTestUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.oran.smo.teiv.utils.query; - -import org.jooq.DSLContext; -import org.jooq.Query; -import org.jooq.Select; - -import static org.jooq.impl.DSL.asterisk; -import static org.jooq.impl.DSL.one; - -public class QueryMonadTestUtil { - public static QueryMonad getQueryMonad(String entityType, String fields, String attributes, String relationships) { - return QueryMonad.builder().managedObject(entityType).targets(fields).scope(attributes).relationships(relationships) - .build(); - } - - public static Query createDistinctQuery(DSLContext context, Select query) { - return context.selectDistinct(asterisk()).from(query.asTable("TiesPathQuery")).orderBy(one().asc()).limit(0, 5); - } - - public static QueryMonad getQueryMonadWithDomain(String entityType, String fields, String attributes, - String relationships, String domain) { - return QueryMonad.builder().managedObject(entityType).targets(fields).scope(attributes).relationships(relationships) - .domain(domain).build(); - } - -} diff --git a/teiv/src/test/resources/application.yaml b/teiv/src/test/resources/application.yaml index ad17d91..a1f8f94 100644 --- a/teiv/src/test/resources/application.yaml +++ b/teiv/src/test/resources/application.yaml @@ -60,6 +60,8 @@ spring.datasource.read.maximum-pool-size: 2 spring.datasource.write.maximum-pool-size: 2 spring.caching.consumer-data-ttl-ms: 60000 +consumer-data.batch-size: 50 + kafka: server: bootstrap-server-host: kafka @@ -74,12 +76,13 @@ kafka: retry-attempts: 3 retry-interval-ms: 1000 topology-ingestion: + topic: + name: topology-inventory-ingestion + partitions: 4 + replicas: 1 + retention-ms: 7200000 + retention-bytes: 104857600 consumer: - topic: - name: topology-inventory-ingestion - partitions: 4 - replicas: 1 - retention-ms: 86400000 group-id: topology-inventory-ingestion-consumer auto-offset-reset: earliest max-poll-records: 500 @@ -94,7 +97,4 @@ database: retry-policies: deadlock: retry-attempts: 3 - retry-backoff-ms: 200 - -feature_flags: - use_alternate_delete_logic: false \ No newline at end of file + retry-backoff-ms: 200 \ No newline at end of file diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-arrays.json b/teiv/src/test/resources/cloudeventdata/common/ce-arrays.json new file mode 100644 index 0000000..de0237f --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-arrays.json @@ -0,0 +1,53 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "entityId_0", + "attributes": { + "eUtranFqBands": [ + "a", + "b", + "c" + ] + } + }, + { + "id": "entityId_1", + "attributes": { + "eUtranFqBands": [ + "a", + "b" + ] + } + }, + { + "id": "entityId_2", + "attributes": { + "geranFqBands": [ + "a" + ] + } + }, + { + "id": "entityId_3", + "attributes": { + "eUtranFqBands": [ + "q" + ], + "nRFqBands": [] + } + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-data-only.json b/teiv/src/test/resources/cloudeventdata/common/ce-data-only.json deleted file mode 100644 index a02d18f..0000000 --- a/teiv/src/test/resources/cloudeventdata/common/ce-data-only.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "entities": [ - { - "o-ran-smo-teiv-ran:NRCellDU": [ - { - "id": "entityId_1", - "attributes": { - "cellLocalId": 4589, - "nRPCI": 12, - "nRTAC": 310, - "primitiveArray": [ - 1, - 2, - 3 - ], - "singleList": [ - "12" - ], - "jsonObjectArray": [ - { - "test1": "128", - "test2": "49" - }, - { - "test1": "129", - "test2": "50" - } - ] - } - }, - { - "id": "entityId_3", - "attributes": { - "cellLocalId": 45891, - "nRPCI": 121, - "nRTAC": 3101, - "primitiveArray": [ - 1, - 2, - 3 - ], - "singleList": [ - "121" - ], - "jsonObjectArray": [ - { - "test1": "1281", - "test2": "491" - }, - { - "test1": "1291", - "test2": "501" - } - ] - } - } - ] - }, - { - "o-ran-smo-teiv-ran:NRSectorCarrier": [ - { - "id": "entityId_2", - "attributes": { - "arfcnDL": 4590, - "testDouble": 32.5, - "testBoolean": true, - "cmId": { - "option1": "test_option1", - "option2": "test_option2" - } - } - } - ] - } - ], - "relationships": [ - { - "o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER": [ - { - "id": "relationshipId", - "aSide": "entityId_1", - "bSide": "entityId_2" - }, - { - "id": "relationshipId2", - "aSide": "entityId_3", - "bSide": "entityId_4" - } - ], - "o-ran-smo-teiv-ran:GNBDUFunctionRealisedByCloudNativeApplication": [ - { - "id": "relationshipId3", - "aSide": "entityId_5", - "bSide": "entityId_6" - }, - { - "id": "relationshipId4", - "aSide": "entityId_5", - "bSide": "entityId_7" - } - ] - } - ] -} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-invalid-entity-attribute.json b/teiv/src/test/resources/cloudeventdata/common/ce-invalid-entity-attribute.json new file mode 100644 index 0000000..b5a6593 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-invalid-entity-attribute.json @@ -0,0 +1,24 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "id": "id1", + "attributes": { + "gNBId": -1.0 + } + } + ] + } + ], + "relationships": [] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module-type-pair.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module-type-pair.json new file mode 100644 index 0000000..86042ea --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module-type-pair.json @@ -0,0 +1,28 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRCELLDU_USES_NRSECTORCARRIER": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module.json new file mode 100644 index 0000000..7ff15ea --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-module.json @@ -0,0 +1,28 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-type.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-type.json new file mode 100644 index 0000000..a23cf1c --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-invalid-type.json @@ -0,0 +1,28 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORSES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-a-side.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-a-side.json new file mode 100644 index 0000000..a51d004 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-a-side.json @@ -0,0 +1,27 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-b-side.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-b-side.json new file mode 100644 index 0000000..aa53179 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-b-side.json @@ -0,0 +1,27 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-both-sides.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-both-sides.json new file mode 100644 index 0000000..5e5eae1 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-both-sides.json @@ -0,0 +1,26 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "relation_3" + }, + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-id.json b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-id.json new file mode 100644 index 0000000..ceba2c1 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-relationship-missing-id.json @@ -0,0 +1,27 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + }, + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-with-data.json b/teiv/src/test/resources/cloudeventdata/common/ce-with-data.json index ef26639..73821da 100644 --- a/teiv/src/test/resources/cloudeventdata/common/ce-with-data.json +++ b/teiv/src/test/resources/cloudeventdata/common/ce-with-data.json @@ -86,27 +86,34 @@ "o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER": [ { "id": "relationshipId", - "aSide": "entityId_1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR004,ManagedElement=me04,GNBDUFunction=gnbdu04,NRCellDU=NR-Cell-07", "bSide": "entityId_2" }, { "id": "relationshipId2", "aSide": "entityId_3", - "bSide": "entityId_4" + "bSide": "entityId_4", + "sourceIds": [ + "source10", + "source20" + ] } ] }, { - "o-ran-smo-teiv-ran:GNBDUFunctionRealisedByCloudNativeApplication": [ + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ { - "id": "relationshipId3", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=89FE9A4ED8451D779865C389900E247B13E360B0A4175EBA80AA9B384BFA4C688F17865AFD934085B0235BCA66128F2E6D4CE6953EAAB2EDEBD94B3683C1A064", "aSide": "entityId_5", - "bSide": "entityId_6" + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR004,ManagedElement=me04,GNBDUFunction=gnbdu04,NRCellDU=NR-Cell-07" }, { "id": "relationshipId4", "aSide": "entityId_5", - "bSide": "entityId_7" + "bSide": "entityId_3", + "sourceIds": [ + "source21" + ] } ] } diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids.json b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids.json new file mode 100644 index 0000000..2d3a410 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids.json @@ -0,0 +1,75 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "entityId_1", + "attributes": { + "cellLocalId": 4589, + "nRPCI": 12, + "nRTAC": 310, + "primitiveArray": [ + 1, + 2, + 3 + ], + "singleList": [ + "12" + ], + "jsonObjectArray": [ + { + "test1": "128", + "test2": "49" + }, + { + "test1": "129", + "test2": "50" + } + ] + }, + "sourceIds": [ + "source1", + "source2" + ] + }, + { + "id": "entityId_2", + "attributes": { + "nCI": 123, + "nRTAC": 32 + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "id": "invalid_relationshipId<3", + "aSide": "entityId_5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_5", + "aSide": "entityId?5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_6", + "aSide": "entityId_5", + "bSide": "entityId[1]" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids2.json b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids2.json new file mode 100644 index 0000000..0b0a0b4 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids2.json @@ -0,0 +1,75 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "entityId_1", + "attributes": { + "cellLocalId": 4589, + "nRPCI": 12, + "nRTAC": 310, + "primitiveArray": [ + 1, + 2, + 3 + ], + "singleList": [ + "12" + ], + "jsonObjectArray": [ + { + "test1": "128", + "test2": "49" + }, + { + "test1": "129", + "test2": "50" + } + ] + }, + "sourceIds": [ + "source1", + "source2" + ] + }, + { + "id": "entityId_2", + "attributes": { + "nCI": 123, + "nRTAC": 32 + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "id": "relationshipId_3", + "aSide": "entityId_5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_5", + "aSide": "invalid_entityId?5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_6", + "aSide": "entityId_5", + "bSide": "entityId_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids3.json b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids3.json new file mode 100644 index 0000000..13df9ff --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/common/ce-with-invalid-relationship-ids3.json @@ -0,0 +1,75 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "entityId_1", + "attributes": { + "cellLocalId": 4589, + "nRPCI": 12, + "nRTAC": 310, + "primitiveArray": [ + 1, + 2, + 3 + ], + "singleList": [ + "12" + ], + "jsonObjectArray": [ + { + "test1": "128", + "test2": "49" + }, + { + "test1": "129", + "test2": "50" + } + ] + }, + "sourceIds": [ + "source1", + "source2" + ] + }, + { + "id": "entityId_2", + "attributes": { + "nCI": 123, + "nRTAC": 32 + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "id": "relationshipId_3", + "aSide": "entityId_5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_5", + "aSide": "entityId_5", + "bSide": "entityId_1" + }, + { + "id": "relationshipId_6", + "aSide": "entityId_5", + "bSide": "invalid_entityId[1]" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-geo-location.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-geo-location.json index 834c647..a8eaaae 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-geo-location.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-geo-location.json @@ -9,9 +9,13 @@ "data": { "entities": [ { - "o-ran-smo-teiv-cloud:CloudSite": [ + "o-ran-smo-teiv-ran-cloud:CloudSite": [ { "id": "CloudSite1", + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ], "attributes": { "name": "geo-location1", "geo-location": { diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-many.json index 99507d6..64e35a4 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-many.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-many.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-cloud:CloudNativeApplication": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeApplication": [ { "id": "CloudNativeApplication_1", "attributes": { @@ -31,7 +31,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBDUFunction": [ + "o-ran-smo-teiv-ran-logical:GNBDUFunction": [ { "id": "GNBDU_1", "attributes": { @@ -52,7 +52,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + "o-ran-smo-teiv-ran-logical:GNBCUUPFunction": [ { "id": "GNBCUUP_1", "attributes": { @@ -68,7 +68,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + "o-ran-smo-teiv-ran-logical:GNBCUCPFunction": [ { "id": "GNBCUCP_1", "attributes": { @@ -91,7 +91,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_1", "aSide": "GNBDU_1", @@ -105,7 +105,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_2", "aSide": "GNBCUUP_1", @@ -119,7 +119,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_3", "aSide": "GNBCUCP_1", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-one.json index 2729d70..65fe5ed 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-many-to-one.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-cloud:NodeCluster": [ + "o-ran-smo-teiv-ran-cloud:NodeCluster": [ { "id": "NodeCluster_1", "attributes": { @@ -19,7 +19,7 @@ ] }, { - "o-ran-smo-teiv-ran:AntennaCapability": [ + "o-ran-smo-teiv-ran-logical:AntennaCapability": [ { "id": "AntennaCapability_1", "attributes": { @@ -32,7 +32,7 @@ ] }, { - "o-ran-smo-teiv-ran:NRSectorCarrier": [ + "o-ran-smo-teiv-ran-logical:NRSectorCarrier": [ { "id": "NRSectorCarrier_1", "attributes": { @@ -42,7 +42,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudSite": [ + "o-ran-smo-teiv-ran-cloud:CloudSite": [ { "id": "CloudSite_1", "attributes": { @@ -54,7 +54,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ + "o-ran-smo-teiv-ran-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ { "id": "relation_1", "aSide": "NodeCluster_1", @@ -63,7 +63,7 @@ ] }, { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ { "id": "relation_10", "aSide": "NRSectorCarrier_1", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-many.json index 2b8d3aa..ed4c895 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-many.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-many.json @@ -9,31 +9,37 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_1", "attributes": { }, - "sourceIds": [] + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] } ] }, { - "o-ran-smo-teiv-ran:ENodeBFunction": [ + "o-ran-smo-teiv-ran-logical:ENodeBFunction": [ { "id": "ENodeBFunction_1", "attributes": { }, - "sourceIds": [] + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] } ] } ], "relationships": [ { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ { "id": "relation_1", "aSide": "ManagedElement_1", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-one.json index 4c4cdb1..defebbb 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-one-to-one.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_2", "attributes": { @@ -25,7 +25,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ { "id": "CloudNativeSystem_2", "attributes": { @@ -43,7 +43,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ { "id": "relation_11", "aSide": "ManagedElement_2", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-relationship-connecting-same-entity.json index a411b47..32d571f 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-relationship-connecting-same-entity.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-relationship-connecting-same-entity.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-equipment:AntennaModule": [ + "o-ran-smo-teiv-ran-equipment:AntennaModule": [ { "id": "AntennaModule_1", "attributes": { @@ -25,7 +25,7 @@ ] }, { - "o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + "o-ran-smo-teiv-ran-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ { "id": "AntennaModule_3", "attributes": { @@ -55,7 +55,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE": [ { "id": "many_to_many_relation_1", "aSide": "AntennaModule_1", @@ -64,7 +64,7 @@ ] }, { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "one_to_many_relation_1", "aSide": "AntennaModule_3", @@ -73,7 +73,7 @@ ] }, { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "one_to_one_relation_1", "aSide": "AntennaModule_5", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-second-case.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-second-case.json index fd427e6..09f4494 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-second-case.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-create-second-case.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-ran:CloudNativeApplication": [ + "o-ran-smo-teiv-ran-logical:CloudNativeApplication": [ { "id": "CNA_SED_1", "attributes": { @@ -19,9 +19,13 @@ ] }, { - "o-ran-smo-teiv-ran:GNBDUFunction": [ + "o-ran-smo-teiv-ran-logical:GNBDUFunction": [ { "id": "GNBDU_SED_1", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], "attributes": { "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", "dUpLMNId": { @@ -40,9 +44,13 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + "o-ran-smo-teiv-ran-logical:GNBCUCPFunction": [ { "id": "GNBCUCP_SED_1", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], "attributes": { "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", "gNBCUName": "Test_sed_gNBCU", @@ -60,6 +68,10 @@ }, { "id": "GNBCUCP_SED_2", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=2", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], "attributes": { "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=2", "gNBCUName": "Test_sed_gNBCU2", @@ -80,7 +92,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_sed_1", "aSide": "GNBDU_SED_1", @@ -89,7 +101,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_sed_2", "aSide": "GNBCUCP_SED_1", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-managed-element.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-managed-element.json new file mode 100644 index 0000000..8d460bb --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-managed-element.json @@ -0,0 +1,20 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-many.json index 8b5797b..de99897 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-many.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-many.json @@ -9,14 +9,14 @@ "data": { "entities": [ { - "o-ran-smo-teiv-ran:CloudNativeApplication": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeApplication": [ { "id": "CloudNativeApplication_3" } ] }, { - "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + "o-ran-smo-teiv-ran-logical:GNBCUCPFunction": [ { "id": "GNBCUCP_1" } @@ -25,7 +25,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ { "id": "relation_1" } diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-one.json index 6ba8fc8..ba43673 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-many-to-one.json @@ -9,14 +9,14 @@ "data": { "entities": [ { - "o-ran-smo-teiv-cloud:NodeCluster": [ + "o-ran-smo-teiv-ran-cloud:NodeCluster": [ { "id": "NodeCluster_1" } ] }, { - "o-ran-smo-teiv-cloud:CloudSite": [ + "o-ran-smo-teiv-ran-cloud:CloudSite": [ { "id": "CloudSite_1" } @@ -25,7 +25,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ + "o-ran-smo-teiv-ran-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ { "id": "relation_1" } diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-many.json index b3d93ee..3a0f983 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-many.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-many.json @@ -9,14 +9,14 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_1" } ] }, { - "o-ran-smo-teiv-ran:ENodeBFunction": [ + "o-ran-smo-teiv-ran-logical:ENodeBFunction": [ { "id": "ENodeBFunction_1" } @@ -25,7 +25,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-logical:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ { "id": "relation_1" } diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-one.json index ccd5081..54ac71d 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-one-to-one.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_2" } @@ -18,7 +18,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ { "id": "relation_12" } diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-relationship-connecting-same-entity.json index e4844a0..9d481a4 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-relationship-connecting-same-entity.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-delete-relationship-connecting-same-entity.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-equipment:AntennaModule": [ + "o-ran-smo-teiv-ran-equipment:AntennaModule": [ { "id": "AntennaModule_1" }, @@ -21,14 +21,14 @@ ], "relationships": [ { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "one_to_many_relation_1" } ] }, { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "one_to_one_relation_1" } diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-long-names.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-long-names.json index ee90fb1..0447e9d 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-long-names.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-long-names.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-cloud:Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + "o-ran-smo-teiv-ran-cloud:Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ { "id": "Namespace_1", "attributes": { @@ -25,7 +25,7 @@ ] }, { - "o-ran-smo-teiv-oam:ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt": [ + "o-ran-smo-teiv-ran-oam:ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt": [ { "id": "ManagedElement_1", "attributes": { @@ -59,7 +59,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm": [ { "id": "CloudNativeSystem_1", "attributes": { @@ -81,7 +81,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ { "id": "CloudNativeApplication_1", "attributes": { @@ -103,7 +103,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ + "o-ran-smo-teiv-ran-logical:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ { "id": "GNBDUFunction_1", "attributes": { @@ -141,7 +141,7 @@ ] }, { - "o-ran-smo-teiv-ran:NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU": [ + "o-ran-smo-teiv-ran-logical:NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU": [ { "id": "NRCellDU_1", "attributes": { @@ -201,7 +201,7 @@ ] }, { - "o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + "o-ran-smo-teiv-ran-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ { "id": "AntennaModule_1", "attributes": { @@ -243,7 +243,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE": [ { "id": "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE_relation_1", "aSide": "CloudNativeApplication_1", @@ -262,7 +262,7 @@ ] }, { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM": [ { "id": "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_relation_1", "aSide": "ManagedElement_1", @@ -281,7 +281,7 @@ ] }, { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN": [ { "id": "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_1", "aSide": "ManagedElement_1", @@ -290,7 +290,7 @@ ] }, { - "o-ran-smo-teiv-ran-to-cloud:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN": [ + "o-ran-smo-teiv-ran-logical-to-cloud:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN": [ { "id": "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_1", "aSide": "GNBDUFunction_1", @@ -304,7 +304,7 @@ ] }, { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN": [ + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN": [ { "id": "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION_relation_1", "aSide": "ManagedElement_1", @@ -313,7 +313,7 @@ ] }, { - "o-ran-smo-teiv-ran:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU": [ + "o-ran-smo-teiv-ran-logical:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU": [ { "id": "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_1", "aSide": "GNBDUFunction_1", @@ -337,7 +337,7 @@ ] }, { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_relation_1", "aSide": "AntennaModule_1", @@ -351,7 +351,7 @@ ] }, { - "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ { "id": "ANTENNAMODULE_DEPLOYED_ON_ANTENNAMODULE_relation_1", "aSide": "AntennaModule_5", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many.json new file mode 100644 index 0000000..0ca2788 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many.json @@ -0,0 +1,101 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0002", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.merge", + "time": "2023-10-25T13:30:12Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran-logical:GNBDUFunction": [ + { + "id": "GNBDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran-logical:NRCellDU": [ + { + "id": "NRCellDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", + "cellLocalId": 4589, + "nCI": 1, + "nRPCI": 12, + "nRTAC": 310, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" + } + } + }, + { + "id": "NRCellDU_2", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", + "cellLocalId": 45891, + "nCI": 2, + "nRPCI": 121, + "nRTAC": 3101, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" + } + } + }, + { + "id": "NRCellDU_3", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", + "cellLocalId": 469, + "nCI": 3, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" + } + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "id": "relation_7", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_1" + }, + { + "id": "relation_8", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_2" + }, + { + "id": "relation_9", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_3" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many2.json b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many2.json index 6032e29..df8a16c 100644 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many2.json +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/ce-merge-one-to-many2.json @@ -9,51 +9,55 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_1", "attributes": { }, - "sourceIds": [] + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] }, { "id": "ManagedElement_2", "attributes": { }, - "sourceIds": [] + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] } ] }, { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ { "id": "CloudNativeSystem_1", "attributes": { }, - "sourceIds": [] + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] } ] }, { - "o-ran-smo-teiv-ran:GNBDUFunction": [ + "o-ran-smo-teiv-ran-logical:GNBDUFunction": [ { "id": "GNBDU_1", "attributes": { - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1", "dUpLMNId": { "mcc": 110, "mnc": 210 }, "gNBDUId": 111, "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" - } + "gNBIdLength": 3 }, "sourceIds": [ "urn:3gpp:dn:/SubNetwork=Europe/SubNetwork=Ireland/MeContext=NR01gNodeBRadio00001/ManagedElement=NR01gNodeBRadio00001/GNBDUFunction=1", @@ -65,7 +69,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ { "id": "relation_1", "aSide": "ManagedElement_1", diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-many.json deleted file mode 100644 index fe79568..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-many.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_6": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_6\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_3": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_3\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_1": "{\"o-ran-smo-teiv-ran:GNBCUCPFunction\":[{\"id\":\"GNBCUCP_1\",\"sourceIds\":[],\"attributes\":{\"gNBIdLength\":3,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1\",\"pLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBCUName\":\"Test_gNBCU\",\"gNBId\":123}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_3": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_3\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_3\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_2": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_2\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_2\"}}]}", - "TEIV/entity-types/CloudNativeApplication/entities/CloudNativeApplication_1": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_1\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_1\"}}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_4": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_4\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBDUFunction/entities/GNBDU_1": "{\"o-ran-smo-teiv-ran:GNBDUFunction\":[{\"id\":\"GNBDU_1\",\"sourceIds\":[],\"attributes\":{\"gNBIdLength\":3,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1\",\"dUpLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBDUId\":111,\"gNBId\":123}}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_2": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_2\",\"sourceIds\":[]}]}", - "TEIV/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_1": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_1\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_5": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_5\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBCUUPFunction/entities/GNBCUUP_1": "{\"o-ran-smo-teiv-ran:GNBCUUPFunction\":[{\"id\":\"GNBCUUP_1\",\"sourceIds\":[],\"attributes\":{\"gNBId\":123,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1\",\"gNBIdLength\":3}}]}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-one.json deleted file mode 100644 index 154a265..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-many-to-one.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "CLOUD/entity-types/NodeCluster/entities/NodeCluster_1": "{\"o-ran-smo-teiv-cloud:NodeCluster\":[{\"id\":\"NodeCluster_1\",\"sourceIds\":[],\"attributes\":{\"name\":null}}]}", - "CLOUD/entity-types/CloudSite/entities/CloudSite_1": "{\"o-ran-smo-teiv-cloud:CloudSite\":[{\"id\":\"CloudSite_1\",\"sourceIds\":[],\"attributes\":{\"geo-location\":null,\"name\":null}}]}", - "CLOUD/relationship-types/NODECLUSTER_LOCATED_AT_CLOUDSITE/relationships/relation_1": "{\"o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE\":[{\"bSide\":\"CloudSite_1\",\"aSide\":\"NodeCluster_1\",\"id\":\"relation_1\",\"sourceIds\":[]}]}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-one-to-many.json deleted file mode 100644 index 55b15db..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-one-to-many.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "RAN/entity-types/ENodeBFunction/entities/ENodeBFunction_1": "{\"o-ran-smo-teiv-ran:ENodeBFunction\":[{\"id\":\"ENodeBFunction_1\",\"sourceIds\":[],\"attributes\":{\"eNodeBPlmnId\":null,\"fdn\":null,\"eNBId\":null,\"cmId\":null},\"id\":\"ENodeBFunction_1\"}]}", - "OAM_TO_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships/relation_1": "{\"o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION\":[{\"bSide\":\"ENodeBFunction_1\",\"aSide\":\"ManagedElement_1\",\"id\":\"relation_1\",\"sourceIds\":[\"fdn_1\",\"cmHandleId_1\"]}]}", - "OAM/entity-types/ManagedElement/entities/ManagedElement_1": "{\"o-ran-smo-teiv-oam:ManagedElement\":[{\"id\":\"ManagedElement_1\",\"sourceIds\":[],\"attributes\":{\"fdn\":null,\"cmId\":null}}]}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-relationship-connecting-same-entity.json deleted file mode 100644 index 08a8ef1..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-relationship-connecting-same-entity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships/many_to_many_relation_1": "{\"o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE\":[{\"bSide\":\"AntennaModule_2\",\"aSide\":\"AntennaModule_1\",\"id\":\"many_to_many_relation_1\",\"sourceIds\":[]}]}", - "EQUIPMENT/relationship-types/ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE/relationships/one_to_many_relation_1": "{\"o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE\":[{\"bSide\":\"AntennaModule_4\",\"aSide\":\"AntennaModule_3\",\"id\":\"one_to_many_relation_1\",\"sourceIds\":[]}]}", - "EQUIPMENT/relationship-types/ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE/relationships/one_to_one_relation_1": "{\"o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE\":[{\"bSide\":\"AntennaModule_6\",\"aSide\":\"AntennaModule_5\",\"id\":\"one_to_one_relation_1\",\"sourceIds\":[]}]}", - "EQUIPMENT/entity-types/AntennaModule/entities/AntennaModule_1": "{\"o-ran-smo-teiv-equipment:AntennaModule\":[{\"id\":\"AntennaModule_1\",\"sourceIds\":[],\"attributes\":{\"totalTilt\":null,\"mechanicalAntennaBearing\":null,\"fdn\":null,\"antennaModelNumber\":null,\"mechanicalAntennaTilt\":null,\"positionWithinSector\":null,\"cmId\":null,\"electricalAntennaTilt\":null}}]}", - "EQUIPMENT/entity-types/AntennaModule/entities/AntennaModule_2": "{\"o-ran-smo-teiv-equipment:AntennaModule\":[{\"id\":\"AntennaModule_2\",\"sourceIds\":[],\"attributes\":{\"totalTilt\":null,\"mechanicalAntennaBearing\":null,\"fdn\":null,\"antennaModelNumber\":null,\"mechanicalAntennaTilt\":null,\"positionWithinSector\":null,\"cmId\":null,\"electricalAntennaTilt\":null}}]}", - "EQUIPMENT/entity-types/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/entities/AntennaModule_3": "{\"o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\":[{\"attributes\":{\"fdn\":\"AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=21\"},\"id\":\"AntennaModule_3\",\"sourceIds\":[]}]}", - "EQUIPMENT/entity-types/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/entities/AntennaModule_4": "{\"o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\":[{\"attributes\":{\"fdn\":\"AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=22\"},\"id\":\"AntennaModule_4\",\"sourceIds\":[]}]}", - "EQUIPMENT/entity-types/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/entities/AntennaModule_5": "{\"o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\":[{\"attributes\":{\"fdn\":\"AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=31\"},\"id\":\"AntennaModule_5\",\"sourceIds\":[]}]}", - "EQUIPMENT/entity-types/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/entities/AntennaModule_6": "{\"o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\":[{\"attributes\":{\"fdn\":\"AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=32\"},\"id\":\"AntennaModule_6\",\"sourceIds\":[]}]}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-second-case.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-second-case.json deleted file mode 100644 index ac685fe..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-create-second-case.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "RAN/entity-types/NRCellDU/entities/NRCellDU_1": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_1\",\"sourceIds\":[],\"attributes\":{\"nCI\":1,\"nRTAC\":310,\"cellLocalId\":4589,\"nRPCI\":12,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1\"}}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_2": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_2\",\"sourceIds\":[],\"attributes\":{\"nCI\":2,\"nRTAC\":3101,\"cellLocalId\":45891,\"nRPCI\":121,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2\"}}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_3": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_3\",\"sourceIds\":[],\"attributes\":{\"nCI\":3,\"nRTAC\":301,\"cellLocalId\":469,\"nRPCI\":15,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CNA_SED_1": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CNA_SED_1\",\"sourceIds\":[],\"attributes\":{\"name\":\"CNA_1\"}}]}", - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_1": "{\"o-ran-smo-teiv-ran:GNBCUCPFunction\":[{\"id\":\"GNBCUCP_1\",\"sourceIds\":[],\"attributes\":{\"pLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBCUName\":\"Test_gNBCU\",\"gNBId\":123,\"gNBIdLength\":3,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_3": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_3\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_3\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_2": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_2\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_2\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_1": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_1\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_1\"}}]}", - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_SED_1": "{\"o-ran-smo-teiv-ran:GNBCUCPFunction\":[{\"id\":\"GNBCUCP_SED_1\",\"sourceIds\":[],\"attributes\":{\"pLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBCUName\":\"Test_sed_gNBCU\",\"gNBId\":123,\"gNBIdLength\":3,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1929103B15999999\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1\"}}]}", - "RAN/entity-types/GNBDUFunction/entities/GNBDU_1": "{\"o-ran-smo-teiv-ran:GNBDUFunction\":[{\"id\":\"GNBDU_1\",\"sourceIds\":[],\"attributes\":{\"dUpLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBDUId\":12,\"gNBId\":1234,\"gNBIdLength\":4,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]\"}}]}", - "RAN/entity-types/GNBCUUPFunction/entities/GNBCUUP_1": "{\"o-ran-smo-teiv-ran:GNBCUUPFunction\":[{\"id\":\"GNBCUUP_1\",\"sourceIds\":[],\"attributes\":{\"gNBId\":123,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1\",\"gNBIdLength\":3}}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_6": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_6\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_3": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_3\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_sed_2": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CNA_SED_1\",\"aSide\":\"GNBCUCP_SED_1\",\"id\":\"relation_sed_2\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_4": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_4\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_2": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_2\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_1": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_1\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_5": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_5\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_sed_1": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CNA_SED_1\",\"aSide\":\"GNBDU_SED_1\",\"id\":\"relation_sed_1\",\"sourceIds\":[]}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_1/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_1\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_7\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"}}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_2/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_2\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_8\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"}}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_3/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_3\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_9\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"}}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-many.json deleted file mode 100644 index 6b66aaa..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-many.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_3": { - - }, - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_1": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_1": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_5": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_3": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_6": { - - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-one.json deleted file mode 100644 index cc9c604..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-many-to-one.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "CLOUD/entity-types/NodeCluster/entities/NodeCluster_1": { - - }, - "CLOUD/entity-types/CloudSite/entities/CloudSite_1": { - - }, - "CLOUD/relationship-types/NODECLUSTER_LOCATED_AT_CLOUDSITE/relationships/relation_1": { - - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-one-to-many.json deleted file mode 100644 index d8bc339..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-one-to-many.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "RAN/entity-types/ENodeBFunction/entities/ENodeBFunction_1": { - - }, - "OAM_TO_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships/relation_1": { - - }, - "OAM/entity-types/ManagedElement/entities/ManagedElement_1": { - - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-relationship-connecting-same-entity.json deleted file mode 100644 index 66c6280..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-delete-relationship-connecting-same-entity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "EQUIPMENT/entity-types/AntennaModule/entities/AntennaModule_1": { - - }, - "EQUIPMENT/entity-types/AntennaModule/entities/AntennaModule_2": { - - }, - "EQUIPMENT/relationship-types/ANTENNAMODULE_REALISED_BY_ANTENNAMODULE/relationships/many_to_many_relation_1": { - - }, - "EQUIPMENT/relationship-types/ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE/relationships/one_to_many_relation_1": { - - }, - "EQUIPMENT/relationship-types/ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE/relationships/one_to_one_relation_1": { - - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-merge-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-merge-one-to-many.json deleted file mode 100644 index 434b0b4..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-merge-one-to-many.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "RAN/entity-types/NRCellDU/entities/NRCellDU_1": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_1\",\"sourceIds\":[],\"attributes\":{\"nRPCI\":12,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1\",\"nCI\":1,\"nRTAC\":310,\"cellLocalId\":4589}}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_2": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_2\",\"sourceIds\":[],\"attributes\":{\"nRPCI\":121,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2\",\"nCI\":2,\"nRTAC\":3101,\"cellLocalId\":45891}}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_3": "{\"o-ran-smo-teiv-ran:NRCellDU\":[{\"id\":\"NRCellDU_3\",\"sourceIds\":[],\"attributes\":{\"nRPCI\":15,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3\",\"nCI\":3,\"nRTAC\":301,\"cellLocalId\":469}}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_6": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_6\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_3": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUCP_1\",\"id\":\"relation_3\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_1": "{\"o-ran-smo-teiv-ran:GNBCUCPFunction\":[{\"id\":\"GNBCUCP_1\",\"sourceIds\":[],\"attributes\":{\"gNBIdLength\":3,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1\",\"pLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBCUName\":\"Test_gNBCU\",\"gNBId\":123}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_3": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_3\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_3\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_2": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_2\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_2\"}}]}", - "CLOUD/entity-types/CloudNativeApplication/entities/CloudNativeApplication_1": "{\"o-ran-smo-teiv-cloud:CloudNativeApplication\":[{\"id\":\"CloudNativeApplication_1\",\"sourceIds\":[],\"attributes\":{\"name\":\"Test_CloudNativeApplication_1\"}}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_4": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_4\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBDUFunction/entities/GNBDU_1": "{\"o-ran-smo-teiv-ran:GNBDUFunction\":[{\"id\":\"GNBDU_1\",\"sourceIds\":[],\"attributes\":{\"gNBIdLength\":4,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]\",\"dUpLMNId\":{\"mcc\":\"110\",\"mnc\":\"210\"},\"gNBDUId\":12,\"gNBId\":1234}}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_2": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_2\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_2\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_1": "{\"o-ran-smo-teiv-cloud-to-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_1\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_1\",\"sourceIds\":[]}]}", - "CLOUD_TO_RAN/relationship-types/GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_5": "{\"o-ran-smo-teiv-cloud-to-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION\":[{\"bSide\":\"CloudNativeApplication_3\",\"aSide\":\"GNBCUUP_1\",\"id\":\"relation_5\",\"sourceIds\":[]}]}", - "RAN/entity-types/GNBCUUPFunction/entities/GNBCUUP_1": "{\"o-ran-smo-teiv-ran:GNBCUUPFunction\":[{\"id\":\"GNBCUUP_1\",\"sourceIds\":[],\"attributes\":{\"gNBId\":123,\"cmId\":{\"cmHandle\":\"395221E080CCF0FD1924103B15873814\",\"resourceIdentifier\":\"/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]\"},\"fdn\":\"SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1\",\"gNBIdLength\":3}}]}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_1/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_1\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_7\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_1\\/relationships?offset=0&limit=500\"}}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_2/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_2\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_8\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_2\\/relationships?offset=0&limit=500\"}}", - "RAN/entity-types/NRCellDU/entities/NRCellDU_3/relationships": "{\"next\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"last\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"prev\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"self\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"},\"totalCount\":1,\"items\":[{\"o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU\":[{\"bSide\":\"NRCellDU_3\",\"aSide\":\"GNBDU_1\",\"id\":\"relation_9\"}]}],\"first\":{\"href\":\"\\/domains\\/RAN\\/entity-types\\/NRCellDU\\/entities\\/NRCellDU_3\\/relationships?offset=0&limit=500\"}}" -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-source-entity-delete-cm-handle.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-source-entity-delete-cm-handle.json deleted file mode 100644 index 5828231..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/api/exp-source-entity-delete-cm-handle.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "RAN/entity-types/GNBDUFunction/entities/GNBDU_SED_1": { - - }, - "RAN/entity-types/GNBCUCPFunction/entities/GNBCUCP_SED_1": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_sed_1": { - - }, - "CLOUD_TO_RAN/relationship-types/GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION/relationships/relation_sed_2": { - - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-many.json deleted file mode 100644 index d2a873a..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-many.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "entity_map_CNA_1": { - "id": "CloudNativeApplication_1", - "name": "Test_CloudNativeApplication_1" - }, - "entity_map_CNA_2": { - "id": "CloudNativeApplication_2", - "name": "Test_CloudNativeApplication_2" - }, - "entity_map_CNA_3": { - "id": "CloudNativeApplication_3", - "name": "Test_CloudNativeApplication_3" - }, - "entity_map_GNBDU_1": { - "id": "GNBDU_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1", - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - }, - "gNBDUId": 111, - "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" - } - }, - "entity_map_GNBCUUP_1": { - "id": "GNBCUUP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", - "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" - } - }, - "entity_map_GNBCUCP_1": { - "id": "GNBCUCP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", - "gNBCUName": "Test_gNBCU", - "gNBId": 123, - "gNBIdLength": 3, - "pLMNId": { - "mcc": "110", - "mnc": "210" - }, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" - } - }, - "relation_map_GNBDU_CNA_1": { - "id": "relation_1", - "aSide_GNBDUFunction": "GNBDU_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_1" - }, - "relation_map_GNBCUUP_CNA_2": { - "id": "relation_2", - "aSide_GNBCUUPFunction": "GNBCUUP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUCP_CNA_3": { - "id": "relation_3", - "aSide_GNBCUCPFunction": "GNBCUCP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_3" - }, - "relation_map_GNBDU_CNA_4": { - "id": "relation_4", - "aSide_GNBDUFunction": "GNBDU_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUUP_CNA_5": { - "id": "relation_5", - "aSide_GNBCUUPFunction": "GNBCUUP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_3" - }, - "relation_map_GNBCUCP_CNA_6": { - "id": "relation_6", - "aSide_GNBCUCPFunction": "GNBCUCP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_1" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one2.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one2.json deleted file mode 100644 index e9337b0..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one2.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "entity_map_NRSectorCarrier_1": { - "id": "NRSectorCarrier_1" - }, - "entity_map_AntennaCapability_1": { - "id": "AntennaCapability_1", - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" - } - }, - "relation_map_NRSC_AC_1": { - "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY": "relation_1", - "id": "NRSectorCarrier_1", - "REL_FK_used-antennaCapability": "AntennaCapability_1" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one3.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one3.json deleted file mode 100644 index bbe2ca7..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one3.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "entity_map_NRSectorCarrier_1": { - "id": "NRSectorCarrier_1" - }, - "entity_map_AntennaCapability_1": { - "id": "AntennaCapability_1" - }, - "relation_map_NRSC_AC_1": { - "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY": "relation_1", - "id": "NRSectorCarrier_1", - "REL_FK_used-antennaCapability": "AntennaCapability_1" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one5.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one5.json deleted file mode 100644 index 6c49856..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-many-to-one5.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "entity_map_AntennaCapability_2": { - "id": "AntennaCapability_2", - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" - } - }, - "relation_map_NRSC_AC_2": { - "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY": "relation_2", - "id": "NRSectorCarrier_2", - "REL_FK_used-antennaCapability": "AntennaCapability_2" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-one-to-one.json deleted file mode 100644 index aeb6ab3..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-one-to-one.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "entity_map_CNS_1": { - "id": "CloudNativeSystem_2" - }, - "entity_map_ME_1": { - "id": "ManagedElement_2", - "REL_FK_deployed-as-cloudNativeSystem": "CloudNativeSystem_2", - "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": "relation_11" - }, - "entity_map_CNS_2": { - "id": "CloudNativeSystem_3" - }, - "entity_map_ME_2": { - "id": "ManagedElement_3", - "REL_FK_deployed-as-cloudNativeSystem": "CloudNativeSystem_3", - "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": "relation_12" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-second-case.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-second-case.json deleted file mode 100644 index 8e8a229..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-create-second-case.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "entity_map_CNA_1": { - "id": "CloudNativeApplication_1", - "name": "Test_CloudNativeApplication_1" - }, - "entity_map_CNA_2": { - "id": "CloudNativeApplication_2", - "name": "Test_CloudNativeApplication_2" - }, - "entity_map_CNA_3": { - "id": "CloudNativeApplication_3", - "name": "Test_CloudNativeApplication_3" - }, - "entity_map_CNA_4": { - "id": "CNA_SED_1", - "name": "CNA_1" - }, - "entity_map_GNBDU_1": { - "id": "GNBDU_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - }, - "gNBDUId": 12, - "gNBId": 1234, - "gNBIdLength": 4, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" - } - }, - "entity_map_GNBDU_2": { - "id": "GNBDU_SED_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - }, - "gNBDUId": 111, - "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1929103B15999999", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" - } - }, - "entity_map_GNBCUUP_1": { - "id": "GNBCUUP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", - "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" - } - }, - "entity_map_GNBCUCP_1": { - "id": "GNBCUCP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", - "gNBCUName": "Test_gNBCU", - "gNBId": 123, - "gNBIdLength": 3, - "pLMNId": { - "mcc": "110", - "mnc": "210" - }, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" - } - }, - "entity_map_GNBCUCP_2": { - "id": "GNBCUCP_SED_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", - "gNBCUName": "Test_sed_gNBCU", - "gNBId": 123, - "gNBIdLength": 3, - "pLMNId": { - "mcc": "110", - "mnc": "210" - }, - "cmId": { - "cmHandle": "395221E080CCF0FD1929103B15999999", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" - } - }, - "entity_map_NRCellDU_1": { - "id": "NRCellDU_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", - "cellLocalId": 4589, - "nCI": 1, - "nRPCI": 12, - "nRTAC": 310, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" - } - }, - "entity_map_NRCellDU_2": { - "id": "NRCellDU_2", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", - "cellLocalId": 45891, - "nCI": 2, - "nRPCI": 121, - "nRTAC": 3101, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" - } - }, - "entity_map_NRCellDU_3": { - "id": "NRCellDU_3", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", - "cellLocalId": 469, - "nCI": 3, - "nRPCI": 15, - "nRTAC": 301, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" - } - }, - "relation_map_GNBDU_CNA_1": { - "id": "relation_1", - "aSide_GNBDUFunction": "GNBDU_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_1" - }, - "relation_map_GNBCUUP_CNA_2": { - "id": "relation_2", - "aSide_GNBCUUPFunction": "GNBCUUP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUCP_CNA_3": { - "id": "relation_3", - "aSide_GNBCUCPFunction": "GNBCUCP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_3" - }, - "relation_map_GNBDU_CNA_4": { - "id": "relation_4", - "aSide_GNBDUFunction": "GNBDU_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUUP_CNA_5": { - "id": "relation_5", - "aSide_GNBCUUPFunction": "GNBCUUP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_3" - }, - "relation_map_GNBCUCP_CNA_6": { - "id": "relation_6", - "aSide_GNBCUCPFunction": "GNBCUCP_1", - "bSide_CloudNativeApplication": "CloudNativeApplication_1" - }, - "relation_map_GNBDU_NRCellDU_1": { - "id": "NRCellDU_1", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_7" - }, - "relation_map_GNBDU_NRCellDU_2": { - "id": "NRCellDU_2", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_8" - }, - "relation_map_GNBDU_NRCellDU_3": { - "id": "NRCellDU_3", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_9" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-delete-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-delete-one-to-one.json deleted file mode 100644 index daad7a1..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-delete-one-to-one.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "entity_map_CNS_1": { - "id": "CloudNativeSystem_2", - "REL_FK_deployed-managedElement": null - }, - "entity_map_CNS_2": { - "id": "CloudNativeSystem_3", - "REL_FK_deployed-managedElement": null - }, - "entity_map_ME_2": { - "id": "ManagedElement_3", - "REL_FK_deployed-as-cloudNativeSystem": null, - "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": null - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-merge-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-merge-one-to-many.json deleted file mode 100644 index c889cf2..0000000 --- a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/db/exp-merge-one-to-many.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "entity_map_CNA_1": { - "id": "CloudNativeApplication_1", - "name": "Test_CloudNativeApplication_1" - }, - "entity_map_CNA_2": { - "id": "CloudNativeApplication_2", - "name": "Test_CloudNativeApplication_2" - }, - "entity_map_CNA_3": { - "id": "CloudNativeApplication_3", - "name": "Test_CloudNativeApplication_3" - }, - "entity_map_GNBDU_1": { - "id": "GNBDU_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - }, - "gNBDUId": 12, - "gNBId": 1234, - "gNBIdLength": 4, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" - } - }, - "entity_map_GNBCUUP_1": { - "id": "GNBCUUP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", - "gNBId": 123, - "gNBIdLength": 3, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" - } - }, - "entity_map_GNBCUCP_1": { - "id": "GNBCUCP_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", - "gNBCUName": "Test_gNBCU", - "gNBId": 123, - "gNBIdLength": 3, - "pLMNId": { - "mcc": "110", - "mnc": "210" - }, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" - } - }, - "entity_map_NRCellDU_1": { - "id": "NRCellDU_1", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", - "cellLocalId": 4589, - "nCI": 1, - "nRPCI": 12, - "nRTAC": 310, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" - } - }, - "entity_map_NRCellDU_2": { - "id": "NRCellDU_2", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", - "cellLocalId": 45891, - "nCI": 2, - "nRPCI": 121, - "nRTAC": 3101, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" - } - }, - "entity_map_NRCellDU_3": { - "id": "NRCellDU_3", - "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", - "cellLocalId": 469, - "nCI": 3, - "nRPCI": 15, - "nRTAC": 301, - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873814", - "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" - } - }, - "relation_map_GNBDU_CNA_1": { - "id": "relation_1", - "gnbdufunction": "GNBDU_1", - "cloudnativeapplication": "CloudNativeApplication_1" - }, - "relation_map_GNBCUUP_CNA_2": { - "id": "relation_2", - "gnbcuupfunction": "GNBCUUP_1", - "cloudnativeapplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUCP_CNA_3": { - "id": "relation_3", - "gnbcucpfunction": "GNBCUCP_1", - "cloudnativeapplication": "CloudNativeApplication_3" - }, - "relation_map_GNBDU_CNA_4": { - "id": "relation_4", - "gnbdufunction": "GNBDU_1", - "cloudnativeapplication": "CloudNativeApplication_2" - }, - "relation_map_GNBCUUP_CNA_5": { - "id": "relation_5", - "gnbcuupfunction": "GNBCUUP_1", - "cloudnativeapplication": "CloudNativeApplication_3" - }, - "relation_map_GNBCUCP_CNA_6": { - "id": "relation_6", - "gnbcucpfunction": "GNBCUCP_1", - "cloudnativeapplication": "CloudNativeApplication_1" - }, - "relation_map_GNBDU_NRCellDU_1": { - "id": "NRCellDU_1", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_7" - }, - "relation_map_GNBDU_NRCellDU_2": { - "id": "NRCellDU_2", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_8" - }, - "relation_map_GNBDU_NRCellDU_3": { - "id": "NRCellDU_3", - "REL_FK_provided-by-gnbduFunction": "GNBDU_1", - "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_9" - }, - "relation_map_GNBDU_NRCellDU_REL_7": { - "id": "relation_7", - "gnbdufunction": "GNBDU_1", - "nrcelldu": "NRCellDU_1" - }, - "relation_map_GNBDU_NRCellDU_REL_8": { - "id": "relation_8", - "gnbdufunction": "GNBDU_1", - "nrcelldu": "NRCellDU_2" - }, - "relation_map_GNBDU_NRCellDU_REL_9": { - "id": "relation_9", - "gnbdufunction": "GNBDU_1", - "nrcelldu": "NRCellDU_3" - } -} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-many-to-many.json new file mode 100644 index 0000000..78dfb9a --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-many-to-many.json @@ -0,0 +1,98 @@ +{ + "e01fcb87ad2c34ce66c34420255e25aaca270e5e": [ + { + "id": "CloudNativeApplication_1", + "name": "Test_CloudNativeApplication_1" + }, + { + "id": "CloudNativeApplication_2", + "name": "Test_CloudNativeApplication_2" + }, + { + "id": "CloudNativeApplication_3", + "name": "Test_CloudNativeApplication_3" + } + ], + "o-ran-smo-teiv-ran-logical_GNBDUFunction": [ + { + "id": "GNBDU_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 111, + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + ], + "8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb": [ + { + "id": "GNBCUUP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" + } + } + ], + "c4a425179d3089b5288fdf059079d0ea26977f0f": [ + { + "id": "GNBCUCP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", + "gNBCUName": "Test_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + } + ], + "10484f157f490eb5b27e40dbfaf4d5f2be17c57c": [ + { + "id": "relation_1", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + }, + { + "id": "relation_4", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + } + ], + "70a4a84bca01ea022ab24d8cb82422c572922675": [ + { + "id": "relation_2", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + }, + { + "id": "relation_5", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + } + ], + "7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7": [ + { + "id": "relation_3", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + }, + { + "id": "relation_6", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + } + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-one-to-one.json new file mode 100644 index 0000000..dd9ccd1 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-one-to-one.json @@ -0,0 +1,22 @@ +{ + "163276fa439cdfccabb80f7acacb6fa638e8d314": [ + { + "id": "CloudNativeSystem_2" + }, + { + "id": "CloudNativeSystem_3" + } + ], + "o-ran-smo-teiv-ran-oam_ManagedElement": [ + { + "id": "ManagedElement_2", + "REL_FK_deployed-as-cloudNativeSystem": "CloudNativeSystem_2", + "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": "relation_11" + }, + { + "id": "ManagedElement_3", + "REL_FK_deployed-as-cloudNativeSystem": "CloudNativeSystem_3", + "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": "relation_12" + } + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-second-case.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-second-case.json new file mode 100644 index 0000000..23c9633 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-create-second-case.json @@ -0,0 +1,185 @@ +{ + "e01fcb87ad2c34ce66c34420255e25aaca270e5e": [ + { + "id": "CloudNativeApplication_1", + "name": "Test_CloudNativeApplication_1" + }, + { + "id": "CloudNativeApplication_2", + "name": "Test_CloudNativeApplication_2" + }, + { + "id": "CloudNativeApplication_3", + "name": "Test_CloudNativeApplication_3" + }, + { + "id": "CNA_SED_1", + "name": "CNA_1" + } + ], + "o-ran-smo-teiv-ran-logical_GNBDUFunction": [ + { + "id": "GNBDU_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + }, + { + "id": "GNBDU_SED_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 111, + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1929103B15999999", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + ], + "8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb": [ + { + "id": "GNBCUUP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" + } + } + ], + "c4a425179d3089b5288fdf059079d0ea26977f0f": [ + { + "id": "GNBCUCP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", + "gNBCUName": "Test_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + }, + { + "id": "GNBCUCP_SED_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", + "gNBCUName": "Test_sed_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1929103B15999999", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + } + ], + "o-ran-smo-teiv-ran-logical_NRCellDU": [ + { + "id": "NRCellDU_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", + "cellLocalId": 4589, + "nCI": 1, + "nRPCI": 12, + "nRTAC": 310, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" + } + }, + { + "id": "NRCellDU_2", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", + "cellLocalId": 45891, + "nCI": 2, + "nRPCI": 121, + "nRTAC": 3101, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" + } + }, + { + "id": "NRCellDU_3", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", + "cellLocalId": 469, + "nCI": 3, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" + } + }, + { + "id": "NRCellDU_1", + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_7" + }, + { + "id": "NRCellDU_2", + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_8" + }, + { + "id": "NRCellDU_3", + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_9" + } + ], + "10484f157f490eb5b27e40dbfaf4d5f2be17c57c": [ + { + "id": "relation_1", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + }, + { + "id": "relation_4", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + } + ], + "70a4a84bca01ea022ab24d8cb82422c572922675": [ + { + "id": "relation_2", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + }, + { + "id": "relation_5", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + } + ], + "7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7": [ + { + "id": "relation_3", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + }, + { + "id": "relation_6", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + } + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-delete-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-delete-one-to-one.json new file mode 100644 index 0000000..ea66a96 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-delete-one-to-one.json @@ -0,0 +1,19 @@ +{ + "163276fa439cdfccabb80f7acacb6fa638e8d314": [ + { + "id": "CloudNativeSystem_2", + "REL_FK_deployed-managedElement": null + }, + { + "id": "CloudNativeSystem_3", + "REL_FK_deployed-managedElement": null + } + ], + "o-ran-smo-teiv-ran-oam_ManagedElement": [ + { + "id": "ManagedElement_3", + "REL_FK_deployed-as-cloudNativeSystem": null, + "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": null + } + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-merge-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-merge-one-to-many.json new file mode 100644 index 0000000..ef104e4 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/exp-merge-one-to-many.json @@ -0,0 +1,142 @@ +{ + "e01fcb87ad2c34ce66c34420255e25aaca270e5e": [ + { + "id": "CloudNativeApplication_1", + "name": "Test_CloudNativeApplication_1" + }, + { + "id": "CloudNativeApplication_2", + "name": "Test_CloudNativeApplication_2" + }, + { + "id": "CloudNativeApplication_3", + "name": "Test_CloudNativeApplication_3" + } + ], + "o-ran-smo-teiv-ran-logical_GNBDUFunction": [ + { + "id": "GNBDU_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + ], + "8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb": [ + { + "id": "GNBCUUP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" + } + } + ], + "c4a425179d3089b5288fdf059079d0ea26977f0f": [ + { + "id": "GNBCUCP_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", + "gNBCUName": "Test_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + } + ], + "o-ran-smo-teiv-ran-logical_NRCellDU": [ + { + "id": "NRCellDU_1", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", + "cellLocalId": 4589, + "nCI": 1, + "nRPCI": 12, + "nRTAC": 310, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" + }, + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_7" + }, + { + "id": "NRCellDU_2", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", + "cellLocalId": 45891, + "nCI": 2, + "nRPCI": 121, + "nRTAC": 3101, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" + }, + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_8" + }, + { + "id": "NRCellDU_3", + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", + "cellLocalId": 469, + "nCI": 3, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" + }, + "REL_FK_provided-by-gnbduFunction": "GNBDU_1", + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU": "relation_9" + } + ], + "10484f157f490eb5b27e40dbfaf4d5f2be17c57c": [ + { + "id": "relation_1", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + }, + { + "id": "relation_4", + "aSide_GNBDUFunction": "GNBDU_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + } + ], + "70a4a84bca01ea022ab24d8cb82422c572922675": [ + { + "id": "relation_2", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_2" + }, + { + "id": "relation_5", + "aSide_GNBCUUPFunction": "GNBCUUP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + } + ], + "7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7": [ + { + "id": "relation_3", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_3" + }, + { + "id": "relation_6", + "aSide_GNBCUCPFunction": "GNBCUCP_1", + "bSide_CloudNativeApplication": "CloudNativeApplication_1" + } + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-many-to-many.json new file mode 100644 index 0000000..731edaf --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-many-to-many.json @@ -0,0 +1,18 @@ +{ + "e01fcb87ad2c34ce66c34420255e25aaca270e5e": [ + "CloudNativeApplication_3" + ], + "c4a425179d3089b5288fdf059079d0ea26977f0f": [ + "GNBCUCP_1" + ], + "10484f157f490eb5b27e40dbfaf4d5f2be17c57c": [ + "relation_1" + ], + "70a4a84bca01ea022ab24d8cb82422c572922675": [ + "relation_5" + ], + "7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7": [ + "relation_3", + "relation_6" + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-one-to-one.json new file mode 100644 index 0000000..b1d9a08 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-delete-one-to-one.json @@ -0,0 +1,11 @@ +{ + "163276fa439cdfccabb80f7acacb6fa638e8d314": [ + "relation_11", + "relation_12" + ], + "o-ran-smo-teiv-ran-oam_ManagedElement": [ + "ManagedElement_2", + "relation_11", + "relation_12" + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-source-entity-delete-cm-handle.json b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-source-entity-delete-cm-handle.json new file mode 100644 index 0000000..b6d5349 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/expected-results/not-exp-source-entity-delete-cm-handle.json @@ -0,0 +1,15 @@ +{ + "o-ran-smo-teiv-ran-logical_GNBDUFunction": [ + "GNBDU_SED_1" + ], + "c4a425179d3089b5288fdf059079d0ea26977f0f": [ + "GNBCUCP_SED_1", + "GNBCUCP_SED_2" + ], + "7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7": [ + "relation_sed_1" + ], + "10484f157f490eb5b27e40dbfaf4d5f2be17c57c": [ + "relation_sed_2" + ] +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-geo-location.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-geo-location.json new file mode 100644 index 0000000..656b5d4 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-geo-location.json @@ -0,0 +1,31 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f1113", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": { + "o-ran-smo-teiv-cloud:CloudSite": [ + { + "id": "CloudSite1", + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ], + "attributes": { + "name": "geo-location1", + "geo-location": { + "location": { + "latitude": 12.78232, + "longitude": 56.7455 + } + } + } + } + ] + } + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-many.json new file mode 100644 index 0000000..99507d6 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-many.json @@ -0,0 +1,137 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0001", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-cloud:CloudNativeApplication": [ + { + "id": "CloudNativeApplication_1", + "attributes": { + "name": "Test_CloudNativeApplication_1" + } + }, + { + "id": "CloudNativeApplication_2", + "attributes": { + "name": "Test_CloudNativeApplication_2" + } + }, + { + "id": "CloudNativeApplication_3", + "attributes": { + "name": "Test_CloudNativeApplication_3" + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "GNBDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 111, + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "GNBCUUP_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUUPFunction=1", + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUUPFunction]/o-ran-smo-GNBCUUP:GNBCUUPFunction[@id=1]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "id": "GNBCUCP_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,GNBCUCPFunction=1", + "gNBCUName": "Test_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=GNBCUCPFunction]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_1", + "aSide": "GNBDU_1", + "bSide": "CloudNativeApplication_1" + }, + { + "id": "relation_4", + "aSide": "GNBDU_1", + "bSide": "CloudNativeApplication_2" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_2", + "aSide": "GNBCUUP_1", + "bSide": "CloudNativeApplication_2" + }, + { + "id": "relation_5", + "aSide": "GNBCUUP_1", + "bSide": "CloudNativeApplication_3" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_3", + "aSide": "GNBCUCP_1", + "bSide": "CloudNativeApplication_3" + }, + { + "id": "relation_6", + "aSide": "GNBCUCP_1", + "bSide": "CloudNativeApplication_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-one.json new file mode 100644 index 0000000..2729d70 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-many-to-one.json @@ -0,0 +1,76 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-cloud:NodeCluster": [ + { + "id": "NodeCluster_1", + "attributes": { + + } + } + ] + }, + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "AntennaCapability_1", + "attributes": { + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873820", + "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:NRSectorCarrier": [ + { + "id": "NRSectorCarrier_1", + "attributes": { + + } + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudSite": [ + { + "id": "CloudSite_1", + "attributes": { + + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ + { + "id": "relation_1", + "aSide": "NodeCluster_1", + "bSide": "CloudSite_1" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "relation_10", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-many.json new file mode 100644 index 0000000..45e422b --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-many.json @@ -0,0 +1,56 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_1", + "attributes": { + + }, + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] + } + ] + }, + { + "o-ran-smo-teiv-ran:ENodeBFunction": [ + { + "id": "ENodeBFunction_1", + "attributes": { + + }, + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ + { + "id": "relation_1", + "aSide": "ManagedElement_1", + "bSide": "ENodeBFunction_1", + "sourceIds": [ + "fdn_1", + "cmHandleId_1" + ] + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-one.json new file mode 100644 index 0000000..4c4cdb1 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-one-to-one.json @@ -0,0 +1,61 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_2", + "attributes": { + + } + }, + { + "id": "ManagedElement_3", + "attributes": { + + } + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + { + "id": "CloudNativeSystem_2", + "attributes": { + + } + }, + { + "id": "CloudNativeSystem_3", + "attributes": { + + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "relation_11", + "aSide": "ManagedElement_2", + "bSide": "CloudNativeSystem_2" + }, + { + "id": "relation_12", + "aSide": "ManagedElement_3", + "bSide": "CloudNativeSystem_3" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-relationship-connecting-same-entity.json new file mode 100644 index 0000000..a411b47 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-relationship-connecting-same-entity.json @@ -0,0 +1,86 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0100", + "source": "dmi-plugin:nm-1", + "type": "ran-equipment-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "AntennaModule_1", + "attributes": { + + } + }, + { + "id": "AntennaModule_2", + "attributes": { + + } + } + ] + }, + { + "o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + { + "id": "AntennaModule_3", + "attributes": { + "fdn": "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=21" + } + }, + { + "id": "AntennaModule_4", + "attributes": { + "fdn": "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=22" + } + }, + { + "id": "AntennaModule_5", + "attributes": { + "fdn": "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=31" + } + }, + { + "id": "AntennaModule_6", + "attributes": { + "fdn": "AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=32" + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-equipment:ANTENNAMODULE_REALISED_BY_ANTENNAMODULE": [ + { + "id": "many_to_many_relation_1", + "aSide": "AntennaModule_1", + "bSide": "AntennaModule_2" + } + ] + }, + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "one_to_many_relation_1", + "aSide": "AntennaModule_3", + "bSide": "AntennaModule_4" + } + ] + }, + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "one_to_one_relation_1", + "aSide": "AntennaModule_5", + "bSide": "AntennaModule_6" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-second-case.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-second-case.json new file mode 100644 index 0000000..0abdcfa --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-create-second-case.json @@ -0,0 +1,114 @@ +{ + "specversion": "1.0", + "id": "26504e8e-838e-11ee-b962-0242ac120002", + "source": "dmi-plugin:nm-3", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:CloudNativeApplication": [ + { + "id": "CNA_SED_1", + "attributes": { + "name": "CNA_1" + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "GNBDU_SED_1", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBDUFunction=1", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 111, + "gNBId": 123, + "gNBIdLength": 3, + "cmId": { + "cmHandle": "395221E080CCF0FD1929103B15999999", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "id": "GNBCUCP_SED_1", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=1", + "gNBCUName": "Test_sed_gNBCU", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1929103B15999999", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=1]" + } + } + }, + { + "id": "GNBCUCP_SED_2", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=2", + "urn:cmHandle:395221E080CCF0FD1929103B15999999" + ], + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00009,ManagedElement=NR01gNodeBRadio00009,GNBCUCPFunction=2", + "gNBCUName": "Test_sed_gNBCU2", + "gNBId": 123, + "gNBIdLength": 3, + "pLMNId": { + "mcc": "110", + "mnc": "210" + }, + "cmId": { + "cmHandle": "395221E080CCF0FD1929103B15999999", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00009]/o-ran-smo-GNBCUCP:GNBCUCPFunction[@id=2]" + } + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_sed_1", + "aSide": "GNBDU_SED_1", + "bSide": "CNA_SED_1" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_sed_2", + "aSide": "GNBCUCP_SED_1", + "bSide": "CNA_SED_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-managed-element.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-managed-element.json new file mode 100644 index 0000000..6083b31 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-managed-element.json @@ -0,0 +1,20 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-many.json new file mode 100644 index 0000000..8b5797b --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-many.json @@ -0,0 +1,36 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran:CloudNativeApplication": [ + { + "id": "CloudNativeApplication_3" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "id": "GNBCUCP_1" + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION": [ + { + "id": "relation_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-one.json new file mode 100644 index 0000000..6ba8fc8 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-many-to-one.json @@ -0,0 +1,36 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-cloud:NodeCluster": [ + { + "id": "NodeCluster_1" + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudSite": [ + { + "id": "CloudSite_1" + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-cloud:NODECLUSTER_LOCATED_AT_CLOUDSITE": [ + { + "id": "relation_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-many.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-many.json new file mode 100644 index 0000000..b3d93ee --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-many.json @@ -0,0 +1,36 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_1" + } + ] + }, + { + "o-ran-smo-teiv-ran:ENodeBFunction": [ + { + "id": "ENodeBFunction_1" + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-oam-to-logical:MANAGEDELEMENT_MANAGES_ENODEBFUNCTION": [ + { + "id": "relation_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-one.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-one.json new file mode 100644 index 0000000..ccd5081 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-one-to-one.json @@ -0,0 +1,29 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_2" + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "relation_12" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-relationship-connecting-same-entity.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-relationship-connecting-same-entity.json new file mode 100644 index 0000000..e4844a0 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-delete-relationship-connecting-same-entity.json @@ -0,0 +1,39 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0103", + "source": "dmi-plugin:nm-1", + "type": "ran-equipment-topology.delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "AntennaModule_1" + }, + { + "id": "AntennaModule_2" + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "one_to_many_relation_1" + } + ] + }, + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "one_to_one_relation_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-long-names.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-long-names.json new file mode 100644 index 0000000..ee90fb1 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-long-names.json @@ -0,0 +1,364 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0002", + "source": "dmi-plugin:nm-1", + "type": "ties.merge", + "time": "2023-10-25T13:30:12Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology-yang", + "data": { + "entities": [ + { + "o-ran-smo-teiv-cloud:Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + { + "id": "Namespace_1", + "attributes": { + "name": "Namespace_1" + } + }, + { + "id": "Namespace_2", + "attributes": { + "name": "Namespace_2" + } + } + ] + }, + { + "o-ran-smo-teiv-oam:ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt": [ + { + "id": "ManagedElement_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001", + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]" + } + } + }, + { + "id": "ManagedElement_2", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00002,ManagedElement=NR01gNodeBRadio00002", + "cmId": { + "cmHandle": "F0FD1924103B15873814395221E080CC", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00002]" + } + } + }, + { + "id": "ManagedElement_3", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00003,ManagedElement=NR01gNodeBRadio00003", + "cmId": { + "cmHandle": "B15873F0FD192410381439E080CC5221", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00003]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm": [ + { + "id": "CloudNativeSystem_1", + "attributes": { + "name": "Test_CloudNativeSystem_1" + } + }, + { + "id": "CloudNativeSystem_2", + "attributes": { + "name": "Test_CloudNativeSystem_2" + } + }, + { + "id": "CloudNativeSystem_3", + "attributes": { + "name": "Test_CloudNativeSystem_3" + } + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ + { + "id": "CloudNativeApplication_1", + "attributes": { + "name": "Test_CloudNativeApplication_1" + } + }, + { + "id": "CloudNativeApplication_2", + "attributes": { + "name": "Test_CloudNativeApplication_2" + } + }, + { + "id": "CloudNativeApplication_3", + "attributes": { + "name": "Test_CloudNativeApplication_3" + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": [ + { + "id": "GNBDUFunction_1", + "attributes": { + "fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + }, + { + "id": "GNBDUFunction_2", + "attributes": { + "fdnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=2", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=2]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU": [ + { + "id": "NRCellDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1,NRCellDU=1", + "cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd": 4589, + "nCI": 1, + "nRPCI": 12, + "nRTAC": 310, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" + } + } + }, + { + "id": "NRCellDU_2", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1,NRCellDU=2", + "cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd": 45891, + "nCI": 2, + "nRPCI": 121, + "nRTAC": 3101, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" + } + } + }, + { + "id": "NRCellDU_3", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=1,NRCellDU=3", + "cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd": 469, + "nCI": 3, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" + } + } + }, + { + "id": "NRCellDU_4", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction=2,NRCellDU=4", + "cellLocalIdddddddddddddddddddddddddddddddddddddddddddddddddddddd": 469, + "nCI": 4, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=2]/o-ran-smo-NRCellDU:NRCellDU[@id=4]" + } + } + } + ] + }, + { + "o-ran-smo-teiv-equipment:AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + { + "id": "AntennaModule_1", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=11" + } + }, + { + "id": "AntennaModule_2", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=12" + } + }, + { + "id": "AntennaModule_3", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=21" + } + }, + { + "id": "AntennaModule_4", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=22" + } + }, + { + "id": "AntennaModule_5", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=31" + } + }, + { + "id": "AntennaModule_6", + "attributes": { + "fdn": "SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=32" + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-cloud:CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE": [ + { + "id": "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE_relation_1", + "aSide": "CloudNativeApplication_1", + "bSide": "Namespace_1" + }, + { + "id": "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE_relation_2", + "aSide": "CloudNativeApplication_2", + "bSide": "Namespace_1" + }, + { + "id": "CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE_relation_3", + "aSide": "CloudNativeApplication_3", + "bSide": "Namespace_2" + } + ] + }, + { + "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM": [ + { + "id": "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_relation_1", + "aSide": "ManagedElement_1", + "bSide": "CloudNativeSystem_1" + }, + { + "id": "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_relation_2", + "aSide": "ManagedElement_2", + "bSide": "CloudNativeSystem_2" + }, + { + "id": "MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM_relation_3", + "aSide": "ManagedElement_3", + "bSide": "CloudNativeSystem_3" + } + ] + }, + { + "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN": [ + { + "id": "MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_1", + "aSide": "ManagedElement_1", + "bSide": "CloudNativeApplication_1" + } + ] + }, + { + "o-ran-smo-teiv-ran-to-cloud:GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN": [ + { + "id": "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_1", + "aSide": "GNBDUFunction_1", + "bSide": "CloudNativeApplication_1" + }, + { + "id": "GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_relation_2", + "aSide": "GNBDUFunction_1", + "bSide": "CloudNativeApplication_2" + } + ] + }, + { + "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN": [ + { + "id": "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION_relation_1", + "aSide": "ManagedElement_1", + "bSide": "GNBDUFunction_1" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU": [ + { + "id": "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_1", + "aSide": "GNBDUFunction_1", + "bSide": "NRCellDU_1" + }, + { + "id": "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_2", + "aSide": "GNBDUFunction_1", + "bSide": "NRCellDU_2" + }, + { + "id": "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_3", + "aSide": "GNBDUFunction_1", + "bSide": "NRCellDU_3" + }, + { + "id": "GNBDUFUNCTION_PROVIDES_NRCELLDU_relation_4", + "aSide": "GNBDUFunction_2", + "bSide": "NRCellDU_4" + } + ] + }, + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_relation_1", + "aSide": "AntennaModule_1", + "bSide": "AntennaModule_2" + }, + { + "id": "ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_relation_2", + "aSide": "AntennaModule_3", + "bSide": "AntennaModule_4" + } + ] + }, + { + "o-ran-smo-teiv-equipment:ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE": [ + { + "id": "ANTENNAMODULE_DEPLOYED_ON_ANTENNAMODULE_relation_1", + "aSide": "AntennaModule_5", + "bSide": "AntennaModule_6" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many-deprecated-structure.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many-deprecated-structure.json new file mode 100644 index 0000000..b4d75c5 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many-deprecated-structure.json @@ -0,0 +1,95 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0002", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.merge", + "time": "2023-10-25T13:30:12Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "GNBDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,MeContext=NR01gNodeBRadio00001,ManagedElement=NR01gNodeBRadio00001,GNBDUFunction[@id=1]", + "dUpLMNId": { + "mcc": "110", + "mnc": "210" + }, + "gNBDUId": 12, + "gNBId": 1234, + "gNBIdLength": 4, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NR01gNodeBRadio00001]/o-ran-smo-GNBDU:GNBDUFunction[@id=1]" + } + } + } + ], + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "NRCellDU_1", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=1", + "cellLocalId": 4589, + "nCI": 1, + "nRPCI": 12, + "nRTAC": 310, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_1]/o-ran-smo-NRCellDU:NRCellDU[@id=1]" + } + } + }, + { + "id": "NRCellDU_2", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=2", + "cellLocalId": 45891, + "nCI": 2, + "nRPCI": 121, + "nRTAC": 3101, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_2]/o-ran-smo-NRCellDU:NRCellDU[@id=2]" + } + } + }, + { + "id": "NRCellDU_3", + "attributes": { + "fdn": "SubNetwork=Europe,SubNetwork=Ireland,NRCellDU=3", + "cellLocalId": 469, + "nCI": 3, + "nRPCI": 15, + "nRTAC": 301, + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873814", + "resourceIdentifier": "/o-ran-smo-ComTop:ManagedElement[@id=NRCellDU_3]/o-ran-smo-NRCellDU:NRCellDU[@id=3]" + } + } + } + ] + }, + "relationships": { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "id": "relation_7", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_1" + }, + { + "id": "relation_8", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_2" + }, + { + "id": "relation_9", + "aSide": "GNBDU_1", + "bSide": "NRCellDU_3" + } + ] + } + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many2.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many2.json new file mode 100644 index 0000000..9ab1302 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-merge-one-to-many2.json @@ -0,0 +1,86 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f1113", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.merge", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "id": "ManagedElement_1", + "attributes": { + + }, + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] + }, + { + "id": "ManagedElement_2", + "attributes": { + + }, + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] + } + ] + }, + { + "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + { + "id": "CloudNativeSystem_1", + "attributes": { + + }, + "sourceIds": [ + "urn:3gpp:dn:fdn1", + "urn:cmHandle:1234" + ] + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "GNBDU_1", + "attributes": { + "dUpLMNId": { + "mcc": 110, + "mnc": 210 + }, + "gNBDUId": 111, + "gNBId": 123, + "gNBIdLength": 3 + }, + "sourceIds": [ + "urn:3gpp:dn:/SubNetwork=Europe/SubNetwork=Ireland/MeContext=NR01gNodeBRadio00001/ManagedElement=NR01gNodeBRadio00001/GNBDUFunction=1", + "urn:cmHandle:/395221E080CCF0FD1924103B15873814" + ] + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "relation_1", + "aSide": "ManagedElement_1", + "bSide": "CloudNativeSystem_1", + "sourceIds": [ + "fdn_1", + "cmHandleId_1" + ] + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle.json new file mode 100644 index 0000000..6f5ce38 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle.json @@ -0,0 +1,13 @@ +{ + "specversion": "1.0", + "id": "063b0da2-8396-11ee-b962-0242ac120002", + "source": "dmi-plugin:nm-3", + "type": "ran-logical-topology.source-entity-delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/source-entity-delete", + "data": { + "type": "cmHandle", + "value": "395221E080CCF0FD1929103B15999999" + } +} diff --git a/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle2.json b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle2.json new file mode 100644 index 0000000..81dd6e0 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/end-to-end/olde2e/ce-source-entity-delete-cm-handle2.json @@ -0,0 +1,13 @@ +{ + "specversion": "1.0", + "id": "063b0da2-8396-11ee-b962-0242ac120002", + "source": "dmi-plugin:nm-3", + "type": "ran-logical-topology.source-entity-delete", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/source-entity-delete", + "data": { + "type": "cmHandle", + "value": "395221E080CCF0FD1924103B15873820" + } +} diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation.json new file mode 100644 index 0000000..b3e8e85 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation.json @@ -0,0 +1,54 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran-equipment:AntennaModule": [ + { + "id": "AntennaModule_1", + "attributes": { + "geo-location": { + "location": { + "latitude": 12.78232, + "longitude": 56.7455 + } + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran-equipment:Site": [ + { + "id": "Site_1", + "attributes": { + "geo-location": { + "location": { + "latitude": 12.78232, + "longitude": 56.7455 + } + } + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULE_INSTALLED_AT_SITE": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "AntennaModule_1", + "bSide": "Site_1" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation2.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation2.json new file mode 100644 index 0000000..48d6056 --- /dev/null +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one-geolocation2.json @@ -0,0 +1,39 @@ +{ + "specversion": "1.0", + "id": "a30e63c9-d29e-46ff-b99a-b63ed83f0003", + "source": "dmi-plugin:nm-1", + "type": "ran-logical-topology.create", + "time": "2023-10-25T13:30:01Z", + "datacontenttype": "application/json", + "dataschema": "https://ties:8080/schemas/v1/r1-topology", + "data": { + "entities": [ + { + "o-ran-smo-teiv-ran-equipment:Site": [ + { + "id": "Site_2", + "attributes": { + "geo-location": { + "location": { + "latitude": 12.78232, + "longitude": 56.7455 + } + } + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-equipment:ANTENNAMODULE_INSTALLED_AT_SITE": [ + { + "id": "Relation_ManyToOne_2", + "aSide": "AntennaModule_1", + "bSide": "Site_2" + } + ] + } + ] + } +} diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one.json index df95133..5491c10 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one.json @@ -7,35 +7,41 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:AntennaCapability": [ - { - "id": "AntennaCapability_1", - "attributes": { - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + "entities": [ + { + "o-ran-smo-teiv-ran-logical:AntennaCapability": [ + { + "id": "AntennaCapability_1", + "attributes": { + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873820", + "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + } } } - } - ], - "o-ran-smo-teiv-ran:NRSectorCarrier": [ - { - "id": "NRSectorCarrier_1", - "attributes": { + ] + }, + { + "o-ran-smo-teiv-ran-logical:NRSectorCarrier": [ + { + "id": "NRSectorCarrier_1", + "attributes": { + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_1" - } - ] - } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one2.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one2.json index 524818d..51805ba 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one2.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one2.json @@ -7,35 +7,41 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:AntennaCapability": [ - { - "id": "AntennaCapability_2", - "attributes": { - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + "entities": [ + { + "o-ran-smo-teiv-ran-logical:AntennaCapability": [ + { + "id": "AntennaCapability_2", + "attributes": { + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873820", + "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + } } } - } - ], - "o-ran-smo-teiv-ran:NRSectorCarrier": [ - { - "id": "NRSectorCarrier_2", - "attributes": { + ] + }, + { + "o-ran-smo-teiv-ran-logical:NRSectorCarrier": [ + { + "id": "NRSectorCarrier_2", + "attributes": { + } + } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_2" } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_2", - "bSide": "AntennaCapability_2" - } - ] - } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one3.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one3.json index 1e82283..c7086e3 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one3.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one3.json @@ -7,27 +7,31 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:AntennaCapability": [ - { - "id": "AntennaCapability_2", - "attributes": { - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + "entities": [ + { + "o-ran-smo-teiv-ran-logical:AntennaCapability": [ + { + "id": "AntennaCapability_2", + "attributes": { + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873820", + "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + } } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_2", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_2" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_2", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one4.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one4.json index 402a2ae..97f2f56 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one4.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one4.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_2" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one5.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one5.json index c3e131e..8c0e59d 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one5.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one5.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:NRSectorCarrier": [ - { - "id": "NRSectorCarrier_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-logical:NRSectorCarrier": [ + { + "id": "NRSectorCarrier_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one6.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one6.json index 4404948..7cdb75b 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one6.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one6.json @@ -7,27 +7,31 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:AntennaCapability": [ - { - "id": "AntennaCapability_1", - "attributes": { - "cmId": { - "cmHandle": "395221E080CCF0FD1924103B15873820", - "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + "entities": [ + { + "o-ran-smo-teiv-ran-logical:AntennaCapability": [ + { + "id": "AntennaCapability_1", + "attributes": { + "cmId": { + "cmHandle": "395221E080CCF0FD1924103B15873820", + "resourceIdentifier": "/o-ran-smo-ComTop:NodeCluster[@id=2]" + } } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one7.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one7.json index 35328aa..120c210 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one7.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one7.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_1", - "bSide": "AntennaCapability_1" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_1", + "bSide": "AntennaCapability_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one8.json b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one8.json index 7536b5e..6e8f736 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one8.json +++ b/teiv/src/test/resources/cloudeventdata/validation/many-to-one/ce-create-many-to-one8.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-ran:NRSectorCarrier": [ - { - "id": "NRSectorCarrier_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-logical:NRSectorCarrier": [ + { + "id": "NRSectorCarrier_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ - { - "id": "Relation_ManyToOne_1", - "aSide": "NRSectorCarrier_2", - "bSide": "AntennaCapability_2" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-logical:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "id": "Relation_ManyToOne_1", + "aSide": "NRSectorCarrier_2", + "bSide": "AntennaCapability_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many.json index 81d6d14..382accd 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many.json @@ -7,32 +7,38 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_1", + "attributes": { + } } - } - ], - "o-ran-smo-teiv-cloud-to-logical:GNBCUCPFunction": [ - { - "id": "GNBCUCPFunction_1", - "attributes": { + ] + }, + { + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFunction": [ + { + "id": "GNBCUCPFunction_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_1", - "bSide": "GNBCUCPFunction_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_1", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many2.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many2.json index 836faff..aeea79d 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many2.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many2.json @@ -7,32 +7,38 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_2", + "attributes": { + } } - } - ], - "o-ran-smo-teiv-ran:GNBCUCPFunction": [ - { - "id": "GNBCUCPFunction_2", - "attributes": { + ] + }, + { + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFunction": [ + { + "id": "GNBCUCPFunction_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_2", - "bSide": "GNBCUCPFunction_2" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_2", + "bSide": "GNBCUCPFunction_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many3.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many3.json index f966e80..1466991 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many3.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many3.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_2", - "aSide": "ManagedElement_2", - "bSide": "GNBCUCPFunction_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_2", + "aSide": "ManagedElement_2", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many4.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many4.json index fec6466..e2d8b5c 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many4.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many4.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_2", - "bSide": "GNBCUCPFunction_1" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_2", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many5.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many5.json index c174ad9..9355350 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many5.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many5.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-cloud-to-ran:GNBCUCPFunction": [ - { - "id": "GNBCUCPFunction_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFunction": [ + { + "id": "GNBCUCPFunction_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_1", - "bSide": "GNBCUCPFunction_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_1", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many6.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many6.json index 5929e58..e78cdc7 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many6.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many6.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_1", - "bSide": "GNBCUCPFunction_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_1", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many7.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many7.json index 36c989d..f7aa901 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many7.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many7.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_1", - "bSide": "GNBCUCPFunction_1" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_1", + "bSide": "GNBCUCPFunction_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many8.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many8.json index c7625d1..cc1cb2b 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many8.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-many/ce-create-one-to-many8.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-cloud-to-ran:GNBCUCPFunction": [ - { - "id": "GNBCUCPFunction_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-logical-to-cloud:GNBCUCPFunction": [ + { + "id": "GNBCUCPFunction_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ - { - "id": "Relation_OneToMany_1", - "aSide": "ManagedElement_2", - "bSide": "GNBCUCPFunction_2" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-logical:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [ + { + "id": "Relation_OneToMany_1", + "aSide": "ManagedElement_2", + "bSide": "GNBCUCPFunction_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one.json index d8433c3..941dc32 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_O2O_1", "attributes": { @@ -19,7 +19,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ { "id": "CloudNativeSystem_1", "attributes": { @@ -31,7 +31,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ { "id": "Relation_OneToOne_1", "aSide": "ManagedElement_O2O_1", diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one2.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one2.json index 3e12fed..6939d96 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one2.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one2.json @@ -9,7 +9,7 @@ "data": { "entities": [ { - "o-ran-smo-teiv-oam:ManagedElement": [ + "o-ran-smo-teiv-ran-oam:ManagedElement": [ { "id": "ManagedElement_O2O_2", "attributes": { @@ -19,7 +19,7 @@ ] }, { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ { "id": "CloudNativeSystem_2", "attributes": { @@ -31,7 +31,7 @@ ], "relationships": [ { - "o-ran-smo-teiv-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ { "id": "Relation_OneToOne_1", "aSide": "ManagedElement_O2O_2", diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one3.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one3.json index 495a9e6..59467dc 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one3.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one3.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_O2O_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_O2O_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_2", - "aSide": "ManagedElement_O2O_2", - "bSide": "CloudNativeSystem_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_2", + "aSide": "ManagedElement_O2O_2", + "bSide": "CloudNativeSystem_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one4.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one4.json index 7504f91..b3e9240 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one4.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one4.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_1", - "aSide": "ManagedElement_O2O_2", - "bSide": "CloudNativeSystem_1" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_1", + "aSide": "ManagedElement_O2O_2", + "bSide": "CloudNativeSystem_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one5.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one5.json index e87aaaa..ec056f0 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one5.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one5.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ - { - "id": "CloudNativeSystem_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ + { + "id": "CloudNativeSystem_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_1", - "aSide": "ManagedElement_O2O_1", - "bSide": "CloudNativeSystem_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_1", + "aSide": "ManagedElement_O2O_1", + "bSide": "CloudNativeSystem_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one6.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one6.json index 2151339..e39deda 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one6.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one6.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-oam:ManagedElement": [ - { - "id": "ManagedElement_O2O_1", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-oam:ManagedElement": [ + { + "id": "ManagedElement_O2O_1", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-ran-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_1", - "aSide": "ManagedElement_1", - "bSide": "CloudNativeSystem_1" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_1", + "aSide": "ManagedElement_1", + "bSide": "CloudNativeSystem_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one7.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one7.json index 552e334..4d65e2b 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one7.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one7.json @@ -7,14 +7,16 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "relationships": { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_1", - "aSide": "ManagedElement_O2O_1", - "bSide": "CloudNativeSystem_1" - } - ] - } + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_1", + "aSide": "ManagedElement_O2O_1", + "bSide": "CloudNativeSystem_1" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one8.json b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one8.json index e4f46f6..202c60d 100644 --- a/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one8.json +++ b/teiv/src/test/resources/cloudeventdata/validation/one-to-one/ce-create-one-to-one8.json @@ -7,24 +7,28 @@ "datacontenttype": "application/json", "dataschema": "https://ties:8080/schemas/v1/r1-topology", "data": { - "entities": { - "o-ran-smo-teiv-cloud:CloudNativeSystem": [ - { - "id": "CloudNativeSystem_2", - "attributes": { + "entities": [ + { + "o-ran-smo-teiv-ran-cloud:CloudNativeSystem": [ + { + "id": "CloudNativeSystem_2", + "attributes": { + } } - } - ] - }, - "relationships": { - "o-ran-smo-teiv-oam-to-ran:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ - { - "id": "Relation_OneToOne_1", - "aSide": "ManagedElement_O2O_2", - "bSide": "CloudNativeSystem_2" - } - ] - } + ] + } + ], + "relationships": [ + { + "o-ran-smo-teiv-ran-oam-to-cloud:MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM": [ + { + "id": "Relation_OneToOne_1", + "aSide": "ManagedElement_O2O_2", + "bSide": "CloudNativeSystem_2" + } + ] + } + ] } } diff --git a/teiv/src/test/resources/contracts/classifiers/00_getClassifiers_getTopologyByEntityTypeName.groovy b/teiv/src/test/resources/contracts/classifiers/00_getClassifiers_getTopologyByEntityTypeName.groovy new file mode 100644 index 0000000..1ceed6e --- /dev/null +++ b/teiv/src/test/resources/contracts/classifiers/00_getClassifiers_getTopologyByEntityTypeName.groovy @@ -0,0 +1,324 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.classifiers + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with classifiers in scopeFilter." + request { + method GET() + url "topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[2]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with classifiers in scopeFilter(OR)" + request { + method GET() + url "topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural'] | /classifiers[@item='test-app-module:Indoor']" + }, + "totalCount": 4 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(4) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[2]', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with classifiers in scopeFilter.(AND)" + request { + method GET() + url "topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[2]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with classifiers in scopeFilter.(Contains)" + request { + method GET() + url "topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'app-module:Rural')]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].classifiers[2]', byEquality()) + } + } + } +] diff --git a/teiv/src/test/resources/contracts/classifiers/01_getClassifiers_getRelationshipsByType.groovy b/teiv/src/test/resources/contracts/classifiers/01_getClassifiers_getRelationshipsByType.groovy new file mode 100644 index 0000000..583196d --- /dev/null +++ b/teiv/src/test/resources/contracts/classifiers/01_getClassifiers_getRelationshipsByType.groovy @@ -0,0 +1,250 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.classifier + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get classifiers using getRelationshipsByType - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10", + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16", + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural']&targetFilter=/classifiers" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural']&targetFilter=/classifiers" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural']&targetFilter=/classifiers" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural']&targetFilter=/classifiers" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural']&targetFilter=/classifiers" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get classifiers using getRelationshipsByType - EQUALS(AND)" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10", + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16", + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']&targetFilter=/classifiers" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']&targetFilter=/classifiers" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']&targetFilter=/classifiers" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']&targetFilter=/classifiers" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[@item='test-app-module:Rural' and @item='test-app-module:Weekend']&targetFilter=/classifiers" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get classifiers using getRelationshipsByType - CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'ural')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10", + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16", + "classifiers": [ + "module-x:Indoor", + "module-y:Rural", + "module-z:Weekend" + ], + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[contains(@item,'ural')]&targetFilter=/classifiers" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[contains(@item,'ural')]&targetFilter=/classifiers" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[contains(@item,'ural')]&targetFilter=/classifiers" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[contains(@item,'ural')]&targetFilter=/classifiers" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/classifiers[contains(@item,'ural')]&targetFilter=/classifiers" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get classifiers using getRelationshipsByType - CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[contains(@item,'NOT_EXISTING')]" + } + response { + status NOT_FOUND() + headers { + contentType('application/json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Invalid classifiers", + "details": "The provided classifiers are invalid [NOT_EXISTING]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, +] diff --git a/teiv/src/test/resources/contracts/classifiers/02_getClassifiers_getEntitiesByDomain.groovy b/teiv/src/test/resources/contracts/classifiers/02_getClassifiers_getEntitiesByDomain.groovy new file mode 100644 index 0000000..2006eb7 --- /dev/null +++ b/teiv/src/test/resources/contracts/classifiers/02_getClassifiers_getEntitiesByDomain.groovy @@ -0,0 +1,163 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.classifier + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get classifiers using getEntitiesByDomain - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/GNBDUFunction/classifiers&scopeFilter=/GNBDUFunction/classifiers[@item='test-app-module:Rural']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get classifiers using getEntitiesByDomain - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "classifiers": [ + "test-app-module:Rural" + ], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=93" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Rural']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, +] diff --git a/teiv/src/test/resources/contracts/classifiers/03_postClassifiers_merge.groovy b/teiv/src/test/resources/contracts/classifiers/03_postClassifiers_merge.groovy new file mode 100644 index 0000000..bf9bb1a --- /dev/null +++ b/teiv/src/test/resources/contracts/classifiers/03_postClassifiers_merge.groovy @@ -0,0 +1,129 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.classifier + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "NOT FOUND - 404: Merge classifiers with wrong entity ids." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: []" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Merge classifiers with wrong relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "WRONG_RELATIONSHIP_ID" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [] Relationships: [WRONG_RELATIONSHIP_ID]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid classifiers to entities and relationships (add)." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Weekday" + ], + "entityIds": [ + "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512" + ], + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + } +] diff --git a/teiv/src/test/resources/contracts/classifiers/04_postClassifiers_delete.groovy b/teiv/src/test/resources/contracts/classifiers/04_postClassifiers_delete.groovy new file mode 100644 index 0000000..a0a3edd --- /dev/null +++ b/teiv/src/test/resources/contracts/classifiers/04_postClassifiers_delete.groovy @@ -0,0 +1,237 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.classifier + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "NOT FOUND - 404: Delete classifiers with wrong entity ids." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers":[ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "operation": "delete" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: []"}''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Delete classifiers with wrong relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "WRONG_RELATIONSHIP_ID" + ], + "operation": "delete" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [] Relationships: [WRONG_RELATIONSHIP_ID]"}''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "BAD REQUEST - 400: Delete classifiers from non-existing schema." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module-wrong:Rural", + "test-app-module:Weekend" + ], + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "operation": "delete" + }''') + } + response { + status BAD_REQUEST() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: test-app-module-wrong"}''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid classifiers, no topology object given." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid classifiers on entities." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid classifiers on relationships." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA", + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid classifiers on entities and relationships." + request { + method POST() + url "/topology-inventory/v1alpha11/classifiers" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "classifiers": [ + "test-app-module:Rural", + "test-app-module:Weekend" + ], + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA", + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + } +] diff --git a/teiv/src/test/resources/contracts/data/00_getAllDomains.groovy b/teiv/src/test/resources/contracts/data/00_getAllDomains.groovy new file mode 100644 index 0000000..10e40f3 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/00_getAllDomains.groovy @@ -0,0 +1,240 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all the available topology domains." + request { + method GET() + url "/topology-inventory/v1alpha11/domains" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "EQUIPMENT", + "entityTypes": { + "href": "/domains/EQUIPMENT/entity-types" + }, + "relationshipTypes": { + "href": "/domains/EQUIPMENT/relationship-types" + } + }, + { + "name": "OAM", + "entityTypes": { + "href": "/domains/OAM/entity-types" + }, + "relationshipTypes": { + "href": "/domains/OAM/relationship-types" + } + }, + { + "name": "RAN", + "entityTypes": { + "href": "/domains/RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/RAN/relationship-types" + } + }, + { + "name": "REL_EQUIPMENT_RAN", + "entityTypes": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types" + } + }, + { + "name": "REL_OAM_RAN", + "entityTypes": { + "href": "/domains/REL_OAM_RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/REL_OAM_RAN/relationship-types" + } + }, + { + "name": "TEIV", + "entityTypes": { + "href": "/domains/TEIV/entity-types" + }, + "relationshipTypes": { + "href": "/domains/TEIV/relationship-types" + } + }, + { + "name": "TEST", + "entityTypes": { + "href": "/domains/TEST/entity-types" + }, + "relationshipTypes": { + "href": "/domains/TEST/relationship-types" + } + } + ], + "self": { + "href": "/domains?offset=0&limit=500" + }, + "first": { + "href": "/domains?offset=0&limit=500" + }, + "prev": { + "href": "/domains?offset=0&limit=500" + }, + "next": { + "href": "/domains?offset=0&limit=500" + }, + "last": { + "href": "/domains?offset=0&limit=500" + }, + "totalCount": 7 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(7) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entityTypes.href', byEquality()) + jsonPath('$.items[0].relationshipTypes.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].entityTypes.href', byEquality()) + jsonPath('$.items[1].relationshipTypes.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].entityTypes.href', byEquality()) + jsonPath('$.items[2].relationshipTypes.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].entityTypes.href', byEquality()) + jsonPath('$.items[3].relationshipTypes.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].entityTypes.href', byEquality()) + jsonPath('$.items[4].relationshipTypes.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].entityTypes.href', byEquality()) + jsonPath('$.items[5].relationshipTypes.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].entityTypes.href', byEquality()) + jsonPath('$.items[6].relationshipTypes.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology domains with offset as 2 and limit as 3." + request { + method GET() + url "/topology-inventory/v1alpha11/domains?offset=2&limit=3" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "RAN", + "entityTypes": { + "href": "/domains/RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/RAN/relationship-types" + } + }, + { + "name": "REL_EQUIPMENT_RAN", + "entityTypes": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types" + } + }, + { + "name": "REL_OAM_RAN", + "entityTypes": { + "href": "/domains/REL_OAM_RAN/entity-types" + }, + "relationshipTypes": { + "href": "/domains/REL_OAM_RAN/relationship-types" + } + } + ], + "self": { + "href": "/domains?offset=2&limit=3" + }, + "first": { + "href": "/domains?offset=0&limit=3" + }, + "prev": { + "href": "/domains?offset=0&limit=3" + }, + "next": { + "href": "/domains?offset=5&limit=3" + }, + "last": { + "href": "/domains?offset=5&limit=3" + }, + "totalCount": 7 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entityTypes.href', byEquality()) + jsonPath('$.items[0].relationshipTypes.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].entityTypes.href', byEquality()) + jsonPath('$.items[1].relationshipTypes.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].entityTypes.href', byEquality()) + jsonPath('$.items[2].relationshipTypes.href', byEquality()) + } + } + }, + Contract.make { + description "ERROR - 400: Get all the available topology domains with invalid offset (greater than total count)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains?offset=100" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 6" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/01_getTopologyEntityTypes.groovy b/teiv/src/test/resources/contracts/data/01_getTopologyEntityTypes.groovy new file mode 100644 index 0000000..d6a89a8 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/01_getTopologyEntityTypes.groovy @@ -0,0 +1,534 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all the available topology entity types in OAM domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/OAM/entity-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ManagedElement", + "entities": { + "href": "/domains/OAM/entity-types/ManagedElement/entities" + } + } + ], + "self": { + "href": "/domains/OAM/entity-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/OAM/entity-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/OAM/entity-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/OAM/entity-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/OAM/entity-types?offset=0&limit=500" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entities.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology entity types in REL_OAM_RAN domain (includes OAM and RAN domains)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/entity-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "AntennaCapability", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/AntennaCapability/entities" + } + }, + { + "name": "ENodeBFunction", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/ENodeBFunction/entities" + } + }, + { + "name": "EUtranCell", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/EUtranCell/entities" + } + }, + { + "name": "GNBCUCPFunction", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/GNBCUCPFunction/entities" + } + }, + { + "name": "GNBCUUPFunction", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/GNBCUUPFunction/entities" + } + }, + { + "name": "GNBDUFunction", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/GNBDUFunction/entities" + } + }, + { + "name": "LTESectorCarrier", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/LTESectorCarrier/entities" + } + }, + { + "name": "ManagedElement", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/ManagedElement/entities" + } + }, + { + "name": "NRCellCU", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/NRCellCU/entities" + } + }, + { + "name": "NRCellDU", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/NRCellDU/entities" + } + }, + { + "name": "NRSectorCarrier", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/NRSectorCarrier/entities" + } + }, + { + "name": "Sector", + "entities": { + "href": "/domains/REL_OAM_RAN/entity-types/Sector/entities" + } + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/entity-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_OAM_RAN/entity-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/entity-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_OAM_RAN/entity-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_OAM_RAN/entity-types?offset=0&limit=500" + }, + "totalCount": 12 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(12) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entities.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].entities.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].entities.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].entities.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].entities.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].entities.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].entities.href', byEquality()) + jsonPath('$.items[7].name', byEquality()) + jsonPath('$.items[7].entities.href', byEquality()) + jsonPath('$.items[8].name', byEquality()) + jsonPath('$.items[8].entities.href', byEquality()) + jsonPath('$.items[9].name', byEquality()) + jsonPath('$.items[9].entities.href', byEquality()) + jsonPath('$.items[10].name', byEquality()) + jsonPath('$.items[10].entities.href', byEquality()) + jsonPath('$.items[11].name', byEquality()) + jsonPath('$.items[11].entities.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology entity types in RAN domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "AntennaCapability", + "entities": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities" + } + }, + { + "name": "ENodeBFunction", + "entities": { + "href": "/domains/RAN/entity-types/ENodeBFunction/entities" + } + }, + { + "name": "EUtranCell", + "entities": { + "href": "/domains/RAN/entity-types/EUtranCell/entities" + } + }, + { + "name": "GNBCUCPFunction", + "entities": { + "href": "/domains/RAN/entity-types/GNBCUCPFunction/entities" + } + }, + { + "name": "GNBCUUPFunction", + "entities": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities" + } + }, + { + "name": "GNBDUFunction", + "entities": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities" + } + }, + { + "name": "LTESectorCarrier", + "entities": { + "href": "/domains/RAN/entity-types/LTESectorCarrier/entities" + } + }, + { + "name": "NRCellCU", + "entities": { + "href": "/domains/RAN/entity-types/NRCellCU/entities" + } + }, + { + "name": "NRCellDU", + "entities": { + "href": "/domains/RAN/entity-types/NRCellDU/entities" + } + }, + { + "name": "NRSectorCarrier", + "entities": { + "href": "/domains/RAN/entity-types/NRSectorCarrier/entities" + } + }, + { + "name": "Sector", + "entities": { + "href": "/domains/RAN/entity-types/Sector/entities" + } + } + ], + "self": { + "href": "/domains/RAN/entity-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/entity-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/entity-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/entity-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/entity-types?offset=0&limit=500" + }, + "totalCount": 11 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(11) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entities.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].entities.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].entities.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].entities.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].entities.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].entities.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].entities.href', byEquality()) + jsonPath('$.items[7].name', byEquality()) + jsonPath('$.items[7].entities.href', byEquality()) + jsonPath('$.items[8].name', byEquality()) + jsonPath('$.items[8].entities.href', byEquality()) + jsonPath('$.items[9].name', byEquality()) + jsonPath('$.items[9].entities.href', byEquality()) + jsonPath('$.items[10].name', byEquality()) + jsonPath('$.items[10].entities.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology entity types in TEIV domain (includes all the supported topology domains)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEIV/entity-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "AntennaCapability", + "entities": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities" + } + }, + { + "name": "AntennaModule", + "entities": { + "href": "/domains/TEIV/entity-types/AntennaModule/entities" + } + }, + { + "name": "ENodeBFunction", + "entities": { + "href": "/domains/TEIV/entity-types/ENodeBFunction/entities" + } + }, + { + "name": "EUtranCell", + "entities": { + "href": "/domains/TEIV/entity-types/EUtranCell/entities" + } + }, + { + "name": "EntityTypeA", + "entities": { + "href": "/domains/TEIV/entity-types/EntityTypeA/entities" + } + }, + { + "name": "EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters", + "entities": { + "href": "/domains/TEIV/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities" + } + }, + { + "name": "GNBCUCPFunction", + "entities": { + "href": "/domains/TEIV/entity-types/GNBCUCPFunction/entities" + } + }, + { + "name": "GNBCUUPFunction", + "entities": { + "href": "/domains/TEIV/entity-types/GNBCUUPFunction/entities" + } + }, + { + "name": "GNBDUFunction", + "entities": { + "href": "/domains/TEIV/entity-types/GNBDUFunction/entities" + } + }, + { + "name": "LTESectorCarrier", + "entities": { + "href": "/domains/TEIV/entity-types/LTESectorCarrier/entities" + } + }, + { + "name": "ManagedElement", + "entities": { + "href": "/domains/TEIV/entity-types/ManagedElement/entities" + } + }, + { + "name": "NRCellCU", + "entities": { + "href": "/domains/TEIV/entity-types/NRCellCU/entities" + } + }, + { + "name": "NRCellDU", + "entities": { + "href": "/domains/TEIV/entity-types/NRCellDU/entities" + } + }, + { + "name": "NRSectorCarrier", + "entities": { + "href": "/domains/TEIV/entity-types/NRSectorCarrier/entities" + } + }, + { + "name": "Sector", + "entities": { + "href": "/domains/TEIV/entity-types/Sector/entities" + } + }, + { + "name": "Site", + "entities": { + "href": "/domains/TEIV/entity-types/Site/entities" + } + } + ], + "self": { + "href": "/domains/TEIV/entity-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/TEIV/entity-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/TEIV/entity-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/TEIV/entity-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/TEIV/entity-types?offset=0&limit=500" + }, + "totalCount": 16 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(16) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].entities.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].entities.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].entities.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].entities.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].entities.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].entities.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].entities.href', byEquality()) + jsonPath('$.items[7].name', byEquality()) + jsonPath('$.items[7].entities.href', byEquality()) + jsonPath('$.items[8].name', byEquality()) + jsonPath('$.items[8].entities.href', byEquality()) + jsonPath('$.items[9].name', byEquality()) + jsonPath('$.items[9].entities.href', byEquality()) + jsonPath('$.items[10].name', byEquality()) + jsonPath('$.items[10].entities.href', byEquality()) + jsonPath('$.items[11].name', byEquality()) + jsonPath('$.items[11].entities.href', byEquality()) + jsonPath('$.items[12].name', byEquality()) + jsonPath('$.items[12].entities.href', byEquality()) + jsonPath('$.items[13].name', byEquality()) + jsonPath('$.items[13].entities.href', byEquality()) + jsonPath('$.items[14].name', byEquality()) + jsonPath('$.items[14].entities.href', byEquality()) + jsonPath('$.items[15].name', byEquality()) + jsonPath('$.items[15].entities.href', byEquality()) + } + } + }, + Contract.make { + description "ERROR - 400: Get all the available topology entity types with invalid domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/INVALID/entity-types" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Unknown domain", + "details": "Unknown domain: INVALID, known domains: [EQUIPMENT, OAM, RAN, REL_EQUIPMENT_RAN, REL_OAM_RAN, TEIV, TEST]" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all the available topology entity types in TEIV domain with invalid offset (greater than total count)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEIV/entity-types?offset=100" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 15" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/02_getTopologyByEntityTypeName.groovy b/teiv/src/test/resources/contracts/data/02_getTopologyByEntityTypeName.groovy new file mode 100644 index 0000000..0b100f9 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/02_getTopologyByEntityTypeName.groovy @@ -0,0 +1,1488 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all topology entities of type NRCellDU." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=92" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=93" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500" + }, + "totalCount": 6 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(6) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with offset as 1 and limit as 4." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=1&limit=4" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=1&limit=4" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=4" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=4" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=5&limit=4" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=5&limit=4" + }, + "totalCount": 7 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(4) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type NRCellDU with scopeFilter." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type NRCellDU which matches given ID (exact ID match). Alternate to GET entity by ID." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type NRCellDU which contain 'ManagedElement=9,GNBDUFunction=9' in ID (partial ID match)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=500&scopeFilter=/NRCellDU[contains(@id, 'ManagedElement=9,GNBDUFunction=9')]" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaCapability which has serving-antennaModule association with ID that contains 'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A'" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEIV/entity-types/AntennaCapability/entities?scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1" + } + ] + } + ], + "self": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities?offset=0&limit=500&scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + }, + "first": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities?offset=0&limit=500&scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + }, + "prev": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities?offset=0&limit=500&scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + }, + "next": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities?offset=0&limit=500&scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + }, + "last": { + "href": "/domains/TEIV/entity-types/AntennaCapability/entities?offset=0&limit=500&scopeFilter=/serving-antennaModule[contains(@id,'AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A')]" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:AntennaCapability[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction which has provided-nrCellDu association with ID that contains 'NRCellDU=1'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/provided-nrCellDu[contains(@id,'NRCellDU=1')]" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaModule with targetFilter=/sourceIds" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?targetFilter=/sourceIds" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaNearUnit=1,RetSubUnit=1", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + }, + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaNearUnit=1,RetSubUnit=1", + "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC" + ] + } + ] + } + ], + "self": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds" + }, + "first": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds" + }, + "prev": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds" + }, + "next": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds" + }, + "last": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[1]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[2]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[3]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-equipment:AntennaModule[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[2]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[3]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaModule with scopeFilter on sourceIds" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']&targetFilter=/sourceIds" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaNearUnit=1,RetSubUnit=1", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + } + ], + "self": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']" + }, + "first": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']" + }, + "prev": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']" + }, + "next": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']" + }, + "last": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[1]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[2]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-equipment:AntennaModule[0].sourceIds[3]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get empty items array when no entity exists of given filter criteria." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=898989]" + }, + "totalCount": 0 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(0) + }) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities by a long named entity type." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=0&limit=1&targetFilter=/attributes" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters": [ + { + "attributes": { + "attributeA2WithAttributeNameLengthLongerThanSixtyThreeCharacters": 9223372036854775807, + "attributeA6WithAttributeNameLengthLongerThanSixtyThreeCharacters": [ + "1000", + "2000" + ], + "attributeA5WithAttributeNameLengthLongerThanSixtyThreeCharacters": 1.1, + "attributeA4WithAttributeNameLengthLongerThanSixtyThreeCharacters": -9223372036854775807, + "attributeA3WithAttributeNameLengthLongerThanSixtyThreeCharacters": 2147483647, + "attributeA7WithAttributeNameLengthLongerThanSixtyThreeCharacters": { + "mcc": "01", + "mnc": "234" + }, + "attributeA1WithAttributeNameLengthLongerThanSixtyThreeCharacters": "someStringValue" + }, + "id": "LongEntityType1" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=0&limit=1&targetFilter=/attributes" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=0&limit=1&targetFilter=/attributes" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=0&limit=1&targetFilter=/attributes" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=1&limit=1&targetFilter=/attributes" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities?offset=2&limit=1&targetFilter=/attributes" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].id', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA1WithAttributeNameLengthLongerThanSixtyThreeCharacters', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA2WithAttributeNameLengthLongerThanSixtyThreeCharacters', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA3WithAttributeNameLengthLongerThanSixtyThreeCharacters', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA4WithAttributeNameLengthLongerThanSixtyThreeCharacters', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA5WithAttributeNameLengthLongerThanSixtyThreeCharacters', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA6WithAttributeNameLengthLongerThanSixtyThreeCharacters[0]', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA6WithAttributeNameLengthLongerThanSixtyThreeCharacters[1]', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA7WithAttributeNameLengthLongerThanSixtyThreeCharacters.mcc', byEquality()) + jsonPath('$.items[0].test-built-in-module:EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[0].attributes.attributeA7WithAttributeNameLengthLongerThanSixtyThreeCharacters.mnc', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type NRCellDU with scopeFilter on association." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']&targetFilter=/attributes(nCI)" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "attributes": { + "nCI": 1 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "attributes": { + "nCI": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "attributes": { + "nCI": 3 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&targetFilter=/attributes(nCI)&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&targetFilter=/attributes(nCI)&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&targetFilter=/attributes(nCI)&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&targetFilter=/attributes(nCI)&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities?offset=0&limit=100&targetFilter=/attributes(nCI)&scopeFilter=/provided-by-gnbduFunction[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].attributes.nCI', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].attributes.nCI', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].attributes.nCI', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter on sourceIds and gNBId with AND condition." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']&targetFilter=/attributes;/sourceIds" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "82" + }, + "gNBId": 10, + "gNBDUId": null, + "gNBIdLength": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "urn:cmHandle:72FDA73D085F138FECC974CB91F1450E" + ] + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes;/sourceIds&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes;/sourceIds&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes;/sourceIds&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes;/sourceIds&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes;/sourceIds&scopeFilter=/attributes[@gNBId=10]; /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter with AND an OR conditions." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]&targetFilter=/GNBDUFunction" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/GNBDUFunction&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/GNBDUFunction&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/GNBDUFunction&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/GNBDUFunction&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/GNBDUFunction&scopeFilter=/attributes[@gNBId=10 or @gNBId=13]; /attributes[@gNBIdLength = 2]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter with AND an OR conditions." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']&targetFilter=/id" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/id&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/id&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/id&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/id&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/id&scopeFilter=/attributes[@gNBId = 9 and @gNBIdLength = 1] | /sourceIds[@item = 'urn:cmHandle:72FDA73D085F138FECC974CB91F1450E']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter on complex attribute STRING value - EQUALS - KEY AND VALUE EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "83" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "86" + } + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter on complex attribute STRING value - EQUALS - KEY AND VALUE EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "83" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "86" + } + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[@mcc='456']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type GNBDUFunction with scopeFilter on complex attribute STRING value - CONTAINS - KEY AND VALUE EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "attributes": { + "dUpLMNId": { + "mcc": "789", + "mnc": "84" + } + } + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", + "attributes": { + "dUpLMNId": { + "mcc": "789", + "mnc": "87" + } + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/attributes(dUpLMNId)&scopeFilter=/attributes/dUpLMNId[contains(@mcc,'78')]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaCapability with scopeFilter on complex attribute STRING array - EXACT MATCH - VALUE EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1", + "attributes": { + "eUtranFqBands": [ + "123", + "456", + "789" + ] + } + } + ] + }, + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "attributes": { + "eUtranFqBands": [ + "123", + "456", + "789" + ] + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + }, + "first": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + }, + "prev": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + }, + "next": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + }, + "last": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item='456']" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:AntennaCapability[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:AntennaCapability[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaCapability with scopeFilter on complex attribute INTEGER array - EXACT MATCH - VALUE NOT EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + }, + "first": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + }, + "prev": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + }, + "next": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + }, + "last": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[@item=456]" + }, + "totalCount": 0 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(0) + }) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaCapability with scopeFilter on complex attribute STRING array - PARTIAL MATCH - VALUE EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1", + "attributes": { + "eUtranFqBands": [ + "123", + "456", + "789" + ] + } + } + ] + }, + { + "o-ran-smo-teiv-ran:AntennaCapability": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "attributes": { + "eUtranFqBands": [ + "123", + "456", + "789" + ] + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + }, + "first": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + }, + "next": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + }, + "last": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'45')]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:AntennaCapability[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:AntennaCapability[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all topology entities of type AntennaCapability with scopeFilter on complex attribute STRING array - PARTIAL MATCH - VALUE NOT EXISTS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + }, + "first": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + }, + "next": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + }, + "last": { + "href": "/domains/RAN/entity-types/AntennaCapability/entities?offset=0&limit=500&targetFilter=/attributes(eUtranFqBands)&scopeFilter=/attributes/eUtranFqBands[contains(@item,'999')]" + }, + "totalCount": 0 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(0) + }) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities of type AntennaModule with scopeFilter on geographic attribute" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A", + "attributes": { + "geo-location": "POINT(39.4019881 67.9419888)" + } + } + ] + } + ], + "self": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + }, + "first": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + }, + "prev": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + }, + "next": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + }, + "last": { + "href": "/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 67.9419888)']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + } + } + }, + Contract.make { + description "ERROR - 400: Get entities of type AntennaModule with scopeFilter on geographic attribute - invalid format" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = '(39.4019881 67.9419888)']" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid query condition", + "details": "Invalid geographic format." + }''') + } + }, + Contract.make { + description "ERROR - 400: Get entities of type AntennaModule with scopeFilter on geographic attribute - 1 coordinate" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881)']" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid query condition", + "details": "A point should have 2 coordinates (longitude and latitude)." + }''') + } + }, + Contract.make { + description "ERROR - 400: Get entities of type AntennaModule with scopeFilter on geographic attribute - invalid coordinate" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/AntennaModule/entities?offset=0&limit=500&targetFilter=/attributes(geo-location)&scopeFilter=/attributes[@geo-location = 'POINT(39.4019881 ABC)']" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid query condition", + "details": "Invalid coordinate: ABC" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all topology entities for an entity type that is not in the domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/EQUIPMENT/entity-types/NRCellDU/entities" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Unknown entity type", + "details": "Entity type NRCellDU is not part of the domain EQUIPMENT, known entity types: [AntennaModule, Site]" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all topology entities for wrong entity type name." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU1/entities" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Unknown entity type", + "details": "Entity type NRCellDU1 is not part of the model, known entity types: [AntennaCapability, AntennaModule, ENodeBFunction, EUtranCell, EntityTypeA, EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters, GNBCUCPFunction, GNBCUUPFunction, GNBDUFunction, LTESectorCarrier, ManagedElement, NRCellCU, NRCellDU, NRSectorCarrier, Sector, Site]" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all topology entities with invalid scopeFilter (attribute not prefixed with @)" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBCUCPFunction/entities?scopeFilter=/attributes[contains(gNBCUName,'Cucp-1')]" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Grammar error", + "details": "no viable alternative at input '[contains(gNBCUName' at line 1:21" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all topology entities of type GNBCUUPFunction with invalid offset (greater than total count)." + request { + method GET() + url "topology-inventory/v1alpha11/domains/RAN/entity-types/GNBCUUPFunction/entities?offset=10000" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 6" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/03_getTopologyById.groovy b/teiv/src/test/resources/contracts/data/03_getTopologyById.groovy new file mode 100644 index 0000000..2ff0980 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/03_getTopologyById.groovy @@ -0,0 +1,110 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get topology for ManagedElement entity with id 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9' in OAM domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9" + } + response { + status OK() + headers { + contentType('application/yang.data+json') + } + body('''{ + "o-ran-smo-teiv-oam:ManagedElement": [ + { + "decorators": {}, + "classifiers": [], + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology for GNBDUFunction entity with id 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9' with REL_EQUIPMENT_RAN (domain including other domains)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + response { + status OK() + headers { + contentType('application/yang.data+json') + } + body('''{ + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "ORAN" + }, + "classifiers": [ + "test-app-module:Indoor", + "test-app-module:Weekend" + ], + "attributes": { + "dUpLMNId": { + "mcc": "123", + "mnc": "82" + }, + "gNBDUId": null, + "gNBId": 9, + "gNBIdLength": 1 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + }''') + } + }, + Contract.make { + description "ERROR - 400: Get topology for GNBDUFunction entity with non existing id 'non-existing-id'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/entity-types/GNBDUFunction/entities/non-existing-id" + } + response { + status NOT_FOUND() + headers { + contentType('application/json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource is not found" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/04_getAllRelationshipsForEntityId.groovy b/teiv/src/test/resources/contracts/data/04_getAllRelationshipsForEntityId.groovy new file mode 100644 index 0000000..0ed0aa7 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/04_getAllRelationshipsForEntityId.groovy @@ -0,0 +1,693 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all relationships for entity type NRCellDU with ID urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "id": "urn:o-ran:smo:teiv:sha512:NRCELLDU_USES_NRSECTORCARRIER=7B9425BBD6977FEA6C180F6078CFBAEBE65400223B29E0EFA4F38424FAD66C690806778909177ECF1457CAC18E5BCF6FA4F24E3ECE524C89DE68108708D6D876" + } + ] + }, + { + "o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "Sector=2", + "id": "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].aSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].bSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].bSide', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for entity type NRCellDU with ID urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1 & targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU" + }, + "totalCount": 1 +}''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for entity type NRCellDU with ID urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1 & targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + ] + }, + { + "o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "Sector=2", + "id": "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1/relationships?offset=0&limit=100&targetFilter=/GNBDUFUNCTION_PROVIDES_NRCELLDU;/SECTOR_GROUPS_NRCELLDU" + }, + "totalCount": 2 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for entity type GNBDUFunction with ID urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1. & scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9/relationships?offset=0&limit=100&scopeFilter=/provided-nrCellDu[@id = 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for entity type NRCellDU with ID urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3 with limit as 2." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?limit=2" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=714C1B73945C298CAA03FE0D800053CDD1C571BBF375DC647B9F23FDA861CEB369832A3593BB1AA4B8A7245AD187ED24ADDF6FB147130827CDC17BA8370C4838" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=3", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3", + "id": "urn:o-ran:smo:teiv:sha512:NRCELLDU_USES_NRSECTORCARRIER=950ED4540349F9859CEA9E47884A28CD567BDD2505A3C5335C8851A7AADF2AF65542157BB42D607EE3847E4223D76DE88B90762D0590E48693822FD6DCAE60CD" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=0&limit=2" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=0&limit=2" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=0&limit=2" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=2&limit=2" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=2&limit=2" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].aSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCELLDU_USES_NRSECTORCARRIER[0].bSide', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for long entity type name with id as LongEntityType1 (OneToOne, ManyToOne, ManyToMany and Same Entity with aSide of relationship)" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType1", + "aSide": "EntityType1", + "id": "RelId_OneToOne_EntityType1_LongEntityType1" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType1", + "aSide": "EntityType2", + "id": "Rel_ManyToOne_EntityType2_LongEntityType1" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType1", + "aSide": "EntityType1", + "id": "Rel_ManyToMany_EntityType1_LongEntityType1" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500" + }, + "totalCount": 4 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for long entity type name with id as LongEntityType2 (OneToMany and Same Entity with bSide of relationship)" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "EntityType2", + "id": "Rel_OneToMany_EntityType2_LongEntityType2" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType3", + "aSide": "LongEntityType2", + "id": "Rel_OneToOne_SameEntity_LongEntityType2_LongEntityType3" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500" + }, + "totalCount": 3 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for long entity type name with id as LongEntityType1 and with scope filter on sourceIds" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']&targetFilter=/sourceIds" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType1/relationships?offset=0&limit=500&targetFilter=/sourceIds&scopeFilter=/sourceIds[@item = 'urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616']" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for long entity type name with id as LongEntityType3 and with scope filter on classifiers" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?scopeFilter=/classifiers[@item='test-app-module:Weekend']&targetFilter=/classifiers" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType3", + "aSide": "LongEntityType2", + "id": "Rel_OneToOne_SameEntity_LongEntityType2_LongEntityType3" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Weekend']" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Weekend']" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Weekend']" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Weekend']" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType3/relationships?offset=0&limit=500&targetFilter=/classifiers&scopeFilter=/classifiers[@item='test-app-module:Weekend']" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for long entity type name with id as LongEntityType2 and with scope filter on decorators" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]&targetFilter=/decorators" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType3", + "aSide": "LongEntityType2", + "id": "Rel_OneToOne_SameEntity_LongEntityType2_LongEntityType3" + } + ] + } + ], + "self": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]" + }, + "first": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]" + }, + "prev": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]" + }, + "next": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]" + }, + "last": { + "href": "/domains/TEST/entity-types/EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters/entities/LongEntityType2/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'ORAN')]" + }, + "totalCount": 2 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Return items as empty for a entity with no relationship" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91/relationships?offset=0&limit=500" + }, + "totalCount": 0 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for an entity id where there exists no relationships for the entity type in the given domain" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBCUUPFunction/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9/relationships?offset=0&limit=500" + }, + "totalCount": 0 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all relationships for an entity id where there exists no relationships in the given domain" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + }, + "first": { + "href": "/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + }, + "prev": { + "href": "/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + }, + "next": { + "href": "/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + }, + "last": { + "href": "/domains/OAM/entity-types/ManagedElement/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9/relationships?offset=0&limit=100" + }, + "totalCount": 0 + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all relationships for NRCellDU entity with invalid offset (greater than total count)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3/relationships?offset=1000" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 2" + }''') + } + }, + Contract.make { + description "ERROR - 404: Get all relationships for non existing NRCellDU id." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/non-existent/relationships" + } + response { + status NOT_FOUND() + headers { + contentType('application/json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource is not found" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/05_getRelationshipTypes.groovy b/teiv/src/test/resources/contracts/data/05_getRelationshipTypes.groovy new file mode 100644 index 0000000..fd50f6e --- /dev/null +++ b/teiv/src/test/resources/contracts/data/05_getRelationshipTypes.groovy @@ -0,0 +1,589 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get all the available topology relationships types in REL_OAM_RAN domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ENODEBFUNCTION_PROVIDES_EUTRANCELL", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/ENODEBFUNCTION_PROVIDES_EUTRANCELL/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "EUTRANCELL_USES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/EUTRANCELL_USES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/GNBCUCPFUNCTION_PROVIDES_NRCELLCU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "LTESECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/LTESECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships" + } + }, + { + "name": "NRCELLDU_USES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "NRSECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "SECTOR_GROUPS_EUTRANCELL", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/SECTOR_GROUPS_EUTRANCELL/relationships" + } + }, + { + "name": "SECTOR_GROUPS_NRCELLDU", + "relationships": { + "href": "/domains/REL_OAM_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships" + } + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types?offset=0&limit=500" + }, + "totalCount": 15 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(15) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].relationships.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].relationships.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].relationships.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].relationships.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].relationships.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].relationships.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].relationships.href', byEquality()) + jsonPath('$.items[7].name', byEquality()) + jsonPath('$.items[7].relationships.href', byEquality()) + jsonPath('$.items[8].name', byEquality()) + jsonPath('$.items[8].relationships.href', byEquality()) + jsonPath('$.items[9].name', byEquality()) + jsonPath('$.items[9].relationships.href', byEquality()) + jsonPath('$.items[10].name', byEquality()) + jsonPath('$.items[10].relationships.href', byEquality()) + jsonPath('$.items[11].name', byEquality()) + jsonPath('$.items[11].relationships.href', byEquality()) + jsonPath('$.items[12].name', byEquality()) + jsonPath('$.items[12].relationships.href', byEquality()) + jsonPath('$.items[13].name', byEquality()) + jsonPath('$.items[13].relationships.href', byEquality()) + jsonPath('$.items[14].name', byEquality()) + jsonPath('$.items[14].relationships.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology relationship types in REL_EQUIPMENT_RAN domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/relationship-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ANTENNAMODULE_INSTALLED_AT_SITE", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_INSTALLED_AT_SITE/relationships" + } + }, + { + "name": "ANTENNAMODULE_SERVES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_EUTRANCELL", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ENODEBFUNCTION_PROVIDES_EUTRANCELL/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "EUTRANCELL_USES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/EUTRANCELL_USES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/GNBCUCPFUNCTION_PROVIDES_NRCELLCU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "LTESECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/LTESECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "NRCELLDU_USES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "NRSECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "SECTOR_GROUPS_ANTENNAMODULE", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_ANTENNAMODULE/relationships" + } + }, + { + "name": "SECTOR_GROUPS_EUTRANCELL", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_EUTRANCELL/relationships" + } + }, + { + "name": "SECTOR_GROUPS_NRCELLDU", + "relationships": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships" + } + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types?offset=0&limit=500" + }, + "totalCount": 14 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology relationship types in RAN domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/relationship-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ENODEBFUNCTION_PROVIDES_EUTRANCELL", + "relationships": { + "href": "/domains/RAN/relationship-types/ENODEBFUNCTION_PROVIDES_EUTRANCELL/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/RAN/relationship-types/ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "EUTRANCELL_USES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/RAN/relationship-types/EUTRANCELL_USES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", + "relationships": { + "href": "/domains/RAN/relationship-types/GNBCUCPFUNCTION_PROVIDES_NRCELLCU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "relationships": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "LTESECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/RAN/relationship-types/LTESECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "NRCELLDU_USES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/RAN/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "NRSECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "SECTOR_GROUPS_EUTRANCELL", + "relationships": { + "href": "/domains/RAN/relationship-types/SECTOR_GROUPS_EUTRANCELL/relationships" + } + }, + { + "name": "SECTOR_GROUPS_NRCELLDU", + "relationships": { + "href": "/domains/RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships" + } + } + ], + "self": { + "href": "/domains/RAN/relationship-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/relationship-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/relationship-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/relationship-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/relationship-types?offset=0&limit=500" + }, + "totalCount": 11 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get all the available topology relationship types in TEIV." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEIV/relationship-types" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ANTENNAMODULE_INSTALLED_AT_SITE", + "relationships": { + "href": "/domains/TEIV/relationship-types/ANTENNAMODULE_INSTALLED_AT_SITE/relationships" + } + }, + { + "name": "ANTENNAMODULE_SERVES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/TEIV/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_EUTRANCELL", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENODEBFUNCTION_PROVIDES_EUTRANCELL/relationships" + } + }, + { + "name": "ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + }, + { + "name": "ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + }, + { + "name": "ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + }, + { + "name": "ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + }, + { + "name": "ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS", + "relationships": { + "href": "/domains/TEIV/relationship-types/ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + }, + { + "name": "EUTRANCELL_USES_LTESECTORCARRIER", + "relationships": { + "href": "/domains/TEIV/relationship-types/EUTRANCELL_USES_LTESECTORCARRIER/relationships" + } + }, + { + "name": "GNBCUCPFUNCTION_PROVIDES_NRCELLCU", + "relationships": { + "href": "/domains/TEIV/relationship-types/GNBCUCPFUNCTION_PROVIDES_NRCELLCU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRCELLDU", + "relationships": { + "href": "/domains/TEIV/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships" + } + }, + { + "name": "GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/TEIV/relationship-types/GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "LTESECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/TEIV/relationship-types/LTESECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", + "relationships": { + "href": "/domains/TEIV/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", + "relationships": { + "href": "/domains/TEIV/relationship-types/MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", + "relationships": { + "href": "/domains/TEIV/relationship-types/MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION/relationships" + } + }, + { + "name": "MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", + "relationships": { + "href": "/domains/TEIV/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships" + } + }, + { + "name": "NRCELLDU_USES_NRSECTORCARRIER", + "relationships": { + "href": "/domains/TEIV/relationship-types/NRCELLDU_USES_NRSECTORCARRIER/relationships" + } + }, + { + "name": "NRSECTORCARRIER_USES_ANTENNACAPABILITY", + "relationships": { + "href": "/domains/TEIV/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + }, + { + "name": "SECTOR_GROUPS_ANTENNAMODULE", + "relationships": { + "href": "/domains/TEIV/relationship-types/SECTOR_GROUPS_ANTENNAMODULE/relationships" + } + }, + { + "name": "SECTOR_GROUPS_EUTRANCELL", + "relationships": { + "href": "/domains/TEIV/relationship-types/SECTOR_GROUPS_EUTRANCELL/relationships" + } + }, + { + "name": "SECTOR_GROUPS_NRCELLDU", + "relationships": { + "href": "/domains/TEIV/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships" + } + } + ], + "self": { + "href": "/domains/TEIV/relationship-types?offset=0&limit=500" + }, + "first": { + "href": "/domains/TEIV/relationship-types?offset=0&limit=500" + }, + "prev": { + "href": "/domains/TEIV/relationship-types?offset=0&limit=500" + }, + "next": { + "href": "/domains/TEIV/relationship-types?offset=0&limit=500" + }, + "last": { + "href": "/domains/TEIV/relationship-types?offset=0&limit=500" + }, + "totalCount": 23 + }''') + } + }, + Contract.make { + description "ERROR - 400: Get all the available topology relationship types in invalid domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/INVALID/relationship-types" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Unknown domain", + "details": "Unknown domain: INVALID, known domains: [EQUIPMENT, OAM, RAN, REL_EQUIPMENT_RAN, REL_OAM_RAN, TEIV, TEST]" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/06_getRelationshipsByType.groovy b/teiv/src/test/resources/contracts/data/06_getRelationshipsByType.groovy new file mode 100644 index 0000000..ac68e26 --- /dev/null +++ b/teiv/src/test/resources/contracts/data/06_getRelationshipsByType.groovy @@ -0,0 +1,707 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get topology relationships of type MANAGEDELEMENT_MANAGES_GNBDUFUNCTION(OneToMany)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6BD25E5C8FB7842F69010736253CC47F43535D7238E9E9A03E8092E8C019C83270DE47C96EF1049C40B83A130F9F129AE93B9C8538B6B004AE89BD0A098E48DD" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=9243B48F7D6A6CF471226915C74CF5FE4BDA6FA3CF7D897473007B46DF7FC50230BD6B8B4256116A6AFBF4D822CF9379EB56DE9490C1C0B54238263F2574B426" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBDUFunction=28", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=ADD4A82DFBAF0409FA9D3C929A09314088627B447C733429D4EE7AAE2FFAEE4894F90826B6814B63431EC07140783C7861E463C5AF8330E29469D704675EAB43" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500" + }, + "totalCount": 7 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(7) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + jsonPath('$.items[6].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[6].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].aSide', byEquality()) + jsonPath('$.items[6].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].bSide', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type NRSECTORCARRIER_USES_ANTENNACAPABILITY(ManyToOne)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=1", + "id": "urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=11EDFC31E2BE240D3CB15DB1A3FA3B78C828524BC8FCA3365A615129A61A627C21DA8EBF6DD788CDBDEC668344D1F79A371749083D6AE04DDDD57CB4FA8C3ECB" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=3", + "id": "urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=1B891FCC4F5479BC71127ED2EB43EA26AC3452F8C47792786373442C10BBC408FE5B779BF1CF732C81220803342F4FB969E348F9C5CEEDEC78F9764E186C633F" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRSECTORCARRIER_USES_ANTENNACAPABILITY": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=2", + "id": "urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=27DF07D016FE349EC565DE2FB09303EE7D8700346624046F79D8DAC176E7FA221E918E3030758B51931C430919E14FD7D16720460F6E1585000C72874A1641DA" + } + ] + } + ], + "self": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/relationship-types/NRSECTORCARRIER_USES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "totalCount": 3 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type ANTENNAMODULE_SERVES_ANTENNACAPABILITY(ManyToMany)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1", + "aSide": "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "id": "urn:o-ran:smo:teiv:sha512:ANTENNAMODULE_SERVES_ANTENNACAPABILITY=8940999E2069725B463052BC35572FDB888C7B734459EE78A01B9F91E2607D87356425BC8EFF0B1C9057D852A4D3F9E1B09479D32FEE68C65EF2821B65F7BD80" + } + ] + }, + { + "o-ran-smo-teiv-rel-equipment-ran:ANTENNAMODULE_SERVES_ANTENNACAPABILITY": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", + "aSide": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A", + "id": "urn:o-ran:smo:teiv:sha512:ANTENNAMODULE_SERVES_ANTENNACAPABILITY=ABD52B030DF1169F9F41C898913EF30F7BB5741F53352F482310B280C90AC569B7D31D52A2BB41F1F0099AE1EDD56CACF0B285D145A5584D376DD45DED1E2D65" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/ANTENNAMODULE_SERVES_ANTENNACAPABILITY/relationships?offset=0&limit=500" + }, + "totalCount": 2 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type MANAGEDELEMENT_MANAGES_GNBDUFUNCTION with offset=1 and limit=1." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=1&limit=1" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19", + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6BD25E5C8FB7842F69010736253CC47F43535D7238E9E9A03E8092E8C019C83270DE47C96EF1049C40B83A130F9F129AE93B9C8538B6B004AE89BD0A098E48DD" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=1&limit=1" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=1" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=1" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=2&limit=1" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=6&limit=1" + }, + "totalCount": 7 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS where used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters id is 'Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + } + ], + "self": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + }, + "first": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + }, + "prev": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + }, + "next": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + }, + "last": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType1']" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS where used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters id is 'Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + } + ], + "self": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + }, + "first": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + }, + "prev": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + }, + "next": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + }, + "last": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=100&scopeFilter=/used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters[@id='LongEntityType2']" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type SECTOR_GROUPS_NRCELLDU where grouped-nrCellDu id is 'urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "Sector=2", + "id": "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/grouped-nrCellDu[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].bSide', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships of type SECTOR_GROUPS_NRCELLDU where relation id is 'urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463'." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "Sector=2", + "id": "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463" + } + ] + } + ], + "self": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + }, + "first": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + }, + "prev": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + }, + "next": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + }, + "last": { + "href": "/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships?offset=0&limit=100&scopeFilter=/SECTOR_GROUPS_NRCELLDU[@id='urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:SECTOR_GROUPS_NRCELLDU[0].bSide', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get topology relationships for same entity long relationship name of type ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType2", + "aSide": "LongEntityType1", + "id": "Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2" + } + ] + }, + { + "test-built-in-module:ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS": [ + { + "bSide": "LongEntityType3", + "aSide": "LongEntityType2", + "id": "Rel_OneToOne_SameEntity_LongEntityType2_LongEntityType3" + } + ] + } + ], + "self": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/TEST/relationship-types/ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS/relationships?offset=0&limit=500" + }, + "totalCount": 2 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get empty items array when no relationship exists of given type." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION": [] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_ENODEBFUNCTION/relationships?offset=0&limit=500" + }, + "totalCount": 0 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get relationship by type checking total count" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=714C1B73945C298CAA03FE0D800053CDD1C571BBF375DC647B9F23FDA861CEB369832A3593BB1AA4B8A7245AD187ED24ADDF6FB147130827CDC17BA8370C4838" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=93", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=7723E5D5B3332E0890EAA620C77A6A47065E15A2EA28AD83F3B3CFEA5A7E3BB5965AE78890F1BF000EAA89BF8DE209E506192BF5EA6871426603ED76CBFAF088" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=78ECC09D4832328976EF0F9C19699EE05D98E3837368D386AE39AD027543494AC620086BD2A7403DACFAA7B474B3DEBD313E0906F1EDE7FA2B584E16542A706A" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=92", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=DDECCEFB8831FA4EB21B121BA35EAB07ED8D841B5A38580C5F3AD11E66FE73D2FC42E823C6C73288860C7562B610C3D07B6C39FD386171A3BE622096F4B3D006" + } + ] + } + ], + "self": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=500" + }, + "first": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=500" + }, + "prev": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=500" + }, + "next": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=500" + }, + "last": { + "href": "/domains/RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships?offset=0&limit=500" + }, + "totalCount": 5 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(5) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].id', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].aSide', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU[0].bSide', byEquality()) + jsonPath('$.totalCount', byEquality()) + } + } + }, + Contract.make { + description "ERROR - 400: Get topology relationships of type MANAGEDELEMENT_MANAGES_GNBDUFUNCTION with invalid offset (greater than total count)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=1000" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 6" + }''') + } + }, + Contract.make { + description "ERROR - 400: Get topology relationships of type SECTOR_GROUPS_NRCELLDU with wrong domain." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/OAM/relationship-types/SECTOR_GROUPS_NRCELLDU/relationships" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Unknown relationship type", + "details": "Relationship type SECTOR_GROUPS_NRCELLDU is not part of the domain OAM, known relationship types: []" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/07_getRelationshipById.groovy b/teiv/src/test/resources/contracts/data/07_getRelationshipById.groovy new file mode 100644 index 0000000..d5f731b --- /dev/null +++ b/teiv/src/test/resources/contracts/data/07_getRelationshipById.groovy @@ -0,0 +1,90 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get relationship with specified id" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_EQUIPMENT_RAN/relationship-types/SECTOR_GROUPS_ANTENNAMODULE/relationships/urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512" + } + response { + status OK() + headers { + contentType('application/yang.data+json') + } + body('''{ + "o-ran-smo-teiv-rel-equipment-ran:SECTOR_GROUPS_ANTENNAMODULE": [ + { + "bSide": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A", + "aSide": "Sector=2", + "id": "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "sourceIds": [] + } + ] + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get relationship with specified id" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/GNBDUFUNCTION_PROVIDES_NRCELLDU/relationships/urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C" + } + response { + status OK() + headers { + contentType('application/yang.data+json') + } + body('''{ + "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ + { + "bSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "aSide": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", + "id": "urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C", + "sourceIds": [] + } + ] + }''') + } + }, + Contract.make { + description "ERROR - 400: Get relationship with non existing id 'non-existing-id'" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships/non-existing-id" + } + response { + status NOT_FOUND() + headers { + contentType('application/json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource is not found" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/data/08_getEntitiesByDomain.groovy b/teiv/src/test/resources/contracts/data/08_getEntitiesByDomain.groovy new file mode 100644 index 0000000..1f4026b --- /dev/null +++ b/teiv/src/test/resources/contracts/data/08_getEntitiesByDomain.groovy @@ -0,0 +1,784 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.data + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with targetFilter=/GNBDUFunction/attributes(gNBDUId)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": 16 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBDUFunction=28" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "gNBDUId": null + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/attributes(gNBDUId)" + }, + "totalCount": 7 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(7) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byRegex(anInteger()).asInteger()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + jsonPath('$.items[5].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + jsonPath('$.items[6].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[6].o-ran-smo-teiv-ran:GNBDUFunction[0].attributes.gNBDUId', byNull()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in TEIV domain with targetFilter=/AntennaModule;/GNBCUUPFunction." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUUPFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBCUUPFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBCUUPFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBCUUPFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBCUUPFunction=19" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBCUUPFunction=28" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9" + } + ] + }, + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + } + ] + }, + { + "o-ran-smo-teiv-equipment:AntennaModule": [ + { + "id": "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7" + } + ] + } + ], + "self": { + "href": "/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + }, + "first": { + "href": "/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + }, + "prev": { + "href": "/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + }, + "next": { + "href": "/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + }, + "last": { + "href": "/domains/TEIV/entities?offset=0&limit=100&targetFilter=/AntennaModule;/GNBCUUPFunction" + }, + "totalCount": 9 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(9) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[3].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[4].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[5].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[6].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[7].o-ran-smo-teiv-equipment:AntennaModule[0].id', byEquality()) + jsonPath('$.items[8].o-ran-smo-teiv-equipment:AntennaModule[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')] or /NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')] and targetFilter=/NRCellDU/sourceIds." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]&targetFilter=/NRCellDU/sourceIds" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "sourceIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU":[ + { + "id":"urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2", + "sourceIds":[ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2", + "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616" + ] + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/sourceIds&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/sourceIds&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/sourceIds&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/sourceIds&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/sourceIds&scopeFilter=/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]|/NRCellDU/sourceIds[contains(@item,'ManagedElement=9,GNBDUFunction=9,NRCellDU=2')]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].sourceIds[0]', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].sourceIds[1]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].sourceIds[0]', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].sourceIds[1]', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter=/NRCellDU/attributes[@cellLocalId=1] and targetFilter=/NRCellDU/attributes(nCI)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]&targetFilter=/NRCellDU/attributes(nCI)" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", + "attributes": { + "nCI": 1 + } + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/attributes(nCI)&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/attributes(nCI)&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/attributes(nCI)&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/attributes(nCI)&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU/attributes(nCI)&scopeFilter=/NRCellDU/attributes[@cellLocalId=1]" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].attributes.nCI', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get topology for an entity with given ID (exact ID match) without knowing entity type." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/id[text()='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2']" + }, + "totalCount": 1 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(1) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get empty items array when no entity exists of given filter criteria." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]&targetFilter=/NRCellDU" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/NRCellDU&scopeFilter=/NRCellDU/attributes[@cellLocalId=8989439]" + }, + "totalCount": 0 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(0) + }) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10'] and targetFilter=/attributes." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=500&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']&targetFilter=/attributes" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "attributes": { + "gNBId": 10, + "gNBIdLength": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUUPFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "82" + }, + "gNBId": 10, + "gNBDUId": null, + "gNBIdLength": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "attributes": { + "gNBId": 10, + "pLMNId": { + "mcc": "01", + "mnc": "234" + }, + "gNBIdLength": 2, + "gNBCUName": "gnbcucp-10" + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUCPFunction=10" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBCUCPFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter=/managed-by-managedElement; /attributes[@gNBId=10] and targetFilter=/attributes." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=500&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']&targetFilter=/attributes" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBCUUPFunction": [ + { + "attributes": { + "gNBId": 10, + "gNBIdLength": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUUPFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "82" + }, + "gNBId": 10, + "gNBDUId": null, + "gNBIdLength": 2 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBCUCPFunction": [ + { + "attributes": { + "gNBId": 10, + "pLMNId": { + "mcc": "01", + "mnc": "234" + }, + "gNBIdLength": 2, + "gNBCUName": "gnbcucp-10" + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUCPFunction=10" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes&scopeFilter=/managed-by-managedElement[@id='urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBCUUPFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBCUCPFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1] and targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=500&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "attributes": { + "dUpLMNId": { + "mcc": "456", + "mnc": "82" + }, + "gNBId": 9 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&targetFilter=/attributes(gNBId, dUpLMNId); /NRCellDU&scopeFilter=/attributes[@gNBIdLength=1]; /NRCellDU/attributes[@nCI=1]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get entities in RAN domain with scopeFilter on 2 different entity types and combining the condition on complex attributes" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + }, + { + "o-ran-smo-teiv-ran:NRCellDU": [ + { + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=500&scopeFilter=/NRCellDU/attributes[@nCI=1];/GNBDUFunction/attributes/dUpLMNId[@mcc='456' or @mnc='83']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:NRCellDU[0].id', byEquality()) + } + } + }, + Contract.make { + description "ERROR - 400: Get entities in RAN domain with invalid offset (greater than total count)." + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?&targetFilter=/NRCellDU;&offset=1000" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 5" + }''') + } + }, + Contract.make { + description "Error - 400: Get entities with wrong syntax items instead of item with scopeFilter=/NRCellDU/sourceIds[contains(@items,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&scopeFilter=/NRCellDU/sourceIds[contains(@items,'ManagedElement=9,GNBDUFunction=9,NRCellDU=1')]" + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid parameter error", + "details": "Invalid source id parameter provided for NRCellDU" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/decorators/00_getDecorators_getTopologyByEntityTypeName.groovy b/teiv/src/test/resources/contracts/decorators/00_getDecorators_getTopologyByEntityTypeName.groovy new file mode 100644 index 0000000..171bce6 --- /dev/null +++ b/teiv/src/test/resources/contracts/decorators/00_getDecorators_getTopologyByEntityTypeName.groovy @@ -0,0 +1,236 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.decorators + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get decorators using getTopologyByEntityTypeName - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 456 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getTopologyByEntityTypeName - CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 456 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getTopologyByEntityTypeName - CONTAINS and EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + }, + "first": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + }, + "prev": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + }, + "next": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + }, + "last": { + "href": "/domains/RAN/entity-types/GNBDUFunction/entities?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + } +] diff --git a/teiv/src/test/resources/contracts/decorators/01_getDecorators_getRelationshipsByType.groovy b/teiv/src/test/resources/contracts/decorators/01_getDecorators_getRelationshipsByType.groovy new file mode 100644 index 0000000..8fa81d9 --- /dev/null +++ b/teiv/src/test/resources/contracts/decorators/01_getDecorators_getRelationshipsByType.groovy @@ -0,0 +1,236 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.decorators + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get decorators using getRelationshipsByType - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 456 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']&targetFilter=/decorators" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']&targetFilter=/decorators" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']&targetFilter=/decorators" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']&targetFilter=/decorators" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[@test-app-module:textdata = 'Stockholm']&targetFilter=/decorators" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getRelationshipsByType - CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 456 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]&targetFilter=/decorators" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]&targetFilter=/decorators" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]&targetFilter=/decorators" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]&targetFilter=/decorators" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')]&targetFilter=/decorators" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getRelationshipsByType - CONTAINS and EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&targetFilter=/decorators&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA" + } + ] + }, + { + "o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE" + } + ] + } + ], + "self": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]&targetFilter=/decorators" + }, + "first": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]&targetFilter=/decorators" + }, + "prev": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]&targetFilter=/decorators" + }, + "next": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]&targetFilter=/decorators" + }, + "last": { + "href": "/domains/REL_OAM_RAN/relationship-types/MANAGEDELEMENT_MANAGES_GNBDUFUNCTION/relationships?offset=0&limit=500&scopeFilter=/decorators[contains(@test-app-module:textdata, 'Stock')] ; /decorators[@test-app-module:intdata = 123]&targetFilter=/decorators" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-rel-oam-ran:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION[0].id', byEquality()) + } + } + } +] diff --git a/teiv/src/test/resources/contracts/decorators/02_getDecorators_getEntitiesByDomain.groovy b/teiv/src/test/resources/contracts/decorators/02_getDecorators_getEntitiesByDomain.groovy new file mode 100644 index 0000000..08ff2a6 --- /dev/null +++ b/teiv/src/test/resources/contracts/decorators/02_getDecorators_getEntitiesByDomain.groovy @@ -0,0 +1,236 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.decorators + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get decorators using getEntitiesByDomain - EQUALS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123]" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getEntitiesByDomain - CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 456 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "totalCount": 3 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(3) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[2].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get decorators using getEntitiesByDomain - EQUALS and CONTAINS" + request { + method GET() + url "/topology-inventory/v1alpha11/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + } + ] + }, + { + "o-ran-smo-teiv-ran:GNBDUFunction": [ + { + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "id": "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16" + } + ] + } + ], + "self": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "first": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "prev": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "next": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "last": { + "href": "/domains/RAN/entities?offset=0&limit=100&targetFilter=/GNBDUFunction/decorators&scopeFilter=/GNBDUFunction/decorators[@test-app-module:intdata=123];/GNBDUFunction/decorators[contains(@test-app-module:textdata,'Stock')]" + }, + "totalCount": 2 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(2) + }) + jsonPath('$.items[0].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + jsonPath('$.items[1].o-ran-smo-teiv-ran:GNBDUFunction[0].id', byEquality()) + } + } + } +] diff --git a/teiv/src/test/resources/contracts/decorators/03_postDecoratorsMerge.groovy b/teiv/src/test/resources/contracts/decorators/03_postDecoratorsMerge.groovy new file mode 100644 index 0000000..77a72b3 --- /dev/null +++ b/teiv/src/test/resources/contracts/decorators/03_postDecoratorsMerge.groovy @@ -0,0 +1,310 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.decorators + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "NOT FOUND - 404: Merge decorators with wrong entity ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: []" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Merge decorators with wrong relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "WRONG_RELATIONSHIP_ID" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [] Relationships: [WRONG_RELATIONSHIP_ID]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Merge decorators with wrong entity and relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "relationshipIds": [ + "WRONG_RELATIONSHIP_ID" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: [WRONG_RELATIONSHIP_ID]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Merge invalid decorators." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:te": "Budapest", + "test-app-module:intdata": "123" + }, + "entityIds": [ + "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512" + ], + "operation": "merge" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Invalid decorators", + "details": "The provided decorators are invalid {test-app-module:intdata=is_not_compatible, test-app-module:te=is_not_available}" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid decorators, no topology object given." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid decorators to entities (add)." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid decorators to relationships (add)." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=CEEC51BE136D671D2101C09FEDD8A1D95E1E177A4818E9FC0D6E63E610BC8FE26FC9C729A1E58AD43D70472F4CD54403E25CB1E5D2BBA66966625C21435C4A78" + ], + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid decorators to entities and relationships (add)." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Budapest", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512" + ], + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Merge valid decorators to entities and relationships (update)." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Athlone", + "test-app-module:intdata": 456 + }, + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328" + ], + "operation": "merge" + }''') + } + response { + status NO_CONTENT() + } + } +] diff --git a/teiv/src/test/resources/contracts/decorators/04_postDecoratorsDelete.groovy b/teiv/src/test/resources/contracts/decorators/04_postDecoratorsDelete.groovy new file mode 100644 index 0000000..16143f9 --- /dev/null +++ b/teiv/src/test/resources/contracts/decorators/04_postDecoratorsDelete.groovy @@ -0,0 +1,301 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.decorators + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "NOT FOUND - 404: Delete decorators with wrong entity ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 1 + }, + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "operation": "delete" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: []" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Delete decorators with wrong relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 2 + }, + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512", + "WRONG_RELATIONSHIP_ID" + ], + "operation": "delete" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [] Relationships: [WRONG_RELATIONSHIP_ID]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "NOT FOUND - 404: Delete decorators with wrong entity and relationship ids." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 3 + }, + "entityIds": [ + "WRONG_ENTITY_ID", + "urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A" + ], + "relationshipIds": [ + "WRONG_RELATIONSHIP_ID" + ], + "operation": "delete" + }''') + } + response { + status NOT_FOUND() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "NOT_FOUND", + "message": "Resource Not Found", + "details": "The requested resource with the following ids cannot be found. Entities: [WRONG_ENTITY_ID] Relationships: [WRONG_RELATIONSHIP_ID]" + }''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "BAD REQUEST - 400: Delete decorators from non-existing schema." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module-wrong:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "operation": "delete" + }''') + } + response { + status BAD_REQUEST() + headers { + contentType('application/problem+json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: test-app-module-wrong"}''') + bodyMatchers { + jsonPath('$.status', byEquality()) + jsonPath('$.message', byEquality()) + jsonPath('$.details', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 204: Delete invalid decorators, no topology object given." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid decorators, no topology object given." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid decorators on entities." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid decorators on relationships." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA", + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "SUCCESS - 204: Delete valid decorators on entities and relationships." + request { + method POST() + url "/topology-inventory/v1alpha11/decorators" + headers { + contentType("application/json") + accept('application/problem+json') + } + body('''{ + "decorators": { + "test-app-module:textdata": "Stockholm", + "test-app-module:intdata": 123 + }, + "entityIds": [ + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", + "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14" + ], + "relationshipIds": [ + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA", + "urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7" + ], + "operation": "delete" + }''') + } + response { + status NO_CONTENT() + } + } +] diff --git a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getAllRelationships.groovy b/teiv/src/test/resources/contracts/ran/GNBDUFunction/getAllRelationships.groovy deleted file mode 100644 index 2b78695..0000000 --- a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getAllRelationships.groovy +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.GNBDUFunction - -import org.springframework.cloud.contract.spec.Contract - -[ - Contract.make { - description "SUCCESS - 200: Get a list of all relationships for GNBDUFunction 1" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [ - { - "o-ran-smo-teiv-ran:GNBDUFUNCTION_PROVIDES_NRCELLDU": [ - { - "id": "urn:sha512:R05CRFVGdW5jdGlvbjpTdWJOZXR3b3JrPUV1cm9wZSxTdWJOZXR3", - "aSide": "urn:3gpp:dn:ManagedElement=1,GNBDUFunction=1", - "bSide": "urn:3gpp:dn:ManagedElement=1,GNBDUFunction=1,NRCellDU=1", - "decorators": { - "location": "Stockholm" - }, - "classifiers": [ - "Rural" - ], - "sourceIds": [], - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] - } - ], - "self": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - }, - "first": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - }, - "prev": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - }, - "next": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - }, - "last": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FManagedElement%3D1%2FGNBDUFunction%3D1/relationships?offset=0&limit=100" - } -}''') - } - }, - Contract.make { - description "BAD_REQUEST - 400: Get a list of all relationships for an unknown objectType" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/5GCell/entities/R05CRFVGdW5jdGlvbg/relationships?offset=1&limit=100" - } - response { - status BAD_REQUEST() - } - } -] diff --git a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyById.groovy b/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyById.groovy deleted file mode 100644 index 07f37dc..0000000 --- a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyById.groovy +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.GNBDUFunction - -import org.springframework.cloud.contract.spec.Contract - -[ - Contract.make { - description "SUCCESS - 200: Get topology for object type by GNBDUFunction 1" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1") - } - response { - status OK() - headers { - contentType('application/yang.data+json') - } - body('''{ - "o-ran-smo-teiv-ran:GNBDUFunction": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1", - "attributes": { - "gNBId": 1, - "gNBDUId": 1, - "gNBIdLength": 2, - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - } - }, - "decorators": { - "location": "Stockholm" - }, - "classifiers": [ - "Rural" - ], - "sourceIds": [ - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1" - ], - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] -}''') - } - }, - Contract.make { - description "SUCCESS - 200: Get topology for object type by GNBDUFunction 2" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D2") - } - response { - status OK() - headers { - contentType('application/yang.data+json') - } - body('''{ - "o-ran-smo-teiv-ran:GNBDUFunction": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=2", - "attributes": { - "gNBId": 2, - "gNBDUId": 2, - "gNBIdLength": 2, - "dUpLMNId": { - "mcc": "110", - "mnc": "210" - } - }, - "decorators": { - "location": "Stockholm" - }, - "classifiers": [ - "Rural" - ], - "sourceIds": [ - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=2" - ], - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] -}''') - } - }, - Contract.make { - description "NOT_FOUND - 404: Get unknown for object type by GNBDUFunction 1" - request { - method GET() - url "/ties/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1" - } - response { - status NOT_FOUND() - } - }, - Contract.make { - description "BAD_REQUEST - 400: Get topology for unknown object type by GNBDUFunction 1" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GBFunction/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio00001%2FGNBDUFunction%3D1" - } - response { - status BAD_REQUEST() - } - } -] diff --git a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyByType.groovy b/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyByType.groovy deleted file mode 100644 index e8426b5..0000000 --- a/teiv/src/test/resources/contracts/ran/GNBDUFunction/getTopologyByType.groovy +++ /dev/null @@ -1,162 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.GNBDUFunction - -import org.springframework.cloud.contract.spec.Contract - -[ - /************************** - * 'targetFilter' query parameter - ***************************/ - Contract.make { - description "SUCCESS - 200: Get topology for GNBDUFunction using 'targetFilter' query parameter" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50") - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [ - { - "o-ran-smo-teiv-ran:GNBDUFunction": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1", - "attributes": { - "gNBDUId": 1 - }, - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] - } - ], - "self": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50" - }, - "first": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50" - }, - "prev": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50" - }, - "next": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50" - }, - "last": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&offset=0&limit=50" - } -}''') - } - }, - Contract.make { - description "NOT_FOUND - 404: Get topology for GNBDUFunction using unknown 'targetFilter' query parameter" - request { - method GET() - url "/ties/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2F%2FGNBDUFunction&offset=1&limit=100" - } - response { - status NOT_FOUND() - } - }, - Contract.make { - description "BAD_REQUEST - 400: The provided request is not valid" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBBUFunction/entities?targetFilter=%2F%2FGNBBUFunction&offset=1&limit=100" - } - response { - status BAD_REQUEST() - } - }, - /*************************************** - * 'targetFilter' and 'scopeFilter' query parameter - ****************************************/ - Contract.make { - description "SUCCESS - 200: Get topology for GNBDUFunction using 'targetFilter' and 'scopeFilter' query parameter" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100") - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [ - { - "o-ran-smo-teiv-ran:GNBDUFunction": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1", - "attributes": { - "gNBDUId": 1 - }, - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] - } - ], - "self": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100" - }, - "first": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100" - }, - "prev": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100" - }, - "next": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100" - }, - "last": { - "href": "/domains/RAN/entity-types/GNBDUFunction/entities?targetFilter=%2Fattributes(gNBDUId)&scopeFilter=%2Fattributes[@gNBDUId=1]&offset=0&limit=100" - } -}''') - } - }, - Contract.make { - description "NOT_FOUND - 404: Get unknown for GNBCUCPFunction using 'targetFilter' and 'scopeFilter' query parameter" - request { - method GET() - url "/ties/v1alpha11/domains/RAN/entity-type/GNBDUFunction/entities?targetFilter=%2F%2FGNBDUFunction&scopeFilter=%2F%2FNRCellDU%2FnRTAC%3D50&offset=1&limit=100" - } - response { - status NOT_FOUND() - } - }, - Contract.make { - description "BAD_REQUEST - 400: The provided request is not valid" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/GNBBUFunction/entities?targetFilter=%2F%2FGNBDUFunction&scopeFilter=%2F%2FNRCellDU%2FnRTAC%3D50&offset=1&limit=100" - } - response { - status BAD_REQUEST() - } - } -] diff --git a/teiv/src/test/resources/contracts/ran/NRCellDU/getTopologyById.groovy b/teiv/src/test/resources/contracts/ran/NRCellDU/getTopologyById.groovy deleted file mode 100644 index 20f1580..0000000 --- a/teiv/src/test/resources/contracts/ran/NRCellDU/getTopologyById.groovy +++ /dev/null @@ -1,122 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.NRCellDU - -import org.springframework.cloud.contract.spec.Contract - -[ - Contract.make { - description "SUCCESS - 200: Get topology for object type by NRCellDU 1" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D1") - } - response { - status OK() - headers { - contentType('application/yang.data+json') - } - body('''{ - "o-ran-smo-teiv-ran:NRCellDU": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=1", - "attributes": { - "cellLocalId": 91, - "nCI": 1, - "nRPCI": 35, - "nRTAC": 50 - }, - "decorators": { - "location": "Stockholm" - }, - "classifiers": [ - "Rural" - ], - "sourceIds": [ - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=1" - ], - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] -}''') - } - }, - Contract.make { - description "SUCCESS - 200: Get topology for object type by NRCellDU 2" - request { - method GET() - url("/topology-inventory/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D2") - } - response { - status OK() - headers { - contentType('application/yang.data+json') - } - body('''{ - "o-ran-smo-teiv-ran:NRCellDU": [ - { - "id": "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=2", - "attributes": { - "cellLocalId": 95, - "nCI": 5, - "nRPCI": 35, - "nRTAC": 50 - }, - "decorators": { - "location": "Stockholm" - }, - "classifiers": [ - "Rural" - ], - "sourceIds": [ - "urn:3gpp:dn:MeContext=NR01,ManagedElement=NR01gNodeBRadio,GNBDUFunction=1,NRCellDU=2" - ], - "metadata": { - "trustLevel": "RELIABLE" - } - } - ] -}''') - } - }, - Contract.make { - description "NOT_FOUND - 404: Get unknown for object type by NRCellDU 1" - request { - method GET() - url "/ties/v1alpha11/domains/RAN/entity-types/NRCellDU/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D1" - } - response { - status NOT_FOUND() - } - }, - Contract.make { - description "BAD_REQUEST - 400: Get topology for unknown object type by NRCellDU 1" - request { - method GET() - url "/topology-inventory/v1alpha11/domains/RAN/entity-types/NRDU/entities/urn%3A3gpp%3Adn%3A%2FMeContext%3DNR01%2FManagedElement%3DNR01gNodeBRadio%2FGNBDUFunction%3D1%2FNRCellDU%3D1" - } - response { - status BAD_REQUEST() - } - } -] diff --git a/teiv/src/test/resources/contracts/ran/schemas/getAllSchemas.groovy b/teiv/src/test/resources/contracts/ran/schemas/getAllSchemas.groovy deleted file mode 100644 index 0135d2d..0000000 --- a/teiv/src/test/resources/contracts/ran/schemas/getAllSchemas.groovy +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.schemas -import org.springframework.cloud.contract.spec.Contract - -[ - Contract.make { - description "SUCCESS - 200: Get a list of all schemas" - request { - method GET() - url("/topology-inventory/v1alpha11/schemas?offset=0&limit=100") - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [ - { - "name": "o-ran-smo-teiv-cloud-to-ran", - "domain": "CLOUD_TO_RAN", - "revision": "2023-06-26", - "content": { - "href": "/schemas/o-ran-smo-teiv-cloud-to-ran/content" - } - } - ], - "self": { - "href": "/schemas?offset=0&limit=100" - }, - "first": { - "href": "/schemas?offset=0&limit=100" - }, - "prev": { - "href": "/schemas?offset=0&limit=100" - }, - "next": { - "href": "/schemas?offset=0&limit=100" - }, - "last": { - "href": "/schemas?offset=0&limit=100" - } -}''') - } - } -] diff --git a/teiv/src/test/resources/contracts/ran/schemas/getSchemasInDomain.groovy b/teiv/src/test/resources/contracts/ran/schemas/getSchemasInDomain.groovy deleted file mode 100644 index f754260..0000000 --- a/teiv/src/test/resources/contracts/ran/schemas/getSchemasInDomain.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 Ericsson - * Modifications Copyright (C) 2024 OpenInfra Foundation Europe - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package contracts.ran.schemas -import org.springframework.cloud.contract.spec.Contract - -[ - Contract.make { - description "SUCCESS - 200: Get a list of all schemas in RAN domain" - request { - method GET() - url("/topology-inventory/v1alpha11/schemas?domain=RAN&offset=0&limit=8") - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [ - { - "name": "o-ran-smo-teiv-cloud-to-ran", - "domain": "CLOUD_TO_RAN", - "revision": "2023-06-26", - "content": { - "href": "/schemas/o-ran-smo-teiv-cloud-to-ran/content" - } - } - ], - "self": { - "href": "/schemas?domain=RAN&offset=0&limit=8" - }, - "first": { - "href": "/schemas?domain=RAN&offset=0&limit=8" - }, - "prev": { - "href": "/schemas?domain=RAN&offset=0&limit=8" - }, - "next": { - "href": "/schemas?domain=RAN&offset=0&limit=8" - }, - "last": { - "href": "/schemas?domain=RAN&offset=0&limit=8" - } -}''') - } - }, - Contract.make { - description "SUCCESS - Get list of all schemas in unknown domain" - request { - method GET() - url("/topology-inventory/v1alpha11/schemas?domain=LOGICAL") - } - response { - status OK() - headers { - contentType('application/json') - } - body('''{ - "items": [], - "self": { - "href": "/schemas?domain=LOGICAL&offset=0&limit=500" - }, - "first": { - "href": "/schemas?domain=LOGICAL&offset=0&limit=500" - }, - "prev": { - "href": "/schemas?domain=LOGICAL&offset=0&limit=500" - }, - "next": { - "href": "/schemas?domain=LOGICAL&offset=0&limit=500" - }, - "last": { - "href": "/schemas?domain=LOGICAL&offset=0&limit=500" - } -}''') - } - } -] diff --git a/teiv/src/test/resources/contracts/schemas/00_getAllSchemas.groovy b/teiv/src/test/resources/contracts/schemas/00_getAllSchemas.groovy new file mode 100644 index 0000000..3294d3d --- /dev/null +++ b/teiv/src/test/resources/contracts/schemas/00_getAllSchemas.groovy @@ -0,0 +1,534 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.schemas + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get a list of all schemas" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "_3gpp-common-yang-extensions", + "domain": "", + "revision": "2019-06-23", + "content": { + "href": "/schemas/_3gpp-common-yang-extensions/content" + } + }, + { + "name": "_3gpp-common-yang-types", + "domain": "", + "revision": "2023-11-06", + "content": { + "href": "/schemas/_3gpp-common-yang-types/content" + } + }, + { + "name": "ietf-geo-location", + "domain": "", + "revision": "2022-02-11", + "content": { + "href": "/schemas/ietf-geo-location/content" + } + }, + { + "name": "ietf-inet-types", + "domain": "", + "revision": "2013-07-15", + "content": { + "href": "/schemas/ietf-inet-types/content" + } + }, + { + "name": "ietf-yang-types", + "domain": "", + "revision": "2013-07-15", + "content": { + "href": "/schemas/ietf-yang-types/content" + } + }, + { + "name": "o-ran-smo-teiv-common-yang-extensions", + "domain": "", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-common-yang-extensions/content" + } + }, + { + "name": "o-ran-smo-teiv-common-yang-types", + "domain": "", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-common-yang-types/content" + } + }, + { + "name": "o-ran-smo-teiv-equipment", + "domain": "EQUIPMENT", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-equipment/content" + } + }, + { + "name": "o-ran-smo-teiv-oam", + "domain": "OAM", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-oam/content" + } + }, + { + "name": "o-ran-smo-teiv-ran", + "domain": "RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-ran/content" + } + }, + { + "name": "o-ran-smo-teiv-rel-equipment-ran", + "domain": "REL_EQUIPMENT_RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-rel-equipment-ran/content" + } + }, + { + "name": "o-ran-smo-teiv-rel-oam-ran", + "domain": "REL_OAM_RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-rel-oam-ran/content" + } + }, + { + "name": "test-existing-rapp-module", + "domain": "", + "revision": "2024-05-02", + "content": { + "href": "/schemas/test-existing-rapp-module/content" + } + }, + { + "name": "test-module-for-deletion", + "domain": "", + "revision": "2024-05-02", + "content": { + "href": "/schemas/test-module-for-deletion/content" + } + }, + { + "name":"test-module-in-deleting-state", + "domain":"", + "revision":"2024-05-02", + "content":{ + "href":"/schemas/test-module-in-deleting-state/content" + } + }, + { + "name":"module-rapp-module", + "domain":"", + "revision":"2024-05-01", + "content":{ + "href":"/schemas/module-rapp-module/content" + } + }, + { + "name": "test-built-in-module", + "domain": "TEST", + "revision": "2024-05-24", + "content": { + "href": "/schemas/test-built-in-module/content" + } + }, + { + "name": "test-app-module", + "domain": "", + "revision": "2024-05-24", + "content": { + "href": "/schemas/test-app-module/content" + } + }, + { + "name": "test-app-for-deletion-module", + "domain": "", + "revision": "2024-05-24", + "content": { + "href": "/schemas/test-app-for-deletion-module/content" + } + } + ], + "self": { + "href": "/schemas?offset=0&limit=500" + }, + "first": { + "href": "/schemas?offset=0&limit=500" + }, + "prev": { + "href": "/schemas?offset=0&limit=500" + }, + "next": { + "href": "/schemas?offset=0&limit=500" + }, + "last": { + "href": "/schemas?offset=0&limit=500" + }, + "totalCount": 19 + }''') + bodyMatchers { + jsonPath('$.items', byType { + occurrence(19) + }) + jsonPath('$.items[0].name', byEquality()) + jsonPath('$.items[0].domain', byEquality()) + jsonPath('$.items[0].revision', byEquality()) + jsonPath('$.items[0].content.href', byEquality()) + jsonPath('$.items[1].name', byEquality()) + jsonPath('$.items[1].domain', byEquality()) + jsonPath('$.items[1].revision', byEquality()) + jsonPath('$.items[1].content.href', byEquality()) + jsonPath('$.items[2].name', byEquality()) + jsonPath('$.items[2].domain', byEquality()) + jsonPath('$.items[2].revision', byEquality()) + jsonPath('$.items[2].content.href', byEquality()) + jsonPath('$.items[3].name', byEquality()) + jsonPath('$.items[3].domain', byEquality()) + jsonPath('$.items[3].revision', byEquality()) + jsonPath('$.items[3].content.href', byEquality()) + jsonPath('$.items[4].name', byEquality()) + jsonPath('$.items[4].domain', byEquality()) + jsonPath('$.items[4].revision', byEquality()) + jsonPath('$.items[4].content.href', byEquality()) + jsonPath('$.items[5].name', byEquality()) + jsonPath('$.items[5].domain', byEquality()) + jsonPath('$.items[5].revision', byEquality()) + jsonPath('$.items[5].content.href', byEquality()) + jsonPath('$.items[6].name', byEquality()) + jsonPath('$.items[6].domain', byEquality()) + jsonPath('$.items[6].revision', byEquality()) + jsonPath('$.items[6].content.href', byEquality()) + jsonPath('$.items[7].name', byEquality()) + jsonPath('$.items[7].domain', byEquality()) + jsonPath('$.items[7].revision', byEquality()) + jsonPath('$.items[7].content.href', byEquality()) + jsonPath('$.items[8].name', byEquality()) + jsonPath('$.items[8].domain', byEquality()) + jsonPath('$.items[8].revision', byEquality()) + jsonPath('$.items[8].content.href', byEquality()) + jsonPath('$.items[9].name', byEquality()) + jsonPath('$.items[9].domain', byEquality()) + jsonPath('$.items[9].revision', byEquality()) + jsonPath('$.items[9].content.href', byEquality()) + jsonPath('$.items[10].name', byEquality()) + jsonPath('$.items[10].domain', byEquality()) + jsonPath('$.items[10].revision', byEquality()) + jsonPath('$.items[10].content.href', byEquality()) + jsonPath('$.items[11].name', byEquality()) + jsonPath('$.items[11].domain', byEquality()) + jsonPath('$.items[11].revision', byEquality()) + jsonPath('$.items[11].content.href', byEquality()) + jsonPath('$.items[12].name', byEquality()) + jsonPath('$.items[12].domain', byEquality()) + jsonPath('$.items[12].revision', byEquality()) + jsonPath('$.items[12].content.href', byEquality()) + jsonPath('$.items[13].name', byEquality()) + jsonPath('$.items[13].domain', byEquality()) + jsonPath('$.items[13].revision', byEquality()) + jsonPath('$.items[13].content.href', byEquality()) + jsonPath('$.items[14].name', byEquality()) + jsonPath('$.items[14].domain', byEquality()) + jsonPath('$.items[14].revision', byEquality()) + jsonPath('$.items[14].content.href', byEquality()) + jsonPath('$.items[16].name', byEquality()) + jsonPath('$.items[16].domain', byEquality()) + jsonPath('$.items[16].revision', byEquality()) + jsonPath('$.items[16].content.href', byEquality()) + jsonPath('$.items[17].name', byEquality()) + jsonPath('$.items[17].domain', byEquality()) + jsonPath('$.items[17].revision', byEquality()) + jsonPath('$.items[17].content.href', byEquality()) + jsonPath('$.items[18].name', byEquality()) + jsonPath('$.items[18].domain', byEquality()) + jsonPath('$.items[18].revision', byEquality()) + jsonPath('$.items[18].content.href', byEquality()) + } + } + }, + Contract.make { + description "SUCCESS - 200: Get a list of all schemas with offset as 0 and limit as 1." + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?offset=0&limit=1") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "_3gpp-common-yang-extensions", + "domain": "", + "revision": "2019-06-23", + "content": { + "href": "/schemas/_3gpp-common-yang-extensions/content" + } + } + ], + "self": { + "href": "/schemas?offset=0&limit=1" + }, + "first": { + "href": "/schemas?offset=0&limit=1" + }, + "prev": { + "href": "/schemas?offset=0&limit=1" + }, + "next": { + "href": "/schemas?offset=1&limit=1" + }, + "last": { + "href": "/schemas?offset=18&limit=1" + }, + "totalCount": 19 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get a list of all schemas with offset as 3 and limit as 3." + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?offset=3&limit=3") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "ietf-inet-types", + "domain": "", + "revision": "2013-07-15", + "content": { + "href": "/schemas/ietf-inet-types/content" + } + }, + { + "name": "ietf-yang-types", + "domain": "", + "revision": "2013-07-15", + "content": { + "href": "/schemas/ietf-yang-types/content" + } + }, + { + "name": "o-ran-smo-teiv-common-yang-extensions", + "domain": "", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-common-yang-extensions/content" + } + } + ], + "self": { + "href": "/schemas?offset=3&limit=3" + }, + "first": { + "href": "/schemas?offset=0&limit=3" + }, + "prev": { + "href": "/schemas?offset=0&limit=3" + }, + "next": { + "href": "/schemas?offset=6&limit=3" + }, + "last": { + "href": "/schemas?offset=18&limit=3" + }, + "totalCount": 19 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get a list of all schemas with RAN domain" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?domain=RAN&offset=0&limit=100") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "o-ran-smo-teiv-ran", + "domain": "RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-ran/content" + } + } + ], + "self": { + "href": "/schemas?offset=0&limit=100&domain=RAN" + }, + "first": { + "href": "/schemas?offset=0&limit=100&domain=RAN" + }, + "prev": { + "href": "/schemas?offset=0&limit=100&domain=RAN" + }, + "next": { + "href": "/schemas?offset=0&limit=100&domain=RAN" + }, + "last": { + "href": "/schemas?offset=0&limit=100&domain=RAN" + }, + "totalCount": 1 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get a list of all schemas with domain name containing RAN" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?domain=.*RAN.*") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [ + { + "name": "o-ran-smo-teiv-rel-oam-ran", + "domain": "REL_OAM_RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-rel-oam-ran/content" + } + }, + { + "name": "o-ran-smo-teiv-ran", + "domain": "RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-ran/content" + } + }, + { + "name": "o-ran-smo-teiv-rel-equipment-ran", + "domain": "REL_EQUIPMENT_RAN", + "revision": "2024-05-24", + "content": { + "href": "/schemas/o-ran-smo-teiv-rel-equipment-ran/content" + } + } + ], + "self": { + "href": "/schemas?offset=0&limit=500&domain=.*RAN.*" + }, + "first": { + "href": "/schemas?offset=0&limit=500&domain=.*RAN.*" + }, + "prev": { + "href": "/schemas?offset=0&limit=500&domain=.*RAN.*" + }, + "next": { + "href": "/schemas?offset=0&limit=500&domain=.*RAN.*" + }, + "last": { + "href": "/schemas?offset=0&limit=500&domain=.*RAN.*" + }, + "totalCount": 3 + }''') + } + }, + Contract.make { + description "SUCCESS - 200: Get a list of all schemas with invalid domain" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?domain=INVALID") + } + response { + status OK() + headers { + contentType('application/json') + } + body('''{ + "items": [], + "self": { + "href": "/schemas?offset=0&limit=500&domain=INVALID" + }, + "first": { + "href": "/schemas?offset=0&limit=500&domain=INVALID" + }, + "prev": { + "href": "/schemas?offset=0&limit=500&domain=INVALID" + }, + "next": { + "href": "/schemas?offset=0&limit=500&domain=INVALID" + }, + "last": { + "href": "/schemas?offset=0&limit=500&domain=INVALID" + }, + "totalCount": 0 + }''') + } + }, + Contract.make { + description "ERROR - 400: Get a list of all schemas with offset greater than totalCount" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas?domain=RAN.*&offset=100") + } + response { + status BAD_REQUEST() + headers { + contentType('application/json') + } + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid Value", + "details": "Offset cannot be larger than 0" + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/schemas/01_getSchemaContent.groovy b/teiv/src/test/resources/contracts/schemas/01_getSchemaContent.groovy new file mode 100644 index 0000000..994402d --- /dev/null +++ b/teiv/src/test/resources/contracts/schemas/01_getSchemaContent.groovy @@ -0,0 +1,177 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.schemas + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 200: Get schema with name o-ran-smo-teiv-rel-oam-ran" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas/o-ran-smo-teiv-rel-oam-ran/content") + } + response { + status OK() + body("module o-ran-smo-teiv-rel-oam-ran {\n" + + " yang-version 1.1;\n" + + " namespace \"urn:o-ran:smo-teiv-rel-oam-ran\";\n" + + " prefix or-teiv-rel-oamran;\n" + + "\n" + + " import o-ran-smo-teiv-common-yang-types { prefix or-teiv-types; }\n" + + "\n" + + " import o-ran-smo-teiv-common-yang-extensions { prefix or-teiv-yext; }\n" + + "\n" + + " import o-ran-smo-teiv-oam { prefix or-teiv-oam; }\n" + + "\n" + + " import o-ran-smo-teiv-ran { prefix or-teiv-ran; }\n" + + "\n" + + " organization \"ORAN\";\n" + + " contact \"The Authors\";\n" + + " description\n" + + " \"RAN O&M to Logical topology model.\n" + + "\n" + + " This model contains the RAN O&M to Logical topology relations\n" + + "\n" + + " Copyright (C) 2024 Ericsson\n" + + " Modifications Copyright (C) 2024 OpenInfra Foundation Europe\n" + + "\n" + + " Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\n" + + " you may not use this file except in compliance with the License.\n" + + " You may obtain a copy of the License at\n" + + "\n" + + " http://www.apache.org/licenses/LICENSE-2.0\n" + + "\n" + + " Unless required by applicable law or agreed to in writing, software\n" + + " distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\n" + + " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + " See the License for the specific language governing permissions and\n" + + " limitations under the License.\n" + + "\n" + + " SPDX-License-Identifier: Apache-2.0\";\n" + + "\n" + + " revision \"2024-05-24\" {\n" + + " description \"Initial revision.\";\n" + + " or-teiv-yext:label 0.3.0;\n" + + " }\n" + + "\n" + + " or-teiv-yext:domain REL_OAM_RAN;\n" + + "\n" + + " or-teiv-yext:biDirectionalTopologyRelationship MANAGEDELEMENT_MANAGES_ENODEBFUNCTION { // 1 to 0..n\n" + + "\n" + + " uses or-teiv-types:Top_Grp_Type;\n" + + " key id;\n" + + "\n" + + " leaf-list managed-enodebFunction {\n" + + " description \"Managed Element manages eNodeB Function.\";\n" + + " or-teiv-yext:aSide or-teiv-oam:ManagedElement;\n" + + " type instance-identifier;\n" + + " }\n" + + "\n" + + " leaf managed-by-managedElement {\n" + + " description \"eNodeB Function managed by Managed Element.\";\n" + + " or-teiv-yext:bSide or-teiv-ran:ENodeBFunction;\n" + + " type instance-identifier;\n" + + " mandatory true;\n" + + " }\n" + + " }\n" + + "\n" + + " or-teiv-yext:biDirectionalTopologyRelationship MANAGEDELEMENT_MANAGES_GNBDUFUNCTION { // 1 to 0..n\n" + + "\n" + + " uses or-teiv-types:Top_Grp_Type;\n" + + " key id;\n" + + "\n" + + " leaf-list managed-gnbduFunction {\n" + + " description \"Managed Element manages gNodeB-DU Function.\";\n" + + " or-teiv-yext:aSide or-teiv-oam:ManagedElement;\n" + + " type instance-identifier;\n" + + " }\n" + + "\n" + + " leaf managed-by-managedElement {\n" + + " description \"gNodeB-DU Function managed by Managed Element.\";\n" + + " or-teiv-yext:bSide or-teiv-ran:GNBDUFunction;\n" + + " type instance-identifier;\n" + + " mandatory true;\n" + + " }\n" + + " }\n" + + "\n" + + " or-teiv-yext:biDirectionalTopologyRelationship MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION { // 1 to 0..n\n" + + "\n" + + " uses or-teiv-types:Top_Grp_Type;\n" + + " key id;\n" + + "\n" + + " leaf-list managed-gnbcucpFunction {\n" + + " description \"Managed Element manages gNodeB-CU-CP Function.\";\n" + + " or-teiv-yext:aSide or-teiv-oam:ManagedElement;\n" + + " type instance-identifier;\n" + + " }\n" + + "\n" + + " leaf managed-by-managedElement {\n" + + " description \"gNodeB-CU-CP Function managed by Managed Element.\";\n" + + " or-teiv-yext:bSide or-teiv-ran:GNBCUCPFunction;\n" + + " type instance-identifier;\n" + + " mandatory true;\n" + + " }\n" + + " }\n" + + "\n" + + " or-teiv-yext:biDirectionalTopologyRelationship MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION { // 1 to 0..n\n" + + "\n" + + " uses or-teiv-types:Top_Grp_Type;\n" + + " key id;\n" + + "\n" + + " leaf-list managed-gnbcuupFunction {\n" + + " description \"Managed Element manages gNodeB-CU-UP Function.\";\n" + + " or-teiv-yext:aSide or-teiv-oam:ManagedElement;\n" + + " type instance-identifier;\n" + + " }\n" + + "\n" + + " leaf managed-by-managedElement {\n" + + " description \"gNodeB-CU-UP Function managed by Managed Element.\";\n" + + " or-teiv-yext:bSide or-teiv-ran:GNBCUUPFunction;\n" + + " type instance-identifier;\n" + + " mandatory true;\n" + + " }\n" + + " }\n" + + "}") + headers { + contentType('text/plain') + } + } + }, + Contract.make { + description "ERROR - 400: Get schema content with invalid name invalid" + request { + method GET() + url("/topology-inventory/v1alpha11/schemas/invalid/content") + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: invalid" + }''') + headers { + contentType('application/json') + } + } + } +] diff --git a/teiv/src/test/resources/contracts/schemas/02_postSchemas.groovy b/teiv/src/test/resources/contracts/schemas/02_postSchemas.groovy new file mode 100644 index 0000000..36018d9 --- /dev/null +++ b/teiv/src/test/resources/contracts/schemas/02_postSchemas.groovy @@ -0,0 +1,1037 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.schemas + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 201: Create a new classifiers + decorators schema with name module-rapp-model1" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model1 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model1"; ' + + ' prefix model1; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status CREATED() + } + }, + Contract.make { + description "SUCCESS - 201: Create a new decorators without classifier schema with name module-rapp-model2" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model2 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model2"; ' + + ' prefix model2; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + '}')))) + } + response { + status CREATED() + } + }, + Contract.make { + description "SUCCESS - 201: Create a new classifiers without decorator schema with name module-rapp-model3" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model3 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model3"; ' + + ' prefix model3; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' identity classifierTest1 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status CREATED() + } + }, + Contract.make { + description "ERROR - 400: Create a new classifiers and decorators schema, exception thrown due to wrong inheritance for the classifiers" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model4 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model4"; ' + + ' prefix model4; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base model-test; ' + + ' } ' + + ' ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: Invalid classifier classifierTest1" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifiers and decorators schema, exception thrown due to wrong inheritance for the classifiers" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model5 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model5"; ' + + ' prefix model5; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf test1 { ' + + ' type string; ' + + ' } ' + + ' leaf test2 { ' + + ' type boolean; ' + + ' } ' + + ' leaf test3 { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base wrong-classifier; ' + + ' } ' + + ' ' + + ' identity urban { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity rural { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: Invalid classifier geo-classifier" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifiers and decorators schema, exception thrown due to wrong inheritance for the classifier" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model6 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model6"; ' + + ' prefix model6; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base model-test; ' + + ' } ' + + ' ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: Invalid classifier classifierTest1" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with already existing schema name" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module test-app-module { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:test-app-module"; ' + + ' prefix module; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Schema already exists" + }''') + } + }, + Contract.make { + description "ERROR - 400: Invalid file type" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.json')), + contentType: p('application/json'), + content: $(c(regex(nonEmpty())), + p('{"sample1":"test", "sample2":99}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Invalid file" + }''') + } + }, + Contract.make { + description "ERROR - 400: Empty file" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty()))))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Missing content at the beginning of the document." + }''') + } + }, + Contract.make { + description "ERROR - 400: Invalid leaf 1" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-x { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-module-x"; ' + + ' prefix module-x; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix test; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-06-10" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /test:decorators { ' + + ' leaf select*fromgnbcucpfunction { ' + + ' type string; ' + + ' } ' + + ' leaf vendor { ' + + ' type string; ' + + ' } ' + + ' } ' + + ' ' + + ' identity Outdoor { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + ' identity Rural { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + ' identity Weekend { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: 'select*fromgnbcucpfunction' is not a valid YANG identifier." + }''') + } + }, + Contract.make { + description "ERROR - 400: Invalid leaf 2" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-x2 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-module-x2"; ' + + ' prefix module-x2; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix test; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-06-10" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /test:decorators { ' + + ' leaf location { ' + + ' type string; ' + + ' } ' + + ' leaf vendor { ' + + ' type string; ' + + ' } ' + + ' } ' + + ' ' + + ' identity UPDATEties_model.module_referenceSETstatusDELETINGWHEREnamegnbdu-function-model { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + ' identity Rural { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + ' identity Weekend { ' + + ' base test:classifiers; ' + + ' } ' + + ' ' + + '}}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Unexpected content at end of document. Check curly braces balance throughout document." + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema without any given decorator or classifier" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model7 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model7"; ' + + ' prefix model7; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base test-classifier; ' + + ' } ' + + ' ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Encountered '{}', which does nothing. Replace with ';' or un-comment the contents." + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema without any given decorator or classifier 2" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-module8 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-module8"; ' + + ' prefix module8; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Invalid schema" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema missing leaf type for the decorators" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model9 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model9"; ' + + ' prefix model9; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Encountered '{}', which does nothing. Replace with ';' or un-comment the contents." + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with wrong decorator type" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model10 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model10"; ' + + ' prefix model10; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type wrong; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Cannot resolve typedef 'wrong'." + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with wrong syntax (missing imports)" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model11 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model11"; ' + + ' prefix model11; ' + + ' ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Invalid schema" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with wrong syntax (missing revision)" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model12 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model12"; ' + + ' prefix model12; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: (Sub-)Module does not have a 'revision' statement." + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with wrong syntax (missing yang version, namespace, prefix)" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-model13 { ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix model; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf urban { ' + + ' type string; ' + + ' } ' + + ' leaf rural { ' + + ' type boolean; ' + + ' } ' + + ' leaf weekend { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + ' identity classifierTest1 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest2 { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity classifierTest3 { ' + + ' base model:classifiers; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Invalid schema" + }''') + } + }, + Contract.make { + description "ERROR - 400: Create a new classifier and decorator schema with wrong syntax (prefix is different then the inheritances)" + request { + method POST() + url("/topology-inventory/v1alpha11/schemas") + headers { + contentType(multipartFormData()) + } + multipart( + file: named( + name: $(c(regex(nonEmpty())), p('file.yang')), + contentType: p('application/yang'), + content: $(c(regex(nonEmpty())), + p('module module-rapp-module14 { ' + + ' ' + + ' yang-version 1.1; ' + + ' namespace "urn:module-rapp-model14"; ' + + ' prefix module14; ' + + ' ' + + ' import o-ran-smo-teiv-common-yang-types { prefix testModel; } ' + + ' import o-ran-smo-teiv-common-yang-extensions {prefix or-teiv-yext; } ' + + ' ' + + ' revision "2024-05-08" { ' + + ' description ' + + ' "Initial revision."; ' + + ' or-teiv-yext:label 0.3.0; ' + + ' } ' + + ' ' + + ' augment /model:decorators { ' + + ' leaf test1 { ' + + ' type string; ' + + ' } ' + + ' leaf test2 { ' + + ' type boolean; ' + + ' } ' + + ' leaf test3 { ' + + ' type uint32; ' + + ' } ' + + ' } ' + + ' ' + + ' identity geo-classifier { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity urban { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + ' identity rural { ' + + ' base geo-classifier; ' + + ' } ' + + ' ' + + '}')))) + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid file input", + "details": "Invalid file input: Path to schema node '/model:decorators', part of 'augment' statement, cannot be resolved." + }''') + } + } +] diff --git a/teiv/src/test/resources/contracts/schemas/03_deleteSchemas.groovy b/teiv/src/test/resources/contracts/schemas/03_deleteSchemas.groovy new file mode 100644 index 0000000..5c486fa --- /dev/null +++ b/teiv/src/test/resources/contracts/schemas/03_deleteSchemas.groovy @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Ericsson + * Modifications Copyright (C) 2024 OpenInfra Foundation Europe + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package contracts.schemas + +import org.springframework.cloud.contract.spec.Contract + +[ + Contract.make { + description "SUCCESS - 204: Delete an existing classifier schema - test-app-for-deletion-module" + request { + method DELETE() + url("/topology-inventory/v1alpha11/schemas/test-app-for-deletion-module") + } + response { + status NO_CONTENT() + } + }, + Contract.make { + description "ERROR - 400: Delete a schema that does not exists" + request { + method DELETE() + url("/topology-inventory/v1alpha11/schemas/does-not-exist-rapp-module") + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: does-not-exist-rapp-module" + }''') + } + }, + Contract.make { + description "ERROR - 400: Delete a schema that is in deleting status" + request { + method DELETE() + url("/topology-inventory/v1alpha11/schemas/test-module-in-deleting-state") + } + response { + status BAD_REQUEST() + body('''{ + "status": "BAD_REQUEST", + "message": "Invalid schema name", + "details": "Invalid schema name: test-module-in-deleting-state" + }''') + } + } +] diff --git a/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql b/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql new file mode 100644 index 0000000..fe8d597 --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data-v1.sql @@ -0,0 +1,1024 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +CREATE EXTENSION IF NOT EXISTS postgis; +CREATE EXTENSION IF NOT EXISTS postgis_topology; +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +CREATE SCHEMA IF NOT EXISTS ties_data; + +-- Function to create CONSTRAINT only if it does not exists +CREATE OR REPLACE FUNCTION ties_data.create_constraint_if_not_exists ( + t_name TEXT, c_name TEXT, constraint_sql TEXT +) +RETURNS void AS +$$ +BEGIN + IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = t_name AND constraint_name = c_name) THEN + EXECUTE constraint_sql; + END IF; +END; +$$ language 'plpgsql'; + +-- Update data schema exec status +INSERT INTO ties_model.execution_status("schema", "status") VALUES ('ties_data', 'success'); + +CREATE TABLE IF NOT EXISTS ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ( + "id" TEXT, + "aSide_AntennaModule" TEXT, + "bSide_AntennaCapability" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-equipment_AntennaModule" ( + "id" TEXT, + "antennaBeamWidth" jsonb, + "antennaModelNumber" TEXT, + "electricalAntennaTilt" INTEGER, + "geo-location" geography, + "mechanicalAntennaBearing" INTEGER, + "mechanicalAntennaTilt" INTEGER, + "positionWithinSector" TEXT, + "totalTilt" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_installed-at-site" TEXT, + "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" TEXT, + "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb, + "REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb, + "REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb, + "REL_FK_grouped-by-sector" TEXT, + "REL_ID_SECTOR_GROUPS_ANTENNAMODULE" TEXT, + "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-equipment_Site" ( + "id" TEXT, + "geo-location" geography, + "name" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_Site" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_Site" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-equipment_Site" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-oam_ManagedElement" ( + "id" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-oam_ManagedElement" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-oam_ManagedElement" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-oam_ManagedElement" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_AntennaCapability" ( + "id" TEXT, + "eUtranFqBands" jsonb, + "geranFqBands" jsonb, + "nRFqBands" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_AntennaCapability" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_AntennaCapability" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_AntennaCapability" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ( + "id" TEXT, + "eNBId" INTEGER, + "eNodeBPlmnId" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_managed-by-managedElement" TEXT, + "REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" TEXT, + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_EUtranCell" ( + "id" TEXT, + "cellId" INTEGER, + "channelBandwidth" INTEGER, + "dlChannelBandwidth" INTEGER, + "duplexType" TEXT, + "earfcn" INTEGER, + "earfcndl" INTEGER, + "earfcnul" INTEGER, + "tac" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-enodebFunction" TEXT, + "REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" TEXT, + "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb, + "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb, + "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb, + "REL_FK_grouped-by-sector" TEXT, + "REL_ID_SECTOR_GROUPS_EUTRANCELL" TEXT, + "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_EUtranCell" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ( + "id" TEXT, + "gNBCUName" TEXT, + "gNBId" BIGINT, + "gNBIdLength" INTEGER, + "pLMNId" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_managed-by-managedElement" TEXT, + "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" TEXT, + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ( + "id" TEXT, + "gNBId" BIGINT, + "gNBIdLength" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_managed-by-managedElement" TEXT, + "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" TEXT, + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ( + "id" TEXT, + "dUpLMNId" jsonb, + "gNBDUId" BIGINT, + "gNBId" BIGINT, + "gNBIdLength" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_managed-by-managedElement" TEXT, + "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" TEXT, + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ( + "id" TEXT, + "sectorCarrierType" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-enodebFunction" TEXT, + "REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" TEXT, + "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, + "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, + "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, + "REL_FK_used-by-euTranCell" TEXT, + "REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" TEXT, + "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" jsonb, + "REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER" jsonb, + "REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER" jsonb, + "REL_FK_used-antennaCapability" TEXT, + "REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY" TEXT, + "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ALTER COLUMN "REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_NRCellCU" ( + "id" TEXT, + "cellLocalId" INTEGER, + "nCI" BIGINT, + "nRTAC" INTEGER, + "plmnId" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-gnbcucpFunction" TEXT, + "REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" TEXT, + "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb, + "REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb, + "REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellCU" ALTER COLUMN "REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_NRCellDU" ( + "id" TEXT, + "cellLocalId" INTEGER, + "nCI" BIGINT, + "nRPCI" INTEGER, + "nRTAC" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-gnbduFunction" TEXT, + "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" TEXT, + "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb, + "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb, + "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb, + "REL_FK_grouped-by-sector" TEXT, + "REL_ID_SECTOR_GROUPS_NRCELLDU" TEXT, + "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_NRCELLDU" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRCellDU" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ( + "id" TEXT, + "arfcnDL" INTEGER, + "arfcnUL" INTEGER, + "bSChannelBwDL" INTEGER, + "frequencyDL" INTEGER, + "frequencyUL" INTEGER, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-gnbduFunction" TEXT, + "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" TEXT, + "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, + "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, + "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, + "REL_FK_used-by-nrCellDu" TEXT, + "REL_ID_NRCELLDU_USES_NRSECTORCARRIER" TEXT, + "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER" jsonb, + "REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER" jsonb, + "REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER" jsonb, + "REL_FK_used-antennaCapability" TEXT, + "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY" TEXT, + "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ALTER COLUMN "REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran_Sector" ( + "id" TEXT, + "azimuth" DECIMAL, + "geo-location" geography, + "sectorId" BIGINT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_Sector" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_Sector" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran_Sector" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +SELECT ties_data.create_constraint_if_not_exists( + 'CFC235E0404703D1E4454647DF8AAE2C193DB402', + 'PK_63E61CB6802F21FE7A04A80A095F6AF8ABF067CE', + 'ALTER TABLE ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ADD CONSTRAINT "PK_63E61CB6802F21FE7A04A80A095F6AF8ABF067CE" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_AntennaModule', + 'PK_o-ran-smo-teiv-equipment_AntennaModule_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_AntennaModule" ADD CONSTRAINT "PK_o-ran-smo-teiv-equipment_AntennaModule_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_Site', + 'PK_o-ran-smo-teiv-equipment_Site_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_Site" ADD CONSTRAINT "PK_o-ran-smo-teiv-equipment_Site_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-oam_ManagedElement', + 'PK_o-ran-smo-teiv-oam_ManagedElement_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-oam_ManagedElement" ADD CONSTRAINT "PK_o-ran-smo-teiv-oam_ManagedElement_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_AntennaCapability', + 'PK_o-ran-smo-teiv-ran_AntennaCapability_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_AntennaCapability" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_AntennaCapability_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_ENodeBFunction', + 'PK_o-ran-smo-teiv-ran_ENodeBFunction_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_ENodeBFunction_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_EUtranCell', + 'PK_o-ran-smo-teiv-ran_EUtranCell_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_EUtranCell" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_EUtranCell_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUCPFunction', + 'PK_o-ran-smo-teiv-ran_GNBCUCPFunction_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_GNBCUCPFunction_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUUPFunction', + 'PK_o-ran-smo-teiv-ran_GNBCUUPFunction_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_GNBCUUPFunction_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBDUFunction', + 'PK_o-ran-smo-teiv-ran_GNBDUFunction_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_GNBDUFunction_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'PK_o-ran-smo-teiv-ran_LTESectorCarrier_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_LTESectorCarrier_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellCU', + 'PK_o-ran-smo-teiv-ran_NRCellCU_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellCU" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_NRCellCU_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellDU', + 'PK_o-ran-smo-teiv-ran_NRCellDU_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellDU" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_NRCellDU_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'PK_o-ran-smo-teiv-ran_NRSectorCarrier_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_NRSectorCarrier_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_Sector', + 'PK_o-ran-smo-teiv-ran_Sector_id', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_Sector" ADD CONSTRAINT "PK_o-ran-smo-teiv-ran_Sector_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'CFC235E0404703D1E4454647DF8AAE2C193DB402', + 'FK_D80D1E6B26DF620B4DE659C600A3B7F709A41960', + 'ALTER TABLE ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ADD CONSTRAINT "FK_D80D1E6B26DF620B4DE659C600A3B7F709A41960" FOREIGN KEY ("aSide_AntennaModule") REFERENCES ties_data."o-ran-smo-teiv-equipment_AntennaModule" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'CFC235E0404703D1E4454647DF8AAE2C193DB402', + 'FK_7148BEED02C0617DE1DEEB6639F34A9FA9251B06', + 'ALTER TABLE ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ADD CONSTRAINT "FK_7148BEED02C0617DE1DEEB6639F34A9FA9251B06" FOREIGN KEY ("bSide_AntennaCapability") REFERENCES ties_data."o-ran-smo-teiv-ran_AntennaCapability" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_AntennaModule', + 'FK_E3BAEF04443354C0FC1837CF7964E05BEF9FD6CC', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_AntennaModule" ADD CONSTRAINT "FK_E3BAEF04443354C0FC1837CF7964E05BEF9FD6CC" FOREIGN KEY ("REL_FK_installed-at-site") REFERENCES ties_data."o-ran-smo-teiv-equipment_Site" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_AntennaModule', + 'UNIQUE_9DF414C2F0CD7FA8BFCB3E9BF851784AC4BC49B1', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_AntennaModule" ADD CONSTRAINT "UNIQUE_9DF414C2F0CD7FA8BFCB3E9BF851784AC4BC49B1" UNIQUE ("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_AntennaModule', + 'FK_078764B2F3D613D44CC6E3586F564C83164D2481', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_AntennaModule" ADD CONSTRAINT "FK_078764B2F3D613D44CC6E3586F564C83164D2481" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."o-ran-smo-teiv-ran_Sector" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-equipment_AntennaModule', + 'UNIQUE_78B1D3DCD903AFFB1965D440D87B2D194CA028A0', + 'ALTER TABLE ties_data."o-ran-smo-teiv-equipment_AntennaModule" ADD CONSTRAINT "UNIQUE_78B1D3DCD903AFFB1965D440D87B2D194CA028A0" UNIQUE ("REL_ID_SECTOR_GROUPS_ANTENNAMODULE");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_ENodeBFunction', + 'FK_6C99B14BF3C9BC6DE2D69AD55DF323ADCB174167', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ADD CONSTRAINT "FK_6C99B14BF3C9BC6DE2D69AD55DF323ADCB174167" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-oam_ManagedElement" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_ENodeBFunction', + 'UNIQUE_A30444B7D036FA579730F0D2853E52FD08DEDCF0', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ADD CONSTRAINT "UNIQUE_A30444B7D036FA579730F0D2853E52FD08DEDCF0" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_EUtranCell', + 'FK_2D1FA89480BF856AB865D58FAFB6AC0B476015EB', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_EUtranCell" ADD CONSTRAINT "FK_2D1FA89480BF856AB865D58FAFB6AC0B476015EB" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."o-ran-smo-teiv-ran_ENodeBFunction" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_EUtranCell', + 'UNIQUE_CA88C7E60C1A332FA7561FC965ED41DD4125CDED', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_EUtranCell" ADD CONSTRAINT "UNIQUE_CA88C7E60C1A332FA7561FC965ED41DD4125CDED" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_EUtranCell', + 'FK_o-ran-smo-teiv-ran_EUtranCell_REL_FK_grouped-by-sector', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_EUtranCell" ADD CONSTRAINT "FK_o-ran-smo-teiv-ran_EUtranCell_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."o-ran-smo-teiv-ran_Sector" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_EUtranCell', + 'UNIQUE_0513FE4A675A02C31E5EDD6BCB3728911FBDA2FA', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_EUtranCell" ADD CONSTRAINT "UNIQUE_0513FE4A675A02C31E5EDD6BCB3728911FBDA2FA" UNIQUE ("REL_ID_SECTOR_GROUPS_EUTRANCELL");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUCPFunction', + 'FK_F1FB8F88851067901B66D53EE1420D2ECCEC98A3', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ADD CONSTRAINT "FK_F1FB8F88851067901B66D53EE1420D2ECCEC98A3" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-oam_ManagedElement" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUCPFunction', + 'UNIQUE_50E9E4A87D93AC833B1D1AC05E3B58805909E20E', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ADD CONSTRAINT "UNIQUE_50E9E4A87D93AC833B1D1AC05E3B58805909E20E" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUUPFunction', + 'FK_34D6E2537E8EE1D395CAF5BF9B2182A4696A1EAA', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ADD CONSTRAINT "FK_34D6E2537E8EE1D395CAF5BF9B2182A4696A1EAA" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-oam_ManagedElement" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBCUUPFunction', + 'UNIQUE_0CA05800AC7D277BDCB5CF0097DC35978E9311F4', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ADD CONSTRAINT "UNIQUE_0CA05800AC7D277BDCB5CF0097DC35978E9311F4" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBDUFunction', + 'FK_F67FAF9D3E82B97104E2392DA0AC8A86DF2407CC', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ADD CONSTRAINT "FK_F67FAF9D3E82B97104E2392DA0AC8A86DF2407CC" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-oam_ManagedElement" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_GNBDUFunction', + 'UNIQUE_5BD09ED226520A0BE27904AEAF0557416808E7E2', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ADD CONSTRAINT "UNIQUE_5BD09ED226520A0BE27904AEAF0557416808E7E2" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'FK_D0868FBC0BBE2754F4B765C4898C1A1700E2BEFD', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "FK_D0868FBC0BBE2754F4B765C4898C1A1700E2BEFD" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."o-ran-smo-teiv-ran_ENodeBFunction" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'UNIQUE_FD943EE596337B11E0C640E1176CADF9CD69E19A', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "UNIQUE_FD943EE596337B11E0C640E1176CADF9CD69E19A" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'FK_96E6D4983CFFDF30FCA20423B5913DEE486E42D0', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "FK_96E6D4983CFFDF30FCA20423B5913DEE486E42D0" FOREIGN KEY ("REL_FK_used-by-euTranCell") REFERENCES ties_data."o-ran-smo-teiv-ran_EUtranCell" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'UNIQUE_0A76398FBBC8E01A2D3BA602AB47835794E997E5', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "UNIQUE_0A76398FBBC8E01A2D3BA602AB47835794E997E5" UNIQUE ("REL_ID_EUTRANCELL_USES_LTESECTORCARRIER");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'FK_3D8DF3FBD9C042A888CEB382688C1E8F39D85AFE', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "FK_3D8DF3FBD9C042A888CEB382688C1E8F39D85AFE" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."o-ran-smo-teiv-ran_AntennaCapability" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_LTESectorCarrier', + 'UNIQUE_EA18F1D278EAFE834B8A80BCF8A7D8355CD013DF', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ADD CONSTRAINT "UNIQUE_EA18F1D278EAFE834B8A80BCF8A7D8355CD013DF" UNIQUE ("REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellCU', + 'FK_F2CDD1E84C7F07BF8065F99A5F3488E91E3BB7B2', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellCU" ADD CONSTRAINT "FK_F2CDD1E84C7F07BF8065F99A5F3488E91E3BB7B2" FOREIGN KEY ("REL_FK_provided-by-gnbcucpFunction") REFERENCES ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellCU', + 'UNIQUE_EA2A6F5BA36ABB0DA357542E05AA2D07415E127A', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellCU" ADD CONSTRAINT "UNIQUE_EA2A6F5BA36ABB0DA357542E05AA2D07415E127A" UNIQUE ("REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellDU', + 'FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_provided-by-gnbduFunction', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellDU" ADD CONSTRAINT "FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_provided-by-gnbduFunction" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."o-ran-smo-teiv-ran_GNBDUFunction" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellDU', + 'UNIQUE_C3D8E5331EC71D46D4B8CED29FE5F6CEB1D8E67A', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellDU" ADD CONSTRAINT "UNIQUE_C3D8E5331EC71D46D4B8CED29FE5F6CEB1D8E67A" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellDU', + 'FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_grouped-by-sector', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellDU" ADD CONSTRAINT "FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."o-ran-smo-teiv-ran_Sector" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRCellDU', + 'UNIQUE_AC1C114ABED77D6DEC3F3AE3F9EBE8231924AEF4', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRCellDU" ADD CONSTRAINT "UNIQUE_AC1C114ABED77D6DEC3F3AE3F9EBE8231924AEF4" UNIQUE ("REL_ID_SECTOR_GROUPS_NRCELLDU");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'FK_F7978366174C82E41F0A6ABF29005FF01603858F', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "FK_F7978366174C82E41F0A6ABF29005FF01603858F" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."o-ran-smo-teiv-ran_GNBDUFunction" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'UNIQUE_0AC16A840F6ACDC50136E71EC6D4F3D4E04B8198', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "UNIQUE_0AC16A840F6ACDC50136E71EC6D4F3D4E04B8198" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_used-by-nrCellDu', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_used-by-nrCellDu" FOREIGN KEY ("REL_FK_used-by-nrCellDu") REFERENCES ties_data."o-ran-smo-teiv-ran_NRCellDU" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'UNIQUE_1AB577E5AC207ED4C99A9A96BA1C9C35544AFD25', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "UNIQUE_1AB577E5AC207ED4C99A9A96BA1C9C35544AFD25" UNIQUE ("REL_ID_NRCELLDU_USES_NRSECTORCARRIER");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'FK_65D538D54EB33081C808540235FEB28823428E64', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "FK_65D538D54EB33081C808540235FEB28823428E64" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."o-ran-smo-teiv-ran_AntennaCapability" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'o-ran-smo-teiv-ran_NRSectorCarrier', + 'UNIQUE_A799EC9DA6624651081E1DA21B5F0C2D38F6A192', + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ADD CONSTRAINT "UNIQUE_A799EC9DA6624651081E1DA21B5F0C2D38F6A192" UNIQUE ("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY");' +); + +CREATE INDEX IF NOT EXISTS "IDX_E896A9EB22A3F9F96CE75A271475316A98B629C8" ON ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_DD0D676834B12CA2F7E8219310998376A08D7F5F" ON ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_7BF09D0227840279556AD27ACECB068705893D28" ON ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_21B0F1FE632B6CB185C49BA6F00224068F443215" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("antennaBeamWidth"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_905011128A2C218B5352C19ED1FE9851F43EB911" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_1C0CAFD80FDD6444044E3F76C7C0A7BDC35F9BC8" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-equipment_AntennaModule_CD_decorators" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_F497DEC01DA066CB09DA2AA7EDE3F4410078491B" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_17E417F7EF56809674BE1D5F5154DCCE01E00A96" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_2321BFA482AD2700F41E2BA359F6EB00F47601B9" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN ("REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE"); + +CREATE INDEX IF NOT EXISTS "IDX_5ABDB19E55A6BDEF33855F14CB1B3B8CF457912C" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_83B6347C0C0A005D5E3D856D973D3322DFEDEA35" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN (("REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_6C6FBD69F47F41970595A8775DC99CA0F5E894A1" ON ties_data."o-ran-smo-teiv-equipment_AntennaModule" USING GIN ("REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE"); + +CREATE INDEX IF NOT EXISTS "IDX_102A50584376DE25B6BBD7157594C607A5C957F2" ON ties_data."o-ran-smo-teiv-equipment_Site" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_EEBF1BC3344E97988232825777AB13FAB6C4F3F0" ON ties_data."o-ran-smo-teiv-equipment_Site" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-equipment_Site_CD_decorators" ON ties_data."o-ran-smo-teiv-equipment_Site" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_DDD73D6F4004BF3A96AA118281EE3E565A922B47" ON ties_data."o-ran-smo-teiv-oam_ManagedElement" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_98AC4232BC02323E03416954215889CEE874A1E9" ON ties_data."o-ran-smo-teiv-oam_ManagedElement" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-oam_ManagedElement_CD_decorators" ON ties_data."o-ran-smo-teiv-oam_ManagedElement" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_5FB80647AE3E5C0443A792618D65B9090EE2A3FC" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN (("eUtranFqBands"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_A94722FF7B95D8974B494793908B57B4E1A9743B" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN (("geranFqBands"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_441B5C05448D63552C6414BD59C13641D8A4408D" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN (("nRFqBands"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_CC3E208A4EE51D3B505416A599F36F3C99F466C8" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_E7FFE8F4A166AA9A382A0659762FFEC313A9EB5C" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_AntennaCapability_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_AntennaCapability" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_eNodeBPlmnId" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN ("eNodeBPlmnId"); + +CREATE INDEX IF NOT EXISTS "IDX_3F7D14B4CF2CA74F28BA1600606E82C6E8C447C0" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_B598B74193845587BA03553CEDBA058D33956847" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_252AF4814C67384A7B05EA116316E83AFF9EB6AE" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN (("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_61CDCD3F69CF67EE740358D2C76FA796CFDA19BF" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN (("REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_35C17C8A9BA3EF3AEADA72C21F8090C38F575BAF" ON ties_data."o-ran-smo-teiv-ran_ENodeBFunction" USING GIN ("REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION"); + +CREATE INDEX IF NOT EXISTS "IDX_84E36DC53519D3E334C60B5B02C1AB27130CFA24" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_C9C19F8F83F50C130F2EB6502ABB7B2833F1F783" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_EUtranCell_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_976F6A0F8991F64592B6F9E716EFEECBD5400FDA" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_4C77E3A51BFAB2FCD30425E4EB21CC7636438299" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_FC7D79187227E0BFA69149048CC10E39AE540B8A" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN ("REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL"); + +CREATE INDEX IF NOT EXISTS "IDX_173887418DD4FD6FD592F6404EA784150B1822C0" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_8A15E61498725DA9D8C78FC4B99053C06E88DCEC" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN (("REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_E4EF3C904939ED4C0996EAB7CDFE1895CDF34BFB" ON ties_data."o-ran-smo-teiv-ran_EUtranCell" USING GIN ("REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL"); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_pLMNId" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN ("pLMNId"); + +CREATE INDEX IF NOT EXISTS "IDX_BE4B476041D559760931630000D3F4A6DFF42707" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_588840BAE32C7FF8CF0553F631DAAF8BB6E8E7C1" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_E01081465B87F46E1CC7A22FE406C7B41C817E8C" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN (("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_1324070754C1EBF8EA78EF40743AFC1713733BA8" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN (("REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_13E734DE57346378DA4F21FC4EA030290A7E532F" ON ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" USING GIN ("REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION"); + +CREATE INDEX IF NOT EXISTS "IDX_C6D2419F8DC299FBC98342AA00BE92308C7566A7" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_4C2B68358221A7FF0E68012DEDD3CBA2C4ED669F" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_GNBCUUPFunction_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_883506CAA3E742D82EEFCEE8C8F29927983B73B1" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN (("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_EB07ADD66F6CF51B9330403DE4500D05CA067647" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN (("REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_C3141DD7D2695EF74B13981AB378A58390D203D6" ON ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" USING GIN ("REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION"); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_dUpLMNId" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN ("dUpLMNId"); + +CREATE INDEX IF NOT EXISTS "IDX_2BEF269CED354C2454AC2B2EABB134AC267A0C62" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_601A4514FFACA8985471531013AFC8F760361F09" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_3065F7FB78C5AA9FF17972F825F89AED127A6324" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN (("REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_04C614FDE6A4AE2AA106A1233D1DF95803FC122D" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN (("REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_298FCD184347DEC995B06FED2B1AE61F12BF766A" ON ties_data."o-ran-smo-teiv-ran_GNBDUFunction" USING GIN ("REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION"); + +CREATE INDEX IF NOT EXISTS "IDX_6EC539C61EA7078DBA264C9877B87FC263605D42" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_E754EB8AD825DB3111B07B9E5DA3B30C38DB406B" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_1EBC7271CEA658156DE25286404CBC4593340F8E" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_846B7740E8AA756B8C1409CD909D2DF73A47ED4C" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_44075E1D464599B61924196C20F2B88332520CD8" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN ("REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER"); + +CREATE INDEX IF NOT EXISTS "IDX_F2D46817C2D618D8C33945F282299BF9EB49465E" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_B291D7EFCAD3BF06A2C11F8C0429ABABEEF8308B" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_EAE482189F45D63CD1A88B0DD5F76EEE163D9E53" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN ("REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER"); + +CREATE INDEX IF NOT EXISTS "IDX_7D01A5D21C990ACCBE65035C062C7D881A05F1EE" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_3D3EFECFB917DAC074F56334224B19F8FD6BF8A5" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN (("REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_4EE2AA643311DFCC13B6ED832EBE2FAB4CFDF494" ON ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" USING GIN ("REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY"); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_plmnId" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN ("plmnId"); + +CREATE INDEX IF NOT EXISTS "IDX_0C443A16285D233F16966C2F0314CDC9D0F6D0B8" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_E5930226819982DC0CFC1FA64FB3600647222435" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_36A671754CD510FFBDC2713FD142303DCA75DD65" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN (("REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_04BE1EB39848069422B97C28EE3C8ED18BCC6D33" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN (("REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_229957181BBC9D7B4535807BB397E8AA1378ED85" ON ties_data."o-ran-smo-teiv-ran_NRCellCU" USING GIN ("REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU"); + +CREATE INDEX IF NOT EXISTS "IDX_FFD60DD99D80C276F402E66546F5DACB2D81EE26" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_C437D39632DC79BAB6AC4F0880826A05425F9C32" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_NRCellDU_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_1F6708B1E34FC908473DD7A7E5641E650B359BEF" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_2F4C43ED084968FDAF9943DB96741885C145FE1D" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_0E63D6B76B229961CD45D998C63175B569DDECD1" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN ("REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU"); + +CREATE INDEX IF NOT EXISTS "IDX_6325926B4D2FDD1FBBB34250DABEA5E7229FF9F5" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_7CB4A7724F68D1CB2D12E8DE779BA9103F7DBE0A" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN (("REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_0A03C47C13AD3B5C84D3D8081493D670E9CBDCD1" ON ties_data."o-ran-smo-teiv-ran_NRCellDU" USING GIN ("REL_CD_decorators_SECTOR_GROUPS_NRCELLDU"); + +CREATE INDEX IF NOT EXISTS "IDX_8E34EC0B1DE7DDCE3B32ADD85B11E15F95C5644E" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_050A80BEEF775E4D3CE216F282F23DB99DA2D798" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN ("CD_decorators"); + +CREATE INDEX IF NOT EXISTS "IDX_CD293AD1111E344D150340A13BD299924D29A9DA" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_273D43FDDD1C4643ECF8BBE51B6B369C657F0861" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_EDE8B88F488F9380DB49CB2C141318FB33C2CCEC" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN ("REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER"); + +CREATE INDEX IF NOT EXISTS "IDX_7BFD17A71AB1B7765FE6431DA4E66C2EDE88AC3B" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_ED50A5139F1449DBAD8DA10D45F5A5BF819EACBA" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_2ADB5C6DCAEE8811FB1CA8FD9EB53381F35FCB70" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN ("REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER"); + +CREATE INDEX IF NOT EXISTS "IDX_1F27C515A028616FAC422A02ABBEC402D5DBB2E5" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_B975D24291849007D4AA6686C5D3983885D5C884" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN (("REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_902B73F741160B9D4FBF62406D3D9ABBECAD8BE7" ON ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" USING GIN ("REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY"); + +CREATE INDEX IF NOT EXISTS "IDX_E234B43A7CD7843672F08F2197AB46A2A50BECB0" ON ties_data."o-ran-smo-teiv-ran_Sector" USING GIN (("CD_sourceIds"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_19C19556F9714850389595E0A16218FA229205FE" ON ties_data."o-ran-smo-teiv-ran_Sector" USING GIN (("CD_classifiers"::TEXT) gin_trgm_ops); + +CREATE INDEX IF NOT EXISTS "IDX_GIN_o-ran-smo-teiv-ran_Sector_CD_decorators" ON ties_data."o-ran-smo-teiv-ran_Sector" USING GIN ("CD_decorators"); + +ANALYZE ties_data."o-ran-smo-teiv-ran_GNBDUFunction"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction"; + +ANALYZE ties_data."o-ran-smo-teiv-equipment_Site"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_AntennaCapability"; + +ANALYZE ties_data."o-ran-smo-teiv-equipment_AntennaModule"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_EUtranCell"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_LTESectorCarrier"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_NRCellCU"; + +ANALYZE ties_data."o-ran-smo-teiv-oam_ManagedElement"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_NRCellDU"; + +ANALYZE ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_NRSectorCarrier"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_ENodeBFunction"; + +ANALYZE ties_data."o-ran-smo-teiv-ran_Sector"; + +COMMIT; diff --git a/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data.sql b/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data.sql index 094be5e..4748549 100644 --- a/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data.sql +++ b/teiv/src/test/resources/pgsqlschema/00_init-oran-smo-teiv-data.sql @@ -31,7 +31,7 @@ ALTER SCHEMA ties_data OWNER TO :pguser; SET default_tablespace = ''; SET default_table_access_method = heap; -SET ROLE :'pguser'; +SET ROLE :pguser; -- Function to create CONSTRAINT only if it does not exists CREATE OR REPLACE FUNCTION ties_data.create_constraint_if_not_exists ( @@ -46,50 +46,76 @@ BEGIN END; $$ language 'plpgsql'; -CREATE TABLE IF NOT EXISTS ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" ( +CREATE TABLE IF NOT EXISTS ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "REL_FK_C2F5EC33C0760F653CE7263A49C0B697FCA2D542" VARCHAR(511) ); -ALTER TABLE ONLY ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ( +CREATE TABLE IF NOT EXISTS ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "fdn" TEXT, "cmId" jsonb, "REL_FK_26958E3A529C4C8B68A29FDA906F8CD290F66078" VARCHAR(511), "REL_ID_B7945BFD83380F3E12CF99F2B0F838F364027F92" VARCHAR(511), - "REL_CD_B7945BFD83380F3E12CF99F2B0F838F364027F92" jsonb + "REL_CD_B7945BFD83380F3E12CF99F2B0F838F364027F92" jsonb, + "REL_CD_BF4AAC1A1A910D1182505CABF55BAAE822B2BE59" jsonb, + "REL_CD_AE82DD80D666B52D79A314F8B4EE9B046830D009" jsonb ); -ALTER TABLE ONLY ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ALTER COLUMN "REL_CD_B7945BFD83380F3E12CF99F2B0F838F364027F92" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "REL_CD_B7945BFD83380F3E12CF99F2B0F838F364027F92" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "REL_CD_BF4AAC1A1A910D1182505CABF55BAAE822B2BE59" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ALTER COLUMN "REL_CD_AE82DD80D666B52D79A314F8B4EE9B046830D009" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ( +CREATE TABLE IF NOT EXISTS ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "REL_FK_AB87B417CCD05C332DDD0C60F0C6AB41D38B05E5" VARCHAR(511), "REL_ID_FC2F6A5A12917357B548C83F4B0C1AD58FA61413" VARCHAR(511), "REL_CD_CEAD4CCE5250E7D3C64801C8FDDC21F1D87BEC0C" jsonb, + "REL_CD_744530EF4EB1D281D23ADB3DB4CC926DFBE7A60D" jsonb, + "REL_CD_4D1F8113C3096B383582A7A04E68974983B4259E" jsonb, "REL_FK_8C98B70070BBD11F90F192DDA3ECF6302390E956" VARCHAR(511), "REL_ID_AFBF10D23507AD3B6408947D2A9AF8465BA7B08C" VARCHAR(511), - "REL_CD_F7E43E0D0F76D6EFED9AB684B84A69E177F591D2" jsonb + "REL_CD_F7E43E0D0F76D6EFED9AB684B84A69E177F591D2" jsonb, + "REL_CD_C4349BB0F0292A3CE7E456E3A4C40C86DD6B15DF" jsonb, + "REL_CD_8AD499BB116F3213C079F643D4B3532035D092D2" jsonb ); -ALTER TABLE ONLY ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ALTER COLUMN "REL_CD_CEAD4CCE5250E7D3C64801C8FDDC21F1D87BEC0C" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_CEAD4CCE5250E7D3C64801C8FDDC21F1D87BEC0C" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_744530EF4EB1D281D23ADB3DB4CC926DFBE7A60D" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_4D1F8113C3096B383582A7A04E68974983B4259E" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ALTER COLUMN "REL_CD_F7E43E0D0F76D6EFED9AB684B84A69E177F591D2" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_F7E43E0D0F76D6EFED9AB684B84A69E177F591D2" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_C4349BB0F0292A3CE7E456E3A4C40C86DD6B15DF" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ALTER COLUMN "REL_CD_8AD499BB116F3213C079F643D4B3532035D092D2" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ( +CREATE TABLE IF NOT EXISTS ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "020335B0F627C169E24167748C38FE756FB34AE2" BIGINT, "nRTAC" BIGINT, "nRPCI" BIGINT, @@ -98,60 +124,88 @@ CREATE TABLE IF NOT EXISTS ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" "nCI" BIGINT, "REL_FK_609963BFEE15FF824280FBE201313C3CDACDDDCE" VARCHAR(511), "REL_ID_040FC8B06B420BA5708AF4798102D1E65FB4DC61" VARCHAR(511), - "REL_CD_040FC8B06B420BA5708AF4798102D1E65FB4DC61" jsonb + "REL_CD_040FC8B06B420BA5708AF4798102D1E65FB4DC61" jsonb, + "REL_CD_66AEF506899F14F936A2F48F9444E2202F5D43F9" jsonb, + "REL_CD_022F8280C0739C614C5F3293E7D8D349A8A10E30" jsonb ); -ALTER TABLE ONLY ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ALTER COLUMN "REL_CD_040FC8B06B420BA5708AF4798102D1E65FB4DC61" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "REL_CD_040FC8B06B420BA5708AF4798102D1E65FB4DC61" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "REL_CD_66AEF506899F14F936A2F48F9444E2202F5D43F9" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ALTER COLUMN "REL_CD_022F8280C0739C614C5F3293E7D8D349A8A10E30" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."78682DB1FFA2533BA45F8E4FAA5596E1A98479FC" ( +CREATE TABLE IF NOT EXISTS ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ( "id" VARCHAR(511), "name" TEXT, - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."78682DB1FFA2533BA45F8E4FAA5596E1A98479FC" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ( +CREATE TABLE IF NOT EXISTS ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "gNBDUId" BIGINT, "cmId" jsonb, "3786A6CA64C9422F9E7FC35B7B039F345BBDDA65" TEXT, - "gNBIdLength" BIGINT, + "gNBIdLength" INTEGER, "dUpLMNId" jsonb, "gNBId" BIGINT, "REL_FK_48B14FA5B787C6398AD1DE5EE670AD0D2A2CB36F" VARCHAR(511), "REL_ID_BDE0B6C74D14AC109D29A08D80E92D4D0DCAEB0B" VARCHAR(511), - "REL_CD_45E8E8693B1B8928376EAA8995D08AA7B1E483BD" jsonb + "REL_CD_45E8E8693B1B8928376EAA8995D08AA7B1E483BD" jsonb, + "REL_CD_7E9F11EFBF8974D7C7DAB02E181A0BE4148091C6" jsonb, + "REL_CD_FFF7E036187A7605BFC714483D2E60FD2FF6560B" jsonb ); -ALTER TABLE ONLY ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ALTER COLUMN "REL_CD_45E8E8693B1B8928376EAA8995D08AA7B1E483BD" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "REL_CD_45E8E8693B1B8928376EAA8995D08AA7B1E483BD" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "REL_CD_7E9F11EFBF8974D7C7DAB02E181A0BE4148091C6" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ALTER COLUMN "REL_CD_FFF7E036187A7605BFC714483D2E60FD2FF6560B" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ( +CREATE TABLE IF NOT EXISTS ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ( "id" VARCHAR(511), "aSide_B0FD0521695A211BFF76F413A31F28CBA32E57ED" VARCHAR(511), "bSide_84EF1134719BB6FCF33A94FF770311FC722BCF41" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ( +CREATE TABLE IF NOT EXISTS ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ( "id" VARCHAR(511), "aSide_AntennaCapability" VARCHAR(511), "bSide_AntennaModule" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."AntennaCapability" ( +CREATE TABLE IF NOT EXISTS ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "eUtranFqBands" jsonb, "fdn" TEXT, "geranFqBands" jsonb, @@ -160,125 +214,191 @@ CREATE TABLE IF NOT EXISTS ties_data."AntennaCapability" ( "REL_FK_used-by-lteSectorCarrier" VARCHAR(511) ); -ALTER TABLE ONLY ties_data."AntennaCapability" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."AntennaModule" ( +CREATE TABLE IF NOT EXISTS ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ( "id" VARCHAR(511), - "CD_sourceIds" jsonb, "totalTilt" BIGINT, + "cmId" jsonb, + "antennaBeamWidth" jsonb, + "positionWithinSector" TEXT, + "geo-location" geography, "mechanicalAntennaBearing" BIGINT, "fdn" TEXT, - "antennaModelNumber" TEXT, - "mechanicalAntennaTilt" BIGINT, - "positionWithinSector" TEXT, - "cmId" jsonb, "electricalAntennaTilt" BIGINT, + "mechanicalAntennaTilt" BIGINT, + "antennaModelNumber" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "REL_FK_grouped-by-sector" VARCHAR(511), "REL_ID_SECTOR_GROUPS_ANTENNAMODULE" VARCHAR(511), "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE" jsonb, "REL_FK_installed-at-site" VARCHAR(511), "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" VARCHAR(511), - "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb + "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb, + "REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb, + "REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE" jsonb ); -ALTER TABLE ONLY ties_data."AntennaModule" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."AntennaModule" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."AntennaModule" ALTER COLUMN "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ALTER COLUMN "REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ( +CREATE TABLE IF NOT EXISTS ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ( "id" VARCHAR(511), "aSide_AntennaModule" VARCHAR(511), "bSide_AntennaModule" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ( +CREATE TABLE IF NOT EXISTS ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ( "id" VARCHAR(511), "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C" VARCHAR(511), "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ( +CREATE TABLE IF NOT EXISTS ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ( "id" VARCHAR(511), "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C" VARCHAR(511), "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."CloudNativeApplication" ( +CREATE TABLE IF NOT EXISTS ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ( "id" VARCHAR(511), "name" TEXT, "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "REL_FK_realised-managedElement" VARCHAR(511), "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION" VARCHAR(511), "REL_CD_8F561B5FB3CF928F2C4046CE1A7C37A8FE06B9A7" jsonb, + "REL_CD_CCEBD4C63B90BD1764CB5A15C282D6CDBDF0B1F2" jsonb, + "REL_CD_21E2495C31F0DBF735976C90F4CD10D1215190E1" jsonb, "REL_FK_comprised-by-cloudNativeSystem" VARCHAR(511), "REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION" VARCHAR(511), "REL_CD_39262797D0119611B8459ECF46754A074711E485" jsonb, + "REL_CD_026A1F92A7D93728916AF3DCC2C013FB79E29D07" jsonb, + "REL_CD_D32E90288E1982363B2BD8DA9D2E90AA16F71575" jsonb, "REL_FK_deployed-on-namespace" VARCHAR(511), "REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" VARCHAR(511), - "REL_CD_sourceIds_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" jsonb + "REL_CD_sourceIds_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" jsonb, + "REL_CD_classifiers_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" jsonb, + "REL_CD_decorators_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" jsonb ); -ALTER TABLE ONLY ties_data."CloudNativeApplication" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."CloudNativeApplication" ALTER COLUMN "REL_CD_8F561B5FB3CF928F2C4046CE1A7C37A8FE06B9A7" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_8F561B5FB3CF928F2C4046CE1A7C37A8FE06B9A7" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_CCEBD4C63B90BD1764CB5A15C282D6CDBDF0B1F2" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_21E2495C31F0DBF735976C90F4CD10D1215190E1" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."CloudNativeApplication" ALTER COLUMN "REL_CD_39262797D0119611B8459ECF46754A074711E485" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_39262797D0119611B8459ECF46754A074711E485" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_026A1F92A7D93728916AF3DCC2C013FB79E29D07" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_D32E90288E1982363B2BD8DA9D2E90AA16F71575" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."CloudNativeApplication" ALTER COLUMN "REL_CD_sourceIds_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_sourceIds_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_classifiers_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ALTER COLUMN "REL_CD_decorators_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."CloudNativeSystem" ( +CREATE TABLE IF NOT EXISTS ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "REL_FK_deployed-managedElement" VARCHAR(511) ); -ALTER TABLE ONLY ties_data."CloudNativeSystem" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."CloudSite" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "geo-location" geography ); -ALTER TABLE ONLY ties_data."CloudSite" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."ENodeBFunction" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ( "id" VARCHAR(511), "fdn" TEXT, "eNBId" BIGINT, "cmId" jsonb, "eNodeBPlmnId" jsonb, "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "REL_FK_managed-by-managedElement" VARCHAR(511), "REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" VARCHAR(511), "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" jsonb, "REL_FK_realised-by-physicalNetworkAppliance" VARCHAR(511), "REL_ID_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE" VARCHAR(511), - "REL_CD_556274C475BA56EE4DEFB691F9037C869223A124" jsonb + "REL_CD_556274C475BA56EE4DEFB691F9037C869223A124" jsonb, + "REL_CD_C6C6D295144A637110DA4E6121BE13F30EFDBEBF" jsonb, + "REL_CD_B369805A0EB24F7C841B0E541A015F85AE2A23B1" jsonb ); -ALTER TABLE ONLY ties_data."ENodeBFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."ENodeBFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."ENodeBFunction" ALTER COLUMN "REL_CD_556274C475BA56EE4DEFB691F9037C869223A124" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_556274C475BA56EE4DEFB691F9037C869223A124" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_C6C6D295144A637110DA4E6121BE13F30EFDBEBF" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ALTER COLUMN "REL_CD_B369805A0EB24F7C841B0E541A015F85AE2A23B1" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."EUtranCell" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "earfcn" BIGINT, "earfcndl" BIGINT, "duplexType" TEXT, @@ -290,103 +410,151 @@ CREATE TABLE IF NOT EXISTS ties_data."EUtranCell" ( "REL_FK_grouped-by-sector" VARCHAR(511), "REL_ID_SECTOR_GROUPS_EUTRANCELL" VARCHAR(511), "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL" jsonb, "REL_FK_provided-by-enodebFunction" VARCHAR(511), "REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" VARCHAR(511), - "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb + "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb, + "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb, + "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL" jsonb ); -ALTER TABLE ONLY ties_data."EUtranCell" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."EUtranCell" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."EUtranCell" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ALTER COLUMN "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ( +CREATE TABLE IF NOT EXISTS ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ( "id" VARCHAR(511), "aSide_GNBCUCPFunction" VARCHAR(511), "bSide_CloudNativeApplication" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBCUCPFunction" ( +CREATE TABLE IF NOT EXISTS ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "fdn" TEXT, "pLMNId" jsonb, "gNBCUName" TEXT, "gNBId" BIGINT, "cmId" jsonb, - "gNBIdLength" BIGINT, + "gNBIdLength" INTEGER, "REL_FK_managed-by-managedElement" VARCHAR(511), "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" VARCHAR(511), - "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" jsonb ); -ALTER TABLE ONLY ties_data."GNBCUCPFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."GNBCUCPFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ( +CREATE TABLE IF NOT EXISTS ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ( "id" VARCHAR(511), "aSide_GNBCUUPFunction" VARCHAR(511), "bSide_CloudNativeApplication" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBCUUPFunction" ( +CREATE TABLE IF NOT EXISTS ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "gNBId" BIGINT, "fdn" TEXT, "cmId" jsonb, - "gNBIdLength" BIGINT, + "gNBIdLength" INTEGER, "REL_FK_managed-by-managedElement" VARCHAR(511), "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" VARCHAR(511), - "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" jsonb ); -ALTER TABLE ONLY ties_data."GNBCUUPFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."GNBCUUPFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ( +CREATE TABLE IF NOT EXISTS ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ( "id" VARCHAR(511), "aSide_GNBDUFunction" VARCHAR(511), "bSide_CloudNativeApplication" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."GNBDUFunction" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "fdn" TEXT, "gNBId" BIGINT, "dUpLMNId" jsonb, "gNBDUId" BIGINT, "cmId" jsonb, - "gNBIdLength" BIGINT, + "gNBIdLength" INTEGER, "REL_FK_managed-by-managedElement" VARCHAR(511), "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" VARCHAR(511), - "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb + "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" jsonb ); -ALTER TABLE ONLY ties_data."GNBDUFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."GNBDUFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."LTESectorCarrier" ( +CREATE TABLE IF NOT EXISTS ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "sectorCarrierType" TEXT, "essScLocalId" BIGINT, "fdn" TEXT, @@ -394,39 +562,63 @@ CREATE TABLE IF NOT EXISTS ties_data."LTESectorCarrier" ( "REL_FK_provided-by-enodebFunction" VARCHAR(511), "REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" VARCHAR(511), "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, + "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, + "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" jsonb, "REL_FK_used-antennaCapability" VARCHAR(511), "REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY" VARCHAR(511), "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, "REL_FK_used-by-euTranCell" VARCHAR(511), "REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" VARCHAR(511), - "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" jsonb + "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" jsonb, + "REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER" jsonb, + "REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER" jsonb ); -ALTER TABLE ONLY ties_data."LTESectorCarrier" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."LTESectorCarrier" ALTER COLUMN "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ALTER COLUMN "REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."ManagedElement" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "fdn" TEXT, "cmId" jsonb, "REL_FK_deployed-as-cloudNativeSystem" VARCHAR(511), "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" VARCHAR(511), - "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" jsonb + "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" jsonb, + "REL_CD_classifiers_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" jsonb, + "REL_CD_decorators_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" jsonb ); -ALTER TABLE ONLY ties_data."ManagedElement" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."ManagedElement" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "REL_CD_sourceIds_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "REL_CD_classifiers_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ALTER COLUMN "REL_CD_decorators_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."NRCellCU" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "nCI" BIGINT, "plmnId" jsonb, "fdn" TEXT, @@ -435,17 +627,25 @@ CREATE TABLE IF NOT EXISTS ties_data."NRCellCU" ( "cmId" jsonb, "REL_FK_provided-by-gnbcucpFunction" VARCHAR(511), "REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" VARCHAR(511), - "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb + "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb, + "REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb, + "REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" jsonb ); -ALTER TABLE ONLY ties_data."NRCellCU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRCellCU" ALTER COLUMN "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ALTER COLUMN "REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."NRCellDU" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "nRTAC" BIGINT, "fdn" TEXT, "nRPCI" BIGINT, @@ -455,20 +655,32 @@ CREATE TABLE IF NOT EXISTS ties_data."NRCellDU" ( "REL_FK_grouped-by-sector" VARCHAR(511), "REL_ID_SECTOR_GROUPS_NRCELLDU" VARCHAR(511), "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU" jsonb, + "REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU" jsonb, + "REL_CD_decorators_SECTOR_GROUPS_NRCELLDU" jsonb, "REL_FK_provided-by-gnbduFunction" VARCHAR(511), "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" VARCHAR(511), - "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb + "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb, + "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb, + "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU" jsonb ); -ALTER TABLE ONLY ties_data."NRCellDU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRCellDU" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_decorators_SECTOR_GROUPS_NRCELLDU" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRCellDU" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ALTER COLUMN "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."NRSectorCarrier" ( +CREATE TABLE IF NOT EXISTS ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "frequencyDL" BIGINT, "arfcnDL" BIGINT, "fdn" TEXT, @@ -479,876 +691,948 @@ CREATE TABLE IF NOT EXISTS ties_data."NRSectorCarrier" ( "REL_FK_used-by-nrCellDu" VARCHAR(511), "REL_ID_NRCELLDU_USES_NRSECTORCARRIER" VARCHAR(511), "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER" jsonb, + "REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER" jsonb, + "REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER" jsonb, "REL_FK_provided-by-gnbduFunction" VARCHAR(511), "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" VARCHAR(511), "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, + "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, + "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" jsonb, "REL_FK_used-antennaCapability" VARCHAR(511), "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY" VARCHAR(511), - "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb + "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb, + "REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY" jsonb ); -ALTER TABLE ONLY ties_data."NRSectorCarrier" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NRSectorCarrier" ALTER COLUMN "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ALTER COLUMN "REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."Namespace" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "REL_FK_deployed-on-nodeCluster" VARCHAR(511), "REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER" VARCHAR(511), - "REL_CD_sourceIds_NAMESPACE_DEPLOYED_ON_NODECLUSTER" jsonb + "REL_CD_sourceIds_NAMESPACE_DEPLOYED_ON_NODECLUSTER" jsonb, + "REL_CD_classifiers_NAMESPACE_DEPLOYED_ON_NODECLUSTER" jsonb, + "REL_CD_decorators_NAMESPACE_DEPLOYED_ON_NODECLUSTER" jsonb ); -ALTER TABLE ONLY ties_data."Namespace" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."Namespace" ALTER COLUMN "REL_CD_sourceIds_NAMESPACE_DEPLOYED_ON_NODECLUSTER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "REL_CD_sourceIds_NAMESPACE_DEPLOYED_ON_NODECLUSTER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "REL_CD_classifiers_NAMESPACE_DEPLOYED_ON_NODECLUSTER" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ALTER COLUMN "REL_CD_decorators_NAMESPACE_DEPLOYED_ON_NODECLUSTER" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."NodeCluster" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "REL_FK_located-at-cloudSite" VARCHAR(511), "REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE" VARCHAR(511), - "REL_CD_sourceIds_NODECLUSTER_LOCATED_AT_CLOUDSITE" jsonb + "REL_CD_sourceIds_NODECLUSTER_LOCATED_AT_CLOUDSITE" jsonb, + "REL_CD_classifiers_NODECLUSTER_LOCATED_AT_CLOUDSITE" jsonb, + "REL_CD_decorators_NODECLUSTER_LOCATED_AT_CLOUDSITE" jsonb ); -ALTER TABLE ONLY ties_data."NodeCluster" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."NodeCluster" ALTER COLUMN "REL_CD_sourceIds_NODECLUSTER_LOCATED_AT_CLOUDSITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "REL_CD_sourceIds_NODECLUSTER_LOCATED_AT_CLOUDSITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "REL_CD_classifiers_NODECLUSTER_LOCATED_AT_CLOUDSITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ALTER COLUMN "REL_CD_decorators_NODECLUSTER_LOCATED_AT_CLOUDSITE" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."PhysicalNetworkAppliance" ( +CREATE TABLE IF NOT EXISTS ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "geo-location" geography, "name" TEXT, "cmId" jsonb, "type" TEXT, "REL_FK_installed-at-site" VARCHAR(511), "REL_ID_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" VARCHAR(511), - "REL_CD_sourceIds_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" jsonb + "REL_CD_sourceIds_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" jsonb, + "REL_CD_classifiers_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" jsonb, + "REL_CD_decorators_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" jsonb ); -ALTER TABLE ONLY ties_data."PhysicalNetworkAppliance" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."PhysicalNetworkAppliance" ALTER COLUMN "REL_CD_sourceIds_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "REL_CD_sourceIds_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "REL_CD_classifiers_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ALTER COLUMN "REL_CD_decorators_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."Sector" ( +CREATE TABLE IF NOT EXISTS ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "azimuth" DECIMAL, "geo-location" geography, "sectorId" BIGINT ); -ALTER TABLE ONLY ties_data."Sector" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."Site" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-equipment_Site" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "name" TEXT, "geo-location" geography, "cmId" jsonb ); -ALTER TABLE ONLY ties_data."Site" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."TESTENTITYA_GROUPS_TESTENTITYB" ( +CREATE TABLE IF NOT EXISTS ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ( "id" VARCHAR(511), "aSide_TestEntityA" VARCHAR(511), "bSide_TestEntityB" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."TESTENTITYA_GROUPS_TESTENTITYB" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."TESTENTITYA_PROVIDES_TESTENTITYB" ( +CREATE TABLE IF NOT EXISTS ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ( "id" VARCHAR(511), "aSide_TestEntityA" VARCHAR(511), "bSide_TestEntityB" VARCHAR(511), - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."TESTENTITYA_PROVIDES_TESTENTITYB" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."TestEntityA" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" ( "id" VARCHAR(511), "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "attribute1" TEXT ); -ALTER TABLE ONLY ties_data."TestEntityA" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."TestEntityB" ( +CREATE TABLE IF NOT EXISTS ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ( "id" VARCHAR(511), - "CD_sourceIds" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, "attribute1" TEXT, "REL_FK_used-by-testEntityA" VARCHAR(511), "REL_ID_TESTENTITYA_USES_TESTENTITYB" VARCHAR(511), - "REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB" jsonb + "REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB" jsonb, + "REL_CD_classifiers_TESTENTITYA_USES_TESTENTITYB" jsonb, + "REL_CD_decorators_TESTENTITYA_USES_TESTENTITYB" jsonb ); -ALTER TABLE ONLY ties_data."TestEntityB" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -ALTER TABLE ONLY ties_data."TestEntityB" ALTER COLUMN "REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "REL_CD_classifiers_TESTENTITYA_USES_TESTENTITYB" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ALTER COLUMN "REL_CD_decorators_TESTENTITYA_USES_TESTENTITYB" SET DEFAULT '{}'; SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_GROUPS_TESTENTITYB', + '70003c8082751e1832e7bc5c0d83db6d22c4fcdc', 'PK_TESTENTITYA_GROUPS_TESTENTITYB_id', - 'ALTER TABLE ties_data."TESTENTITYA_GROUPS_TESTENTITYB" ADD CONSTRAINT "PK_TESTENTITYA_GROUPS_TESTENTITYB_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ADD CONSTRAINT "PK_TESTENTITYA_GROUPS_TESTENTITYB_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_PROVIDES_TESTENTITYB', + '73936e503f137d82d1422c0f08c66c7ff8b90209', 'PK_TESTENTITYA_PROVIDES_TESTENTITYB_id', - 'ALTER TABLE ties_data."TESTENTITYA_PROVIDES_TESTENTITYB" ADD CONSTRAINT "PK_TESTENTITYA_PROVIDES_TESTENTITYB_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ADD CONSTRAINT "PK_TESTENTITYA_PROVIDES_TESTENTITYB_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'TestEntityA', + 'o-ran-smo-teiv-ran-logical_TestEntityA', 'PK_TestEntityA_id', - 'ALTER TABLE ties_data."TestEntityA" ADD CONSTRAINT "PK_TestEntityA_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" ADD CONSTRAINT "PK_TestEntityA_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'TestEntityB', + 'o-ran-smo-teiv-ran-logical_TestEntityB', 'PK_TestEntityB_id', - 'ALTER TABLE ties_data."TestEntityB" ADD CONSTRAINT "PK_TestEntityB_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ADD CONSTRAINT "PK_TestEntityB_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_GROUPS_TESTENTITYB', + '70003c8082751e1832e7bc5c0d83db6d22c4fcdc', 'FK_TESTENTITYA_GROUPS_TESTENTITYB_aSide_TestEntityA', - 'ALTER TABLE ties_data."TESTENTITYA_GROUPS_TESTENTITYB" ADD CONSTRAINT "FK_TESTENTITYA_GROUPS_TESTENTITYB_aSide_TestEntityA" FOREIGN KEY ("aSide_TestEntityA") REFERENCES ties_data."TestEntityA" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ADD CONSTRAINT "FK_TESTENTITYA_GROUPS_TESTENTITYB_aSide_TestEntityA" FOREIGN KEY ("aSide_TestEntityA") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_GROUPS_TESTENTITYB', + '70003c8082751e1832e7bc5c0d83db6d22c4fcdc', 'FK_TESTENTITYA_GROUPS_TESTENTITYB_bSide_TestEntityB', - 'ALTER TABLE ties_data."TESTENTITYA_GROUPS_TESTENTITYB" ADD CONSTRAINT "FK_TESTENTITYA_GROUPS_TESTENTITYB_bSide_TestEntityB" FOREIGN KEY ("bSide_TestEntityB") REFERENCES ties_data."TestEntityB" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."70003c8082751e1832e7bc5c0d83db6d22c4fcdc" ADD CONSTRAINT "FK_TESTENTITYA_GROUPS_TESTENTITYB_bSide_TestEntityB" FOREIGN KEY ("bSide_TestEntityB") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_PROVIDES_TESTENTITYB', + '73936e503f137d82d1422c0f08c66c7ff8b90209', 'FK_TESTENTITYA_PROVIDES_TESTENTITYB_aSide_TestEntityA', - 'ALTER TABLE ties_data."TESTENTITYA_PROVIDES_TESTENTITYB" ADD CONSTRAINT "FK_TESTENTITYA_PROVIDES_TESTENTITYB_aSide_TestEntityA" FOREIGN KEY ("aSide_TestEntityA") REFERENCES ties_data."TestEntityA" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ADD CONSTRAINT "FK_TESTENTITYA_PROVIDES_TESTENTITYB_aSide_TestEntityA" FOREIGN KEY ("aSide_TestEntityA") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'TESTENTITYA_PROVIDES_TESTENTITYB', + '73936e503f137d82d1422c0f08c66c7ff8b90209', 'FK_TESTENTITYA_PROVIDES_TESTENTITYB_bSide_TestEntityB', - 'ALTER TABLE ties_data."TESTENTITYA_PROVIDES_TESTENTITYB" ADD CONSTRAINT "FK_TESTENTITYA_PROVIDES_TESTENTITYB_bSide_TestEntityB" FOREIGN KEY ("bSide_TestEntityB") REFERENCES ties_data."TestEntityB" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."73936e503f137d82d1422c0f08c66c7ff8b90209" ADD CONSTRAINT "FK_TESTENTITYA_PROVIDES_TESTENTITYB_bSide_TestEntityB" FOREIGN KEY ("bSide_TestEntityB") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'TestEntityB', + 'o-ran-smo-teiv-ran-logical_TestEntityB', 'FK_TestEntityB_REL_FK_used-by-testEntityA', - 'ALTER TABLE ties_data."TestEntityB" ADD CONSTRAINT "FK_TestEntityB_REL_FK_used-by-testEntityA" FOREIGN KEY ("REL_FK_used-by-testEntityA") REFERENCES ties_data."TestEntityA" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ADD CONSTRAINT "FK_TestEntityB_REL_FK_used-by-testEntityA" FOREIGN KEY ("REL_FK_used-by-testEntityA") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_TestEntityA" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'TestEntityB', + 'o-ran-smo-teiv-ran-logical_TestEntityB', 'UNIQUE_TestEntityB_REL_ID_TESTENTITYA_USES_TESTENTITYB', - 'ALTER TABLE ties_data."TestEntityB" ADD CONSTRAINT "UNIQUE_TestEntityB_REL_ID_TESTENTITYA_USES_TESTENTITYB" UNIQUE ("REL_ID_TESTENTITYA_USES_TESTENTITYB");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_TestEntityB" ADD CONSTRAINT "UNIQUE_TestEntityB_REL_ID_TESTENTITYA_USES_TESTENTITYB" UNIQUE ("REL_ID_TESTENTITYA_USES_TESTENTITYB");' ); -ALTER TABLE ONLY ties_data."Site" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."o-ran-smo-teiv-ran-equipment_Site" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; -CREATE TABLE IF NOT EXISTS ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" ( +CREATE TABLE IF NOT EXISTS ties_data."341622dca4e0350289717b52df5883edc3fa0280" ( "id" VARCHAR(511), "fdn" TEXT, - "CD_sourceIds" jsonb + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb ); -ALTER TABLE ONLY ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."341622dca4e0350289717b52df5883edc3fa0280" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."341622dca4e0350289717b52df5883edc3fa0280" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; +ALTER TABLE ONLY ties_data."341622dca4e0350289717b52df5883edc3fa0280" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; SELECT ties_data.create_constraint_if_not_exists( - '003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F', + 'ef701af8e1445ed5d377664ba1d3d1c645e31639', 'PK_F568C5029499EE188A168886B2EF09C0D1FAAA9F', - 'ALTER TABLE ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" ADD CONSTRAINT "PK_F568C5029499EE188A168886B2EF09C0D1FAAA9F" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ADD CONSTRAINT "PK_F568C5029499EE188A168886B2EF09C0D1FAAA9F" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '1EF2A41C34A961CD8AE603E020B7B8B57345267F', + 'fa2dceaf53e045c136ce9db9bc5faae65a29fa4d', 'PK_19E2CBE3A8BBA12A7D9EC9923573BC0A65B1EC4A', - 'ALTER TABLE ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ADD CONSTRAINT "PK_19E2CBE3A8BBA12A7D9EC9923573BC0A65B1EC4A" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ADD CONSTRAINT "PK_19E2CBE3A8BBA12A7D9EC9923573BC0A65B1EC4A" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '25978231183BE3B9ADD7DBE6C77F5E59696CDE5F', + '5f8facd51b2bbddc90d9dee9be697907441892d0', 'PK_F52E445B46B712C0D9014D194AB039C205E69818', - 'ALTER TABLE ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ADD CONSTRAINT "PK_F52E445B46B712C0D9014D194AB039C205E69818" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ADD CONSTRAINT "PK_F52E445B46B712C0D9014D194AB039C205E69818" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '50AC08AB775076E74FC4891954F1D99D3D293ACC', + '300672c8a708d6af0b9af2f9accdff5e6e005721', 'PK_CCB39BED50FEF60B1B1F86A7C938BE89B7D90D38', - 'ALTER TABLE ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ADD CONSTRAINT "PK_CCB39BED50FEF60B1B1F86A7C938BE89B7D90D38" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ADD CONSTRAINT "PK_CCB39BED50FEF60B1B1F86A7C938BE89B7D90D38" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '78682DB1FFA2533BA45F8E4FAA5596E1A98479FC', + 'bc563e4310b0538e6bdd35f52684160af5b23671', 'PK_77881E9D6F659316F836050DDC6E26FA4DE425EE', - 'ALTER TABLE ties_data."78682DB1FFA2533BA45F8E4FAA5596E1A98479FC" ADD CONSTRAINT "PK_77881E9D6F659316F836050DDC6E26FA4DE425EE" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ADD CONSTRAINT "PK_77881E9D6F659316F836050DDC6E26FA4DE425EE" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '7D7AACEBB0E4E4732835BA4BFE708DDD3738962D', + '3fdb9cd7557edf559a0e4de88df220e7545884b5', 'PK_079D5D67E043B09F9C7CD4F6EA1DB12688D43F69', - 'ALTER TABLE ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ADD CONSTRAINT "PK_079D5D67E043B09F9C7CD4F6EA1DB12688D43F69" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ADD CONSTRAINT "PK_079D5D67E043B09F9C7CD4F6EA1DB12688D43F69" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'AC201B3A42917A9A983A1E3683B67C38C50630FC', + 'f86057a8762a50b1c7fb07af9d5c001bffaefd15', 'PK_5D1AC46C58E1FE44FB266F86CE79B3AEBE1D92B3', - 'ALTER TABLE ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ADD CONSTRAINT "PK_5D1AC46C58E1FE44FB266F86CE79B3AEBE1D92B3" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ADD CONSTRAINT "PK_5D1AC46C58E1FE44FB266F86CE79B3AEBE1D92B3" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE', - 'PK_ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE_id', - 'ALTER TABLE ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "PK_ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE_id" PRIMARY KEY ("id");' + '5b8a47d4a8297a0a1d31e091af06e26d25ef6caf', + 'PK_5b8a47d4a8297a0a1d31e091af06e26d25ef6caf_id', + 'ALTER TABLE ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ADD CONSTRAINT "PK_5b8a47d4a8297a0a1d31e091af06e26d25ef6caf_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaCapability', + '88f1bd76c7a935fb505cf235e6819f46c55ec98a', 'PK_AntennaCapability_id', - 'ALTER TABLE ties_data."AntennaCapability" ADD CONSTRAINT "PK_AntennaCapability_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ADD CONSTRAINT "PK_AntennaCapability_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaModule', + 'f8caf5ebe876c3001d67efe06e4d83abf0babe31', 'PK_AntennaModule_id', - 'ALTER TABLE ties_data."AntennaModule" ADD CONSTRAINT "PK_AntennaModule_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ADD CONSTRAINT "PK_AntennaModule_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'PK_CloudNativeApplication_id', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "PK_CloudNativeApplication_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "PK_CloudNativeApplication_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeSystem', + '163276fa439cdfccabb80f7acacb6fa638e8d314', 'PK_CloudNativeSystem_id', - 'ALTER TABLE ties_data."CloudNativeSystem" ADD CONSTRAINT "PK_CloudNativeSystem_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ADD CONSTRAINT "PK_CloudNativeSystem_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudSite', + 'o-ran-smo-teiv-ran-cloud_CloudSite', 'PK_CloudSite_id', - 'ALTER TABLE ties_data."CloudSite" ADD CONSTRAINT "PK_CloudSite_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ADD CONSTRAINT "PK_CloudSite_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ENodeBFunction', + 'o-ran-smo-teiv-ran-logical_ENodeBFunction', 'PK_ENodeBFunction_id', - 'ALTER TABLE ties_data."ENodeBFunction" ADD CONSTRAINT "PK_ENodeBFunction_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ADD CONSTRAINT "PK_ENodeBFunction_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'EUtranCell', + 'o-ran-smo-teiv-ran-logical_EUtranCell', 'PK_EUtranCell_id', - 'ALTER TABLE ties_data."EUtranCell" ADD CONSTRAINT "PK_EUtranCell_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ADD CONSTRAINT "PK_EUtranCell_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7', 'PK_GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id', - 'ALTER TABLE ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "PK_GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ADD CONSTRAINT "PK_GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFunction', + 'c4a425179d3089b5288fdf059079d0ea26977f0f', 'PK_GNBCUCPFunction_id', - 'ALTER TABLE ties_data."GNBCUCPFunction" ADD CONSTRAINT "PK_GNBCUCPFunction_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ADD CONSTRAINT "PK_GNBCUCPFunction_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '70a4a84bca01ea022ab24d8cb82422c572922675', 'PK_GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id', - 'ALTER TABLE ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "PK_GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ADD CONSTRAINT "PK_GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFunction', + '8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb', 'PK_GNBCUUPFunction_id', - 'ALTER TABLE ties_data."GNBCUUPFunction" ADD CONSTRAINT "PK_GNBCUUPFunction_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ADD CONSTRAINT "PK_GNBCUUPFunction_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '10484f157f490eb5b27e40dbfaf4d5f2be17c57c', 'PK_GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id', - 'ALTER TABLE ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "PK_GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ADD CONSTRAINT "PK_GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFunction', + 'o-ran-smo-teiv-ran-logical_GNBDUFunction', 'PK_GNBDUFunction_id', - 'ALTER TABLE ties_data."GNBDUFunction" ADD CONSTRAINT "PK_GNBDUFunction_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ADD CONSTRAINT "PK_GNBDUFunction_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'PK_LTESectorCarrier_id', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "PK_LTESectorCarrier_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "PK_LTESectorCarrier_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ManagedElement', + 'o-ran-smo-teiv-ran-oam_ManagedElement', 'PK_ManagedElement_id', - 'ALTER TABLE ties_data."ManagedElement" ADD CONSTRAINT "PK_ManagedElement_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ADD CONSTRAINT "PK_ManagedElement_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellCU', + 'o-ran-smo-teiv-ran-logical_NRCellCU', 'PK_NRCellCU_id', - 'ALTER TABLE ties_data."NRCellCU" ADD CONSTRAINT "PK_NRCellCU_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ADD CONSTRAINT "PK_NRCellCU_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellDU', + 'o-ran-smo-teiv-ran-logical_NRCellDU', 'PK_NRCellDU_id', - 'ALTER TABLE ties_data."NRCellDU" ADD CONSTRAINT "PK_NRCellDU_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ADD CONSTRAINT "PK_NRCellDU_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'PK_NRSectorCarrier_id', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "PK_NRSectorCarrier_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "PK_NRSectorCarrier_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'Namespace', + 'o-ran-smo-teiv-ran-cloud_Namespace', 'PK_Namespace_id', - 'ALTER TABLE ties_data."Namespace" ADD CONSTRAINT "PK_Namespace_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ADD CONSTRAINT "PK_Namespace_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NodeCluster', + 'o-ran-smo-teiv-ran-cloud_NodeCluster', 'PK_NodeCluster_id', - 'ALTER TABLE ties_data."NodeCluster" ADD CONSTRAINT "PK_NodeCluster_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ADD CONSTRAINT "PK_NodeCluster_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'PhysicalNetworkAppliance', + '57a20807ab3f39c86b0b5bf9a819e0881353fa1e', 'PK_PhysicalNetworkAppliance_id', - 'ALTER TABLE ties_data."PhysicalNetworkAppliance" ADD CONSTRAINT "PK_PhysicalNetworkAppliance_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ADD CONSTRAINT "PK_PhysicalNetworkAppliance_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'Sector', + '22174a23af5d5a96143c83ddfa78654df0acb697', 'PK_Sector_id', - 'ALTER TABLE ties_data."Sector" ADD CONSTRAINT "PK_Sector_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ADD CONSTRAINT "PK_Sector_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'Site', + 'o-ran-smo-teiv-ran-equipment_Site', 'PK_Site_id', - 'ALTER TABLE ties_data."Site" ADD CONSTRAINT "PK_Site_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-equipment_Site" ADD CONSTRAINT "PK_Site_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - '003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F', + 'ef701af8e1445ed5d377664ba1d3d1c645e31639', 'FK_54FE608944AC8EFFFBE7E55744B8BA52F6B29ABB', - 'ALTER TABLE ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" ADD CONSTRAINT "FK_54FE608944AC8EFFFBE7E55744B8BA52F6B29ABB" FOREIGN KEY ("REL_FK_C2F5EC33C0760F653CE7263A49C0B697FCA2D542") REFERENCES ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ADD CONSTRAINT "FK_54FE608944AC8EFFFBE7E55744B8BA52F6B29ABB" FOREIGN KEY ("REL_FK_C2F5EC33C0760F653CE7263A49C0B697FCA2D542") REFERENCES ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '1EF2A41C34A961CD8AE603E020B7B8B57345267F', + 'fa2dceaf53e045c136ce9db9bc5faae65a29fa4d', 'FK_9C091709D40D51DEE4DC87A44695F6EBA2E965DE', - 'ALTER TABLE ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ADD CONSTRAINT "FK_9C091709D40D51DEE4DC87A44695F6EBA2E965DE" FOREIGN KEY ("REL_FK_26958E3A529C4C8B68A29FDA906F8CD290F66078") REFERENCES ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ADD CONSTRAINT "FK_9C091709D40D51DEE4DC87A44695F6EBA2E965DE" FOREIGN KEY ("REL_FK_26958E3A529C4C8B68A29FDA906F8CD290F66078") REFERENCES ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '1EF2A41C34A961CD8AE603E020B7B8B57345267F', + 'fa2dceaf53e045c136ce9db9bc5faae65a29fa4d', 'UNIQUE_9A721779BB5547778B9258ACD73261B9AABFF302', - 'ALTER TABLE ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ADD CONSTRAINT "UNIQUE_9A721779BB5547778B9258ACD73261B9AABFF302" UNIQUE ("REL_ID_B7945BFD83380F3E12CF99F2B0F838F364027F92");' + 'ALTER TABLE ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ADD CONSTRAINT "UNIQUE_9A721779BB5547778B9258ACD73261B9AABFF302" UNIQUE ("REL_ID_B7945BFD83380F3E12CF99F2B0F838F364027F92");' ); SELECT ties_data.create_constraint_if_not_exists( - '25978231183BE3B9ADD7DBE6C77F5E59696CDE5F', + '5f8facd51b2bbddc90d9dee9be697907441892d0', 'FK_899FCB466B0BBCC040E945A3E746F5DE53CCCB29', - 'ALTER TABLE ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ADD CONSTRAINT "FK_899FCB466B0BBCC040E945A3E746F5DE53CCCB29" FOREIGN KEY ("REL_FK_AB87B417CCD05C332DDD0C60F0C6AB41D38B05E5") REFERENCES ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ADD CONSTRAINT "FK_899FCB466B0BBCC040E945A3E746F5DE53CCCB29" FOREIGN KEY ("REL_FK_AB87B417CCD05C332DDD0C60F0C6AB41D38B05E5") REFERENCES ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '25978231183BE3B9ADD7DBE6C77F5E59696CDE5F', + '5f8facd51b2bbddc90d9dee9be697907441892d0', 'UNIQUE_3DDA71C08F678AA7303FE0BD127CC27A80D1DDED', - 'ALTER TABLE ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ADD CONSTRAINT "UNIQUE_3DDA71C08F678AA7303FE0BD127CC27A80D1DDED" UNIQUE ("REL_ID_FC2F6A5A12917357B548C83F4B0C1AD58FA61413");' + 'ALTER TABLE ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ADD CONSTRAINT "UNIQUE_3DDA71C08F678AA7303FE0BD127CC27A80D1DDED" UNIQUE ("REL_ID_FC2F6A5A12917357B548C83F4B0C1AD58FA61413");' ); SELECT ties_data.create_constraint_if_not_exists( - '25978231183BE3B9ADD7DBE6C77F5E59696CDE5F', + '5f8facd51b2bbddc90d9dee9be697907441892d0', 'FK_E33FB71E6FAC69C92ADEEC55E63D401D21DF91AE', - 'ALTER TABLE ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ADD CONSTRAINT "FK_E33FB71E6FAC69C92ADEEC55E63D401D21DF91AE" FOREIGN KEY ("REL_FK_8C98B70070BBD11F90F192DDA3ECF6302390E956") REFERENCES ties_data."78682DB1FFA2533BA45F8E4FAA5596E1A98479FC" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ADD CONSTRAINT "FK_E33FB71E6FAC69C92ADEEC55E63D401D21DF91AE" FOREIGN KEY ("REL_FK_8C98B70070BBD11F90F192DDA3ECF6302390E956") REFERENCES ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '25978231183BE3B9ADD7DBE6C77F5E59696CDE5F', + '5f8facd51b2bbddc90d9dee9be697907441892d0', 'UNIQUE_287E65679DC2108F55F43D62A4325F6DECF372E1', - 'ALTER TABLE ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ADD CONSTRAINT "UNIQUE_287E65679DC2108F55F43D62A4325F6DECF372E1" UNIQUE ("REL_ID_AFBF10D23507AD3B6408947D2A9AF8465BA7B08C");' + 'ALTER TABLE ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ADD CONSTRAINT "UNIQUE_287E65679DC2108F55F43D62A4325F6DECF372E1" UNIQUE ("REL_ID_AFBF10D23507AD3B6408947D2A9AF8465BA7B08C");' ); SELECT ties_data.create_constraint_if_not_exists( - '50AC08AB775076E74FC4891954F1D99D3D293ACC', + '300672c8a708d6af0b9af2f9accdff5e6e005721', 'FK_D43434F9F6FD1C14BE14A0EEDA4C9918B26E82F1', - 'ALTER TABLE ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ADD CONSTRAINT "FK_D43434F9F6FD1C14BE14A0EEDA4C9918B26E82F1" FOREIGN KEY ("REL_FK_609963BFEE15FF824280FBE201313C3CDACDDDCE") REFERENCES ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ADD CONSTRAINT "FK_D43434F9F6FD1C14BE14A0EEDA4C9918B26E82F1" FOREIGN KEY ("REL_FK_609963BFEE15FF824280FBE201313C3CDACDDDCE") REFERENCES ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '50AC08AB775076E74FC4891954F1D99D3D293ACC', + '300672c8a708d6af0b9af2f9accdff5e6e005721', 'UNIQUE_4E6028C8AF5DB6D082B612C5CBB5B32A943C0AAD', - 'ALTER TABLE ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ADD CONSTRAINT "UNIQUE_4E6028C8AF5DB6D082B612C5CBB5B32A943C0AAD" UNIQUE ("REL_ID_040FC8B06B420BA5708AF4798102D1E65FB4DC61");' + 'ALTER TABLE ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ADD CONSTRAINT "UNIQUE_4E6028C8AF5DB6D082B612C5CBB5B32A943C0AAD" UNIQUE ("REL_ID_040FC8B06B420BA5708AF4798102D1E65FB4DC61");' ); SELECT ties_data.create_constraint_if_not_exists( - '7D7AACEBB0E4E4732835BA4BFE708DDD3738962D', + '3fdb9cd7557edf559a0e4de88df220e7545884b5', 'FK_C5EB2FEB41FDD27A7CED04A3FD665B4BDEF994F5', - 'ALTER TABLE ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ADD CONSTRAINT "FK_C5EB2FEB41FDD27A7CED04A3FD665B4BDEF994F5" FOREIGN KEY ("REL_FK_48B14FA5B787C6398AD1DE5EE670AD0D2A2CB36F") REFERENCES ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ADD CONSTRAINT "FK_C5EB2FEB41FDD27A7CED04A3FD665B4BDEF994F5" FOREIGN KEY ("REL_FK_48B14FA5B787C6398AD1DE5EE670AD0D2A2CB36F") REFERENCES ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - '7D7AACEBB0E4E4732835BA4BFE708DDD3738962D', + '3fdb9cd7557edf559a0e4de88df220e7545884b5', 'UNIQUE_176E72F1225D7EEFC222D87B6EC4D66DD968BD13', - 'ALTER TABLE ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ADD CONSTRAINT "UNIQUE_176E72F1225D7EEFC222D87B6EC4D66DD968BD13" UNIQUE ("REL_ID_BDE0B6C74D14AC109D29A08D80E92D4D0DCAEB0B");' + 'ALTER TABLE ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ADD CONSTRAINT "UNIQUE_176E72F1225D7EEFC222D87B6EC4D66DD968BD13" UNIQUE ("REL_ID_BDE0B6C74D14AC109D29A08D80E92D4D0DCAEB0B");' ); SELECT ties_data.create_constraint_if_not_exists( - 'AC201B3A42917A9A983A1E3683B67C38C50630FC', + 'f86057a8762a50b1c7fb07af9d5c001bffaefd15', 'FK_BFC9C18D6DBCD1FFC021B021CF31444EAA1FEDCA', - 'ALTER TABLE ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ADD CONSTRAINT "FK_BFC9C18D6DBCD1FFC021B021CF31444EAA1FEDCA" FOREIGN KEY ("aSide_B0FD0521695A211BFF76F413A31F28CBA32E57ED") REFERENCES ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ADD CONSTRAINT "FK_BFC9C18D6DBCD1FFC021B021CF31444EAA1FEDCA" FOREIGN KEY ("aSide_B0FD0521695A211BFF76F413A31F28CBA32E57ED") REFERENCES ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'AC201B3A42917A9A983A1E3683B67C38C50630FC', + 'f86057a8762a50b1c7fb07af9d5c001bffaefd15', 'FK_EADC754A352728E72F7320F69D802725C71EDE3E', - 'ALTER TABLE ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ADD CONSTRAINT "FK_EADC754A352728E72F7320F69D802725C71EDE3E" FOREIGN KEY ("bSide_84EF1134719BB6FCF33A94FF770311FC722BCF41") REFERENCES ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ADD CONSTRAINT "FK_EADC754A352728E72F7320F69D802725C71EDE3E" FOREIGN KEY ("bSide_84EF1134719BB6FCF33A94FF770311FC722BCF41") REFERENCES ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE', + '5b8a47d4a8297a0a1d31e091af06e26d25ef6caf', 'FK_03713853A2B7ACDC198858CAFBFF355026FEA0B3', - 'ALTER TABLE ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "FK_03713853A2B7ACDC198858CAFBFF355026FEA0B3" FOREIGN KEY ("aSide_AntennaCapability") REFERENCES ties_data."AntennaCapability" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ADD CONSTRAINT "FK_03713853A2B7ACDC198858CAFBFF355026FEA0B3" FOREIGN KEY ("aSide_AntennaCapability") REFERENCES ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE', + '5b8a47d4a8297a0a1d31e091af06e26d25ef6caf', 'FK_5059CE8D2FEE5A1FAD9E06F4FAAFC148BAEA70E3', - 'ALTER TABLE ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "FK_5059CE8D2FEE5A1FAD9E06F4FAAFC148BAEA70E3" FOREIGN KEY ("bSide_AntennaModule") REFERENCES ties_data."AntennaModule" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ADD CONSTRAINT "FK_5059CE8D2FEE5A1FAD9E06F4FAAFC148BAEA70E3" FOREIGN KEY ("bSide_AntennaModule") REFERENCES ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaCapability', + '88f1bd76c7a935fb505cf235e6819f46c55ec98a', 'FK_AntennaCapability_REL_FK_used-by-lteSectorCarrier', - 'ALTER TABLE ties_data."AntennaCapability" ADD CONSTRAINT "FK_AntennaCapability_REL_FK_used-by-lteSectorCarrier" FOREIGN KEY ("REL_FK_used-by-lteSectorCarrier") REFERENCES ties_data."LTESectorCarrier" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ADD CONSTRAINT "FK_AntennaCapability_REL_FK_used-by-lteSectorCarrier" FOREIGN KEY ("REL_FK_used-by-lteSectorCarrier") REFERENCES ties_data."c88307168935f02fdecc084ea5040bb9db16c701" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaModule', + 'f8caf5ebe876c3001d67efe06e4d83abf0babe31', 'FK_AntennaModule_REL_FK_grouped-by-sector', - 'ALTER TABLE ties_data."AntennaModule" ADD CONSTRAINT "FK_AntennaModule_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."Sector" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ADD CONSTRAINT "FK_AntennaModule_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaModule', + 'f8caf5ebe876c3001d67efe06e4d83abf0babe31', 'UNIQUE_AntennaModule_REL_ID_SECTOR_GROUPS_ANTENNAMODULE', - 'ALTER TABLE ties_data."AntennaModule" ADD CONSTRAINT "UNIQUE_AntennaModule_REL_ID_SECTOR_GROUPS_ANTENNAMODULE" UNIQUE ("REL_ID_SECTOR_GROUPS_ANTENNAMODULE");' + 'ALTER TABLE ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ADD CONSTRAINT "UNIQUE_AntennaModule_REL_ID_SECTOR_GROUPS_ANTENNAMODULE" UNIQUE ("REL_ID_SECTOR_GROUPS_ANTENNAMODULE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaModule', + 'f8caf5ebe876c3001d67efe06e4d83abf0babe31', 'FK_AntennaModule_REL_FK_installed-at-site', - 'ALTER TABLE ties_data."AntennaModule" ADD CONSTRAINT "FK_AntennaModule_REL_FK_installed-at-site" FOREIGN KEY ("REL_FK_installed-at-site") REFERENCES ties_data."Site" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ADD CONSTRAINT "FK_AntennaModule_REL_FK_installed-at-site" FOREIGN KEY ("REL_FK_installed-at-site") REFERENCES ties_data."o-ran-smo-teiv-ran-equipment_Site" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'AntennaModule', + 'f8caf5ebe876c3001d67efe06e4d83abf0babe31', 'UNIQUE_AntennaModule_REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE', - 'ALTER TABLE ties_data."AntennaModule" ADD CONSTRAINT "UNIQUE_AntennaModule_REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" UNIQUE ("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE");' + 'ALTER TABLE ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ADD CONSTRAINT "UNIQUE_AntennaModule_REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" UNIQUE ("REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'FK_CloudNativeApplication_REL_FK_realised-managedElement', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_realised-managedElement" FOREIGN KEY ("REL_FK_realised-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_realised-managedElement" FOREIGN KEY ("REL_FK_realised-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'UNIQUE_DAB3C12479849DA6C222B812C2A8CD1535D0C186', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "UNIQUE_DAB3C12479849DA6C222B812C2A8CD1535D0C186" UNIQUE ("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION");' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "UNIQUE_DAB3C12479849DA6C222B812C2A8CD1535D0C186" UNIQUE ("REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'FK_CloudNativeApplication_REL_FK_comprised-by-cloudNativeSystem', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_comprised-by-cloudNativeSystem" FOREIGN KEY ("REL_FK_comprised-by-cloudNativeSystem") REFERENCES ties_data."CloudNativeSystem" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_comprised-by-cloudNativeSystem" FOREIGN KEY ("REL_FK_comprised-by-cloudNativeSystem") REFERENCES ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'UNIQUE_F2774BC0806E925ADA0B1CAA50B5A41DFB7BF79A', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "UNIQUE_F2774BC0806E925ADA0B1CAA50B5A41DFB7BF79A" UNIQUE ("REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION");' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "UNIQUE_F2774BC0806E925ADA0B1CAA50B5A41DFB7BF79A" UNIQUE ("REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'FK_CloudNativeApplication_REL_FK_deployed-on-namespace', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_deployed-on-namespace" FOREIGN KEY ("REL_FK_deployed-on-namespace") REFERENCES ties_data."Namespace" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "FK_CloudNativeApplication_REL_FK_deployed-on-namespace" FOREIGN KEY ("REL_FK_deployed-on-namespace") REFERENCES ties_data."o-ran-smo-teiv-ran-cloud_Namespace" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeApplication', + 'e01fcb87ad2c34ce66c34420255e25aaca270e5e', 'UNIQUE_1A317D31DA93B0CF9A9F8A04077B0F60ABCFF49C', - 'ALTER TABLE ties_data."CloudNativeApplication" ADD CONSTRAINT "UNIQUE_1A317D31DA93B0CF9A9F8A04077B0F60ABCFF49C" UNIQUE ("REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE");' + 'ALTER TABLE ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ADD CONSTRAINT "UNIQUE_1A317D31DA93B0CF9A9F8A04077B0F60ABCFF49C" UNIQUE ("REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'CloudNativeSystem', + '163276fa439cdfccabb80f7acacb6fa638e8d314', 'FK_CloudNativeSystem_REL_FK_deployed-managedElement', - 'ALTER TABLE ties_data."CloudNativeSystem" ADD CONSTRAINT "FK_CloudNativeSystem_REL_FK_deployed-managedElement" FOREIGN KEY ("REL_FK_deployed-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ADD CONSTRAINT "FK_CloudNativeSystem_REL_FK_deployed-managedElement" FOREIGN KEY ("REL_FK_deployed-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ENodeBFunction', + 'o-ran-smo-teiv-ran-logical_ENodeBFunction', 'FK_ENodeBFunction_REL_FK_managed-by-managedElement', - 'ALTER TABLE ties_data."ENodeBFunction" ADD CONSTRAINT "FK_ENodeBFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ADD CONSTRAINT "FK_ENodeBFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ENodeBFunction', + 'o-ran-smo-teiv-ran-logical_ENodeBFunction', 'UNIQUE_F33037EE8037D0606D15FFB45EE8A27FD6DE30EE', - 'ALTER TABLE ties_data."ENodeBFunction" ADD CONSTRAINT "UNIQUE_F33037EE8037D0606D15FFB45EE8A27FD6DE30EE" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ADD CONSTRAINT "UNIQUE_F33037EE8037D0606D15FFB45EE8A27FD6DE30EE" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ENodeBFunction', + 'o-ran-smo-teiv-ran-logical_ENodeBFunction', 'FK_ENodeBFunction_REL_FK_realised-by-physicalNetworkAppliance', - 'ALTER TABLE ties_data."ENodeBFunction" ADD CONSTRAINT "FK_ENodeBFunction_REL_FK_realised-by-physicalNetworkAppliance" FOREIGN KEY ("REL_FK_realised-by-physicalNetworkAppliance") REFERENCES ties_data."PhysicalNetworkAppliance" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ADD CONSTRAINT "FK_ENodeBFunction_REL_FK_realised-by-physicalNetworkAppliance" FOREIGN KEY ("REL_FK_realised-by-physicalNetworkAppliance") REFERENCES ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ENodeBFunction', + 'o-ran-smo-teiv-ran-logical_ENodeBFunction', 'UNIQUE_6964DA7D7CC1F79A3DB8B43E5F77E42DF8DFBF73', - 'ALTER TABLE ties_data."ENodeBFunction" ADD CONSTRAINT "UNIQUE_6964DA7D7CC1F79A3DB8B43E5F77E42DF8DFBF73" UNIQUE ("REL_ID_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ADD CONSTRAINT "UNIQUE_6964DA7D7CC1F79A3DB8B43E5F77E42DF8DFBF73" UNIQUE ("REL_ID_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'EUtranCell', + 'o-ran-smo-teiv-ran-logical_EUtranCell', 'FK_EUtranCell_REL_FK_grouped-by-sector', - 'ALTER TABLE ties_data."EUtranCell" ADD CONSTRAINT "FK_EUtranCell_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."Sector" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ADD CONSTRAINT "FK_EUtranCell_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'EUtranCell', + 'o-ran-smo-teiv-ran-logical_EUtranCell', 'UNIQUE_EUtranCell_REL_ID_SECTOR_GROUPS_EUTRANCELL', - 'ALTER TABLE ties_data."EUtranCell" ADD CONSTRAINT "UNIQUE_EUtranCell_REL_ID_SECTOR_GROUPS_EUTRANCELL" UNIQUE ("REL_ID_SECTOR_GROUPS_EUTRANCELL");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ADD CONSTRAINT "UNIQUE_EUtranCell_REL_ID_SECTOR_GROUPS_EUTRANCELL" UNIQUE ("REL_ID_SECTOR_GROUPS_EUTRANCELL");' ); SELECT ties_data.create_constraint_if_not_exists( - 'EUtranCell', + 'o-ran-smo-teiv-ran-logical_EUtranCell', 'FK_EUtranCell_REL_FK_provided-by-enodebFunction', - 'ALTER TABLE ties_data."EUtranCell" ADD CONSTRAINT "FK_EUtranCell_REL_FK_provided-by-enodebFunction" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."ENodeBFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ADD CONSTRAINT "FK_EUtranCell_REL_FK_provided-by-enodebFunction" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'EUtranCell', + 'o-ran-smo-teiv-ran-logical_EUtranCell', 'UNIQUE_EUtranCell_REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL', - 'ALTER TABLE ties_data."EUtranCell" ADD CONSTRAINT "UNIQUE_EUtranCell_REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ADD CONSTRAINT "UNIQUE_EUtranCell_REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7', 'FK_B2DDDC542E95DD31826EECEBBF67FD01DAF48833', - 'ALTER TABLE ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_B2DDDC542E95DD31826EECEBBF67FD01DAF48833" FOREIGN KEY ("aSide_GNBCUCPFunction") REFERENCES ties_data."GNBCUCPFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ADD CONSTRAINT "FK_B2DDDC542E95DD31826EECEBBF67FD01DAF48833" FOREIGN KEY ("aSide_GNBCUCPFunction") REFERENCES ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7', 'FK_95C3AD1FCFBD310B9947B9B622CA8E0FC2135DC5', - 'ALTER TABLE ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_95C3AD1FCFBD310B9947B9B622CA8E0FC2135DC5" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."CloudNativeApplication" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ADD CONSTRAINT "FK_95C3AD1FCFBD310B9947B9B622CA8E0FC2135DC5" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFunction', + 'c4a425179d3089b5288fdf059079d0ea26977f0f', 'FK_GNBCUCPFunction_REL_FK_managed-by-managedElement', - 'ALTER TABLE ties_data."GNBCUCPFunction" ADD CONSTRAINT "FK_GNBCUCPFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ADD CONSTRAINT "FK_GNBCUCPFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUCPFunction', + 'c4a425179d3089b5288fdf059079d0ea26977f0f', 'UNIQUE_249F73FF1F4316A56DEF4424FA43C2064FFBE4DD', - 'ALTER TABLE ties_data."GNBCUCPFunction" ADD CONSTRAINT "UNIQUE_249F73FF1F4316A56DEF4424FA43C2064FFBE4DD" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION");' + 'ALTER TABLE ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ADD CONSTRAINT "UNIQUE_249F73FF1F4316A56DEF4424FA43C2064FFBE4DD" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '70a4a84bca01ea022ab24d8cb82422c572922675', 'FK_F3346189A1BB0DA705219A4136349DF50AE8AA33', - 'ALTER TABLE ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_F3346189A1BB0DA705219A4136349DF50AE8AA33" FOREIGN KEY ("aSide_GNBCUUPFunction") REFERENCES ties_data."GNBCUUPFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ADD CONSTRAINT "FK_F3346189A1BB0DA705219A4136349DF50AE8AA33" FOREIGN KEY ("aSide_GNBCUUPFunction") REFERENCES ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '70a4a84bca01ea022ab24d8cb82422c572922675', 'FK_36215EA9FC5F31CC0F131E526A84A54CB006C66B', - 'ALTER TABLE ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_36215EA9FC5F31CC0F131E526A84A54CB006C66B" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."CloudNativeApplication" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ADD CONSTRAINT "FK_36215EA9FC5F31CC0F131E526A84A54CB006C66B" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFunction', + '8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb', 'FK_GNBCUUPFunction_REL_FK_managed-by-managedElement', - 'ALTER TABLE ties_data."GNBCUUPFunction" ADD CONSTRAINT "FK_GNBCUUPFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ADD CONSTRAINT "FK_GNBCUUPFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBCUUPFunction', + '8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb', 'UNIQUE_BDB349CDF0C4055902881ECCB71F460AE1DD323E', - 'ALTER TABLE ties_data."GNBCUUPFunction" ADD CONSTRAINT "UNIQUE_BDB349CDF0C4055902881ECCB71F460AE1DD323E" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION");' + 'ALTER TABLE ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ADD CONSTRAINT "UNIQUE_BDB349CDF0C4055902881ECCB71F460AE1DD323E" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '10484f157f490eb5b27e40dbfaf4d5f2be17c57c', 'FK_69C6800CC81731E475893CC85582971C7530C98E', - 'ALTER TABLE ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_69C6800CC81731E475893CC85582971C7530C98E" FOREIGN KEY ("aSide_GNBDUFunction") REFERENCES ties_data."GNBDUFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ADD CONSTRAINT "FK_69C6800CC81731E475893CC85582971C7530C98E" FOREIGN KEY ("aSide_GNBDUFunction") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION', + '10484f157f490eb5b27e40dbfaf4d5f2be17c57c', 'FK_CA6721EE0944CBBB8E071CEA630162ABD7DFF2DA', - 'ALTER TABLE ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ADD CONSTRAINT "FK_CA6721EE0944CBBB8E071CEA630162ABD7DFF2DA" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."CloudNativeApplication" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ADD CONSTRAINT "FK_CA6721EE0944CBBB8E071CEA630162ABD7DFF2DA" FOREIGN KEY ("bSide_CloudNativeApplication") REFERENCES ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFunction', + 'o-ran-smo-teiv-ran-logical_GNBDUFunction', 'FK_GNBDUFunction_REL_FK_managed-by-managedElement', - 'ALTER TABLE ties_data."GNBDUFunction" ADD CONSTRAINT "FK_GNBDUFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."ManagedElement" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ADD CONSTRAINT "FK_GNBDUFunction_REL_FK_managed-by-managedElement" FOREIGN KEY ("REL_FK_managed-by-managedElement") REFERENCES ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'GNBDUFunction', + 'o-ran-smo-teiv-ran-logical_GNBDUFunction', 'UNIQUE_08DFEFAF56EDDE43CBDC336F459D28C6518D3E1D', - 'ALTER TABLE ties_data."GNBDUFunction" ADD CONSTRAINT "UNIQUE_08DFEFAF56EDDE43CBDC336F459D28C6518D3E1D" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ADD CONSTRAINT "UNIQUE_08DFEFAF56EDDE43CBDC336F459D28C6518D3E1D" UNIQUE ("REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION");' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'FK_LTESectorCarrier_REL_FK_provided-by-enodebFunction', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_provided-by-enodebFunction" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."ENodeBFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_provided-by-enodebFunction" FOREIGN KEY ("REL_FK_provided-by-enodebFunction") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'UNIQUE_B9770D6C26DDA0173DB9690F6E3B42C111AF26E9', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "UNIQUE_B9770D6C26DDA0173DB9690F6E3B42C111AF26E9" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER");' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "UNIQUE_B9770D6C26DDA0173DB9690F6E3B42C111AF26E9" UNIQUE ("REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER");' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'FK_LTESectorCarrier_REL_FK_used-antennaCapability', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_used-antennaCapability" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."AntennaCapability" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_used-antennaCapability" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'UNIQUE_5D5FEB6B4B09D5D42A589753C684994CD0B96E88', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "UNIQUE_5D5FEB6B4B09D5D42A589753C684994CD0B96E88" UNIQUE ("REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY");' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "UNIQUE_5D5FEB6B4B09D5D42A589753C684994CD0B96E88" UNIQUE ("REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY");' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'FK_LTESectorCarrier_REL_FK_used-by-euTranCell', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_used-by-euTranCell" FOREIGN KEY ("REL_FK_used-by-euTranCell") REFERENCES ties_data."EUtranCell" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "FK_LTESectorCarrier_REL_FK_used-by-euTranCell" FOREIGN KEY ("REL_FK_used-by-euTranCell") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'LTESectorCarrier', + 'c88307168935f02fdecc084ea5040bb9db16c701', 'UNIQUE_LTESectorCarrier_REL_ID_EUTRANCELL_USES_LTESECTORCARRIER', - 'ALTER TABLE ties_data."LTESectorCarrier" ADD CONSTRAINT "UNIQUE_LTESectorCarrier_REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" UNIQUE ("REL_ID_EUTRANCELL_USES_LTESECTORCARRIER");' + 'ALTER TABLE ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ADD CONSTRAINT "UNIQUE_LTESectorCarrier_REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" UNIQUE ("REL_ID_EUTRANCELL_USES_LTESECTORCARRIER");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ManagedElement', + 'o-ran-smo-teiv-ran-oam_ManagedElement', 'FK_ManagedElement_REL_FK_deployed-as-cloudNativeSystem', - 'ALTER TABLE ties_data."ManagedElement" ADD CONSTRAINT "FK_ManagedElement_REL_FK_deployed-as-cloudNativeSystem" FOREIGN KEY ("REL_FK_deployed-as-cloudNativeSystem") REFERENCES ties_data."CloudNativeSystem" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ADD CONSTRAINT "FK_ManagedElement_REL_FK_deployed-as-cloudNativeSystem" FOREIGN KEY ("REL_FK_deployed-as-cloudNativeSystem") REFERENCES ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ManagedElement', + 'o-ran-smo-teiv-ran-oam_ManagedElement', 'UNIQUE_ADD7C124AEF822CB0293FC75E39449DC1AD097E5', - 'ALTER TABLE ties_data."ManagedElement" ADD CONSTRAINT "UNIQUE_ADD7C124AEF822CB0293FC75E39449DC1AD097E5" UNIQUE ("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ADD CONSTRAINT "UNIQUE_ADD7C124AEF822CB0293FC75E39449DC1AD097E5" UNIQUE ("REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellCU', + 'o-ran-smo-teiv-ran-logical_NRCellCU', 'FK_NRCellCU_REL_FK_provided-by-gnbcucpFunction', - 'ALTER TABLE ties_data."NRCellCU" ADD CONSTRAINT "FK_NRCellCU_REL_FK_provided-by-gnbcucpFunction" FOREIGN KEY ("REL_FK_provided-by-gnbcucpFunction") REFERENCES ties_data."GNBCUCPFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ADD CONSTRAINT "FK_NRCellCU_REL_FK_provided-by-gnbcucpFunction" FOREIGN KEY ("REL_FK_provided-by-gnbcucpFunction") REFERENCES ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellCU', + 'o-ran-smo-teiv-ran-logical_NRCellCU', 'UNIQUE_NRCellCU_REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU', - 'ALTER TABLE ties_data."NRCellCU" ADD CONSTRAINT "UNIQUE_NRCellCU_REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" UNIQUE ("REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ADD CONSTRAINT "UNIQUE_NRCellCU_REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" UNIQUE ("REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellDU', + 'o-ran-smo-teiv-ran-logical_NRCellDU', 'FK_NRCellDU_REL_FK_grouped-by-sector', - 'ALTER TABLE ties_data."NRCellDU" ADD CONSTRAINT "FK_NRCellDU_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."Sector" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ADD CONSTRAINT "FK_NRCellDU_REL_FK_grouped-by-sector" FOREIGN KEY ("REL_FK_grouped-by-sector") REFERENCES ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellDU', + 'o-ran-smo-teiv-ran-logical_NRCellDU', 'UNIQUE_NRCellDU_REL_ID_SECTOR_GROUPS_NRCELLDU', - 'ALTER TABLE ties_data."NRCellDU" ADD CONSTRAINT "UNIQUE_NRCellDU_REL_ID_SECTOR_GROUPS_NRCELLDU" UNIQUE ("REL_ID_SECTOR_GROUPS_NRCELLDU");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ADD CONSTRAINT "UNIQUE_NRCellDU_REL_ID_SECTOR_GROUPS_NRCELLDU" UNIQUE ("REL_ID_SECTOR_GROUPS_NRCELLDU");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellDU', + 'o-ran-smo-teiv-ran-logical_NRCellDU', 'FK_NRCellDU_REL_FK_provided-by-gnbduFunction', - 'ALTER TABLE ties_data."NRCellDU" ADD CONSTRAINT "FK_NRCellDU_REL_FK_provided-by-gnbduFunction" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."GNBDUFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ADD CONSTRAINT "FK_NRCellDU_REL_FK_provided-by-gnbduFunction" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRCellDU', + 'o-ran-smo-teiv-ran-logical_NRCellDU', 'UNIQUE_NRCellDU_REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU', - 'ALTER TABLE ties_data."NRCellDU" ADD CONSTRAINT "UNIQUE_NRCellDU_REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ADD CONSTRAINT "UNIQUE_NRCellDU_REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'FK_NRSectorCarrier_REL_FK_used-by-nrCellDu', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_used-by-nrCellDu" FOREIGN KEY ("REL_FK_used-by-nrCellDu") REFERENCES ties_data."NRCellDU" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_used-by-nrCellDu" FOREIGN KEY ("REL_FK_used-by-nrCellDu") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'UNIQUE_NRSectorCarrier_REL_ID_NRCELLDU_USES_NRSECTORCARRIER', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "UNIQUE_NRSectorCarrier_REL_ID_NRCELLDU_USES_NRSECTORCARRIER" UNIQUE ("REL_ID_NRCELLDU_USES_NRSECTORCARRIER");' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "UNIQUE_NRSectorCarrier_REL_ID_NRCELLDU_USES_NRSECTORCARRIER" UNIQUE ("REL_ID_NRCELLDU_USES_NRSECTORCARRIER");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'FK_NRSectorCarrier_REL_FK_provided-by-gnbduFunction', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_provided-by-gnbduFunction" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."GNBDUFunction" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_provided-by-gnbduFunction" FOREIGN KEY ("REL_FK_provided-by-gnbduFunction") REFERENCES ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'UNIQUE_872BE05F1989443F2595D99A77BC03733B2D1E2F', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "UNIQUE_872BE05F1989443F2595D99A77BC03733B2D1E2F" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER");' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "UNIQUE_872BE05F1989443F2595D99A77BC03733B2D1E2F" UNIQUE ("REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'FK_NRSectorCarrier_REL_FK_used-antennaCapability', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_used-antennaCapability" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."AntennaCapability" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "FK_NRSectorCarrier_REL_FK_used-antennaCapability" FOREIGN KEY ("REL_FK_used-antennaCapability") REFERENCES ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NRSectorCarrier', + '39a335dca201ef99ae06f4ffd1908b534f8c6c39', 'UNIQUE_EDF7D5C78EF6505848B1679B714D7831F5863991', - 'ALTER TABLE ties_data."NRSectorCarrier" ADD CONSTRAINT "UNIQUE_EDF7D5C78EF6505848B1679B714D7831F5863991" UNIQUE ("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY");' + 'ALTER TABLE ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ADD CONSTRAINT "UNIQUE_EDF7D5C78EF6505848B1679B714D7831F5863991" UNIQUE ("REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY");' ); SELECT ties_data.create_constraint_if_not_exists( - 'Namespace', + 'o-ran-smo-teiv-ran-cloud_Namespace', 'FK_Namespace_REL_FK_deployed-on-nodeCluster', - 'ALTER TABLE ties_data."Namespace" ADD CONSTRAINT "FK_Namespace_REL_FK_deployed-on-nodeCluster" FOREIGN KEY ("REL_FK_deployed-on-nodeCluster") REFERENCES ties_data."NodeCluster" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ADD CONSTRAINT "FK_Namespace_REL_FK_deployed-on-nodeCluster" FOREIGN KEY ("REL_FK_deployed-on-nodeCluster") REFERENCES ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'Namespace', + 'o-ran-smo-teiv-ran-cloud_Namespace', 'UNIQUE_Namespace_REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER', - 'ALTER TABLE ties_data."Namespace" ADD CONSTRAINT "UNIQUE_Namespace_REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER" UNIQUE ("REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ADD CONSTRAINT "UNIQUE_Namespace_REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER" UNIQUE ("REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER");' ); SELECT ties_data.create_constraint_if_not_exists( - 'NodeCluster', + 'o-ran-smo-teiv-ran-cloud_NodeCluster', 'FK_NodeCluster_REL_FK_located-at-cloudSite', - 'ALTER TABLE ties_data."NodeCluster" ADD CONSTRAINT "FK_NodeCluster_REL_FK_located-at-cloudSite" FOREIGN KEY ("REL_FK_located-at-cloudSite") REFERENCES ties_data."CloudSite" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ADD CONSTRAINT "FK_NodeCluster_REL_FK_located-at-cloudSite" FOREIGN KEY ("REL_FK_located-at-cloudSite") REFERENCES ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'NodeCluster', + 'o-ran-smo-teiv-ran-cloud_NodeCluster', 'UNIQUE_NodeCluster_REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE', - 'ALTER TABLE ties_data."NodeCluster" ADD CONSTRAINT "UNIQUE_NodeCluster_REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE" UNIQUE ("REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE");' + 'ALTER TABLE ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ADD CONSTRAINT "UNIQUE_NodeCluster_REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE" UNIQUE ("REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'PhysicalNetworkAppliance', + '57a20807ab3f39c86b0b5bf9a819e0881353fa1e', 'FK_PhysicalNetworkAppliance_REL_FK_installed-at-site', - 'ALTER TABLE ties_data."PhysicalNetworkAppliance" ADD CONSTRAINT "FK_PhysicalNetworkAppliance_REL_FK_installed-at-site" FOREIGN KEY ("REL_FK_installed-at-site") REFERENCES ties_data."Site" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ADD CONSTRAINT "FK_PhysicalNetworkAppliance_REL_FK_installed-at-site" FOREIGN KEY ("REL_FK_installed-at-site") REFERENCES ties_data."o-ran-smo-teiv-ran-equipment_Site" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'PhysicalNetworkAppliance', + '57a20807ab3f39c86b0b5bf9a819e0881353fa1e', 'UNIQUE_A9110A77514C472452AC80053A8010FBAF481AD0', - 'ALTER TABLE ties_data."PhysicalNetworkAppliance" ADD CONSTRAINT "UNIQUE_A9110A77514C472452AC80053A8010FBAF481AD0" UNIQUE ("REL_ID_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE");' + 'ALTER TABLE ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ADD CONSTRAINT "UNIQUE_A9110A77514C472452AC80053A8010FBAF481AD0" UNIQUE ("REL_ID_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNAMODULE_REALISED_BY_ANTENNAMODULE', + '5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6', 'PK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_id', - 'ALTER TABLE ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "PK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_id" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ADD CONSTRAINT "PK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_id" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNAMODULE_REALISED_BY_ANTENNAMODULE', + '5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6', 'FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_aSide_AntennaModule', - 'ALTER TABLE ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_aSide_AntennaModule" FOREIGN KEY ("aSide_AntennaModule") REFERENCES ties_data."AntennaModule" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ADD CONSTRAINT "FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_aSide_AntennaModule" FOREIGN KEY ("aSide_AntennaModule") REFERENCES ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'ANTENNAMODULE_REALISED_BY_ANTENNAMODULE', + '5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6', 'FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_bSide_AntennaModule', - 'ALTER TABLE ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ADD CONSTRAINT "FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_bSide_AntennaModule" FOREIGN KEY ("bSide_AntennaModule") REFERENCES ties_data."AntennaModule" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ADD CONSTRAINT "FK_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE_bSide_AntennaModule" FOREIGN KEY ("bSide_AntennaModule") REFERENCES ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'B69D3E92CA22CE61B921AE61BD3CF031791CF714', + '341622dca4e0350289717b52df5883edc3fa0280', 'PK_2673E8FB17E57FD56D5E897DA13412B9165B90AA', - 'ALTER TABLE ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" ADD CONSTRAINT "PK_2673E8FB17E57FD56D5E897DA13412B9165B90AA" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."341622dca4e0350289717b52df5883edc3fa0280" ADD CONSTRAINT "PK_2673E8FB17E57FD56D5E897DA13412B9165B90AA" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6', + 'cd39d44beed963d50df42cd301e63d288f911c97', 'PK_E3722EAF721B41FACDCF065D2017267CE2C90BED', - 'ALTER TABLE ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ADD CONSTRAINT "PK_E3722EAF721B41FACDCF065D2017267CE2C90BED" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ADD CONSTRAINT "PK_E3722EAF721B41FACDCF065D2017267CE2C90BED" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6', + 'cd39d44beed963d50df42cd301e63d288f911c97', 'FK_00AE9B9921E38ACFEE934695787FA8794817A6ED', - 'ALTER TABLE ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ADD CONSTRAINT "FK_00AE9B9921E38ACFEE934695787FA8794817A6ED" FOREIGN KEY ("aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C") REFERENCES ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ADD CONSTRAINT "FK_00AE9B9921E38ACFEE934695787FA8794817A6ED" FOREIGN KEY ("aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C") REFERENCES ties_data."341622dca4e0350289717b52df5883edc3fa0280" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6', + 'cd39d44beed963d50df42cd301e63d288f911c97', 'FK_68EED3C83D2C93559F7A61E7D05B4363CDF1DB8F', - 'ALTER TABLE ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ADD CONSTRAINT "FK_68EED3C83D2C93559F7A61E7D05B4363CDF1DB8F" FOREIGN KEY ("bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E") REFERENCES ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ADD CONSTRAINT "FK_68EED3C83D2C93559F7A61E7D05B4363CDF1DB8F" FOREIGN KEY ("bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E") REFERENCES ties_data."341622dca4e0350289717b52df5883edc3fa0280" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'C35AE10CFF62DEDC5E3FC3C40E47373B10800818', + 'c6f3a3396e9165e886da928c5fe1382fb20dc850', 'PK_F03D1DD176CD75707BD6217EF652705007C0F272', - 'ALTER TABLE ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ADD CONSTRAINT "PK_F03D1DD176CD75707BD6217EF652705007C0F272" PRIMARY KEY ("id");' + 'ALTER TABLE ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ADD CONSTRAINT "PK_F03D1DD176CD75707BD6217EF652705007C0F272" PRIMARY KEY ("id");' ); SELECT ties_data.create_constraint_if_not_exists( - 'C35AE10CFF62DEDC5E3FC3C40E47373B10800818', + 'c6f3a3396e9165e886da928c5fe1382fb20dc850', 'FK_E19DA712FB443E0212578638DF62281CFD6BFA7A', - 'ALTER TABLE ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ADD CONSTRAINT "FK_E19DA712FB443E0212578638DF62281CFD6BFA7A" FOREIGN KEY ("aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C") REFERENCES ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ADD CONSTRAINT "FK_E19DA712FB443E0212578638DF62281CFD6BFA7A" FOREIGN KEY ("aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C") REFERENCES ties_data."341622dca4e0350289717b52df5883edc3fa0280" (id) ON DELETE CASCADE;' ); SELECT ties_data.create_constraint_if_not_exists( - 'C35AE10CFF62DEDC5E3FC3C40E47373B10800818', + 'c6f3a3396e9165e886da928c5fe1382fb20dc850', 'FK_7772B14325D2340707AF687BF0F70F32914F935D', - 'ALTER TABLE ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ADD CONSTRAINT "FK_7772B14325D2340707AF687BF0F70F32914F935D" FOREIGN KEY ("bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E") REFERENCES ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" (id) ON DELETE CASCADE;' + 'ALTER TABLE ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ADD CONSTRAINT "FK_7772B14325D2340707AF687BF0F70F32914F935D" FOREIGN KEY ("bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E") REFERENCES ties_data."341622dca4e0350289717b52df5883edc3fa0280" (id) ON DELETE CASCADE;' ); diff --git a/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql b/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql new file mode 100644 index 0000000..0bb48d2 --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model-v1.sql @@ -0,0 +1,430 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +DROP SCHEMA IF EXISTS ties_model cascade; +CREATE SCHEMA IF NOT EXISTS ties_model; + +CREATE TABLE IF NOT EXISTS ties_model.execution_status ( + "schema" VARCHAR(127) PRIMARY KEY, + "status" VARCHAR(127) +); + +CREATE TABLE IF NOT EXISTS ties_model.hash_info ( + "name" VARCHAR(511) PRIMARY KEY, + "hashedValue" VARCHAR(511) NOT NULL, + "type" VARCHAR(511) +); + +CREATE TABLE IF NOT EXISTS ties_model.module_reference ( + "name" VARCHAR(511) PRIMARY KEY, + "namespace" VARCHAR(511), + "domain" VARCHAR(511), + "includedModules" jsonb DEFAULT '[]'::jsonb, + "revision" VARCHAR(511) NOT NULL, + "content" TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS ties_model.entity_info ( + "storedAt" VARCHAR(511) PRIMARY KEY, + "name" VARCHAR(511) NOT NULL, + "moduleReferenceName" VARCHAR(511) NOT NULL, + FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS ties_model.relationship_info ( + "name" VARCHAR(511) NOT NULL, + "aSideAssociationName" TEXT NOT NULL, + "aSideMOType" TEXT NOT NULL, + "aSideModule" TEXT NOT NULL, + "aSideMinCardinality" BIGINT NOT NULL, + "aSideMaxCardinality" BIGINT NOT NULL, + "bSideAssociationName" TEXT NOT NULL, + "bSideMOType" TEXT NOT NULL, + "bSideModule" TEXT NOT NULL, + "bSideMinCardinality" BIGINT NOT NULL, + "bSideMaxCardinality" BIGINT NOT NULL, + "associationKind" TEXT NOT NULL, + "relationshipDataLocation" TEXT NOT NULL, + "connectSameEntity" BOOLEAN NOT NULL, + "storedAt" VARCHAR(511) NOT NULL, + "moduleReferenceName" TEXT NOT NULL, + PRIMARY KEY ("name", "moduleReferenceName"), + FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE +); + +-- Update model schema exec status +INSERT INTO ties_model.execution_status("schema", "status") VALUES ('ties_model', 'success'); + +COPY ties_model.hash_info("name", "hashedValue", "type") FROM stdin; +CD_classifiers CD_classifiers COLUMN +CD_decorators CD_decorators COLUMN +CD_sourceIds CD_sourceIds COLUMN +FK_o-ran-smo-teiv-equipment_AntennaModule_REL_FK_grouped-by-sector FK_078764B2F3D613D44CC6E3586F564C83164D2481 CONSTRAINT +FK_o-ran-smo-teiv-equipment_AntennaModule_REL_FK_installed-at-site FK_E3BAEF04443354C0FC1837CF7964E05BEF9FD6CC CONSTRAINT +FK_o-ran-smo-teiv-ran_ENodeBFunction_REL_FK_managed-by-managedElement FK_6C99B14BF3C9BC6DE2D69AD55DF323ADCB174167 CONSTRAINT +FK_o-ran-smo-teiv-ran_EUtranCell_REL_FK_grouped-by-sector FK_o-ran-smo-teiv-ran_EUtranCell_REL_FK_grouped-by-sector CONSTRAINT +FK_o-ran-smo-teiv-ran_EUtranCell_REL_FK_provided-by-enodebFunction FK_2D1FA89480BF856AB865D58FAFB6AC0B476015EB CONSTRAINT +FK_o-ran-smo-teiv-ran_GNBCUCPFunction_REL_FK_managed-by-managedElement FK_F1FB8F88851067901B66D53EE1420D2ECCEC98A3 CONSTRAINT +FK_o-ran-smo-teiv-ran_GNBCUUPFunction_REL_FK_managed-by-managedElement FK_34D6E2537E8EE1D395CAF5BF9B2182A4696A1EAA CONSTRAINT +FK_o-ran-smo-teiv-ran_GNBDUFunction_REL_FK_managed-by-managedElement FK_F67FAF9D3E82B97104E2392DA0AC8A86DF2407CC CONSTRAINT +FK_o-ran-smo-teiv-ran_LTESectorCarrier_REL_FK_provided-by-enodebFunction FK_D0868FBC0BBE2754F4B765C4898C1A1700E2BEFD CONSTRAINT +FK_o-ran-smo-teiv-ran_LTESectorCarrier_REL_FK_used-antennaCapability FK_3D8DF3FBD9C042A888CEB382688C1E8F39D85AFE CONSTRAINT +FK_o-ran-smo-teiv-ran_LTESectorCarrier_REL_FK_used-by-euTranCell FK_96E6D4983CFFDF30FCA20423B5913DEE486E42D0 CONSTRAINT +FK_o-ran-smo-teiv-ran_NRCellCU_REL_FK_provided-by-gnbcucpFunction FK_F2CDD1E84C7F07BF8065F99A5F3488E91E3BB7B2 CONSTRAINT +FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_grouped-by-sector FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_grouped-by-sector CONSTRAINT +FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_provided-by-gnbduFunction FK_o-ran-smo-teiv-ran_NRCellDU_REL_FK_provided-by-gnbduFunction CONSTRAINT +FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_provided-by-gnbduFunction FK_F7978366174C82E41F0A6ABF29005FF01603858F CONSTRAINT +FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_used-antennaCapability FK_65D538D54EB33081C808540235FEB28823428E64 CONSTRAINT +FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_used-by-nrCellDu FK_o-ran-smo-teiv-ran_NRSectorCarrier_REL_FK_used-by-nrCellDu CONSTRAINT +FK_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_aSide_AntennaModule FK_D80D1E6B26DF620B4DE659C600A3B7F709A41960 CONSTRAINT +FK_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_bSide_AntennaCapability FK_7148BEED02C0617DE1DEEB6639F34A9FA9251B06 CONSTRAINT +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_CD_classifiers IDX_1C0CAFD80FDD6444044E3F76C7C0A7BDC35F9BC8 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_CD_sourceIds IDX_905011128A2C218B5352C19ED1FE9851F43EB911 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE IDX_17E417F7EF56809674BE1D5F5154DCCE01E00A96 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE IDX_83B6347C0C0A005D5E3D856D973D3322DFEDEA35 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE IDX_F497DEC01DA066CB09DA2AA7EDE3F4410078491B INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE IDX_5ABDB19E55A6BDEF33855F14CB1B3B8CF457912C INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_AntennaModule_antennaBeamWidth IDX_21B0F1FE632B6CB185C49BA6F00224068F443215 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_Site_CD_classifiers IDX_EEBF1BC3344E97988232825777AB13FAB6C4F3F0 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-equipment_Site_CD_sourceIds IDX_102A50584376DE25B6BBD7157594C607A5C957F2 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-oam_ManagedElement_CD_classifiers IDX_98AC4232BC02323E03416954215889CEE874A1E9 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-oam_ManagedElement_CD_sourceIds IDX_DDD73D6F4004BF3A96AA118281EE3E565A922B47 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_AntennaCapability_CD_classifiers IDX_E7FFE8F4A166AA9A382A0659762FFEC313A9EB5C INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_AntennaCapability_CD_sourceIds IDX_CC3E208A4EE51D3B505416A599F36F3C99F466C8 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_AntennaCapability_eUtranFqBands IDX_5FB80647AE3E5C0443A792618D65B9090EE2A3FC INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_AntennaCapability_geranFqBands IDX_A94722FF7B95D8974B494793908B57B4E1A9743B INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_AntennaCapability_nRFqBands IDX_441B5C05448D63552C6414BD59C13641D8A4408D INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_ENodeBFunction_CD_classifiers IDX_B598B74193845587BA03553CEDBA058D33956847 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_ENodeBFunction_CD_sourceIds IDX_3F7D14B4CF2CA74F28BA1600606E82C6E8C447C0 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_ENodeBFunction_REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION IDX_61CDCD3F69CF67EE740358D2C76FA796CFDA19BF INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_ENodeBFunction_REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION IDX_252AF4814C67384A7B05EA116316E83AFF9EB6AE INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_CD_classifiers IDX_C9C19F8F83F50C130F2EB6502ABB7B2833F1F783 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_CD_sourceIds IDX_84E36DC53519D3E334C60B5B02C1AB27130CFA24 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL IDX_4C77E3A51BFAB2FCD30425E4EB21CC7636438299 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL IDX_8A15E61498725DA9D8C78FC4B99053C06E88DCEC INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL IDX_976F6A0F8991F64592B6F9E716EFEECBD5400FDA INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_EUtranCell_REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL IDX_173887418DD4FD6FD592F6404EA784150B1822C0 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUCPFunction_CD_classifiers IDX_588840BAE32C7FF8CF0553F631DAAF8BB6E8E7C1 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUCPFunction_CD_sourceIds IDX_BE4B476041D559760931630000D3F4A6DFF42707 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUCPFunction_REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION IDX_1324070754C1EBF8EA78EF40743AFC1713733BA8 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUCPFunction_REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION IDX_E01081465B87F46E1CC7A22FE406C7B41C817E8C INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUUPFunction_CD_classifiers IDX_4C2B68358221A7FF0E68012DEDD3CBA2C4ED669F INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUUPFunction_CD_sourceIds IDX_C6D2419F8DC299FBC98342AA00BE92308C7566A7 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUUPFunction_REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION IDX_EB07ADD66F6CF51B9330403DE4500D05CA067647 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBCUUPFunction_REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION IDX_883506CAA3E742D82EEFCEE8C8F29927983B73B1 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBDUFunction_CD_classifiers IDX_601A4514FFACA8985471531013AFC8F760361F09 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBDUFunction_CD_sourceIds IDX_2BEF269CED354C2454AC2B2EABB134AC267A0C62 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBDUFunction_REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION IDX_04C614FDE6A4AE2AA106A1233D1DF95803FC122D INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_GNBDUFunction_REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION IDX_3065F7FB78C5AA9FF17972F825F89AED127A6324 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_CD_classifiers IDX_E754EB8AD825DB3111B07B9E5DA3B30C38DB406B INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_CD_sourceIds IDX_6EC539C61EA7078DBA264C9877B87FC263605D42 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER IDX_846B7740E8AA756B8C1409CD909D2DF73A47ED4C INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER IDX_B291D7EFCAD3BF06A2C11F8C0429ABABEEF8308B INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY IDX_3D3EFECFB917DAC074F56334224B19F8FD6BF8A5 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER IDX_1EBC7271CEA658156DE25286404CBC4593340F8E INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER IDX_F2D46817C2D618D8C33945F282299BF9EB49465E INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY IDX_7D01A5D21C990ACCBE65035C062C7D881A05F1EE INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellCU_CD_classifiers IDX_E5930226819982DC0CFC1FA64FB3600647222435 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellCU_CD_sourceIds IDX_0C443A16285D233F16966C2F0314CDC9D0F6D0B8 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellCU_REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU IDX_04BE1EB39848069422B97C28EE3C8ED18BCC6D33 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellCU_REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU IDX_36A671754CD510FFBDC2713FD142303DCA75DD65 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_CD_classifiers IDX_C437D39632DC79BAB6AC4F0880826A05425F9C32 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_CD_sourceIds IDX_FFD60DD99D80C276F402E66546F5DACB2D81EE26 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU IDX_2F4C43ED084968FDAF9943DB96741885C145FE1D INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU IDX_7CB4A7724F68D1CB2D12E8DE779BA9103F7DBE0A INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU IDX_1F6708B1E34FC908473DD7A7E5641E650B359BEF INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRCellDU_REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU IDX_6325926B4D2FDD1FBBB34250DABEA5E7229FF9F5 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_CD_classifiers IDX_050A80BEEF775E4D3CE216F282F23DB99DA2D798 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_CD_sourceIds IDX_8E34EC0B1DE7DDCE3B32ADD85B11E15F95C5644E INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER IDX_273D43FDDD1C4643ECF8BBE51B6B369C657F0861 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER IDX_ED50A5139F1449DBAD8DA10D45F5A5BF819EACBA INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY IDX_B975D24291849007D4AA6686C5D3983885D5C884 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER IDX_CD293AD1111E344D150340A13BD299924D29A9DA INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER IDX_7BFD17A71AB1B7765FE6431DA4E66C2EDE88AC3B INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY IDX_1F27C515A028616FAC422A02ABBEC402D5DBB2E5 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_Sector_CD_classifiers IDX_19C19556F9714850389595E0A16218FA229205FE INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-ran_Sector_CD_sourceIds IDX_E234B43A7CD7843672F08F2197AB46A2A50BECB0 INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_CD_classifiers IDX_DD0D676834B12CA2F7E8219310998376A08D7F5F INDEX +IDX_GIN_TRGM_OPS_ON_LIST_AS_JSONB_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_CD_sourceIds IDX_E896A9EB22A3F9F96CE75A271475316A98B629C8 INDEX +IDX_GIN_o-ran-smo-teiv-equipment_AntennaModule_CD_decorators IDX_GIN_o-ran-smo-teiv-equipment_AntennaModule_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE IDX_2321BFA482AD2700F41E2BA359F6EB00F47601B9 INDEX +IDX_GIN_o-ran-smo-teiv-equipment_AntennaModule_REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE IDX_6C6FBD69F47F41970595A8775DC99CA0F5E894A1 INDEX +IDX_GIN_o-ran-smo-teiv-equipment_Site_CD_decorators IDX_GIN_o-ran-smo-teiv-equipment_Site_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-oam_ManagedElement_CD_decorators IDX_GIN_o-ran-smo-teiv-oam_ManagedElement_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_AntennaCapability_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_AntennaCapability_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION IDX_35C17C8A9BA3EF3AEADA72C21F8090C38F575BAF INDEX +IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_eNodeBPlmnId IDX_GIN_o-ran-smo-teiv-ran_ENodeBFunction_eNodeBPlmnId INDEX +IDX_GIN_o-ran-smo-teiv-ran_EUtranCell_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_EUtranCell_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_EUtranCell_REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL IDX_FC7D79187227E0BFA69149048CC10E39AE540B8A INDEX +IDX_GIN_o-ran-smo-teiv-ran_EUtranCell_REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL IDX_E4EF3C904939ED4C0996EAB7CDFE1895CDF34BFB INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION IDX_13E734DE57346378DA4F21FC4EA030290A7E532F INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_pLMNId IDX_GIN_o-ran-smo-teiv-ran_GNBCUCPFunction_pLMNId INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBCUUPFunction_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_GNBCUUPFunction_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBCUUPFunction_REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION IDX_C3141DD7D2695EF74B13981AB378A58390D203D6 INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION IDX_298FCD184347DEC995B06FED2B1AE61F12BF766A INDEX +IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_dUpLMNId IDX_GIN_o-ran-smo-teiv-ran_GNBDUFunction_dUpLMNId INDEX +IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER IDX_44075E1D464599B61924196C20F2B88332520CD8 INDEX +IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER IDX_EAE482189F45D63CD1A88B0DD5F76EEE163D9E53 INDEX +IDX_GIN_o-ran-smo-teiv-ran_LTESectorCarrier_REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY IDX_4EE2AA643311DFCC13B6ED832EBE2FAB4CFDF494 INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU IDX_229957181BBC9D7B4535807BB397E8AA1378ED85 INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_plmnId IDX_GIN_o-ran-smo-teiv-ran_NRCellCU_plmnId INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellDU_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_NRCellDU_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellDU_REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU IDX_0E63D6B76B229961CD45D998C63175B569DDECD1 INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRCellDU_REL_CD_decorators_SECTOR_GROUPS_NRCELLDU IDX_0A03C47C13AD3B5C84D3D8081493D670E9CBDCD1 INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER IDX_EDE8B88F488F9380DB49CB2C141318FB33C2CCEC INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER IDX_2ADB5C6DCAEE8811FB1CA8FD9EB53381F35FCB70 INDEX +IDX_GIN_o-ran-smo-teiv-ran_NRSectorCarrier_REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY IDX_902B73F741160B9D4FBF62406D3D9ABBECAD8BE7 INDEX +IDX_GIN_o-ran-smo-teiv-ran_Sector_CD_decorators IDX_GIN_o-ran-smo-teiv-ran_Sector_CD_decorators INDEX +IDX_GIN_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_CD_decorators IDX_7BF09D0227840279556AD27ACECB068705893D28 INDEX +PK_o-ran-smo-teiv-equipment_AntennaModule_id PK_o-ran-smo-teiv-equipment_AntennaModule_id CONSTRAINT +PK_o-ran-smo-teiv-equipment_Site_id PK_o-ran-smo-teiv-equipment_Site_id CONSTRAINT +PK_o-ran-smo-teiv-oam_ManagedElement_id PK_o-ran-smo-teiv-oam_ManagedElement_id CONSTRAINT +PK_o-ran-smo-teiv-ran_AntennaCapability_id PK_o-ran-smo-teiv-ran_AntennaCapability_id CONSTRAINT +PK_o-ran-smo-teiv-ran_ENodeBFunction_id PK_o-ran-smo-teiv-ran_ENodeBFunction_id CONSTRAINT +PK_o-ran-smo-teiv-ran_EUtranCell_id PK_o-ran-smo-teiv-ran_EUtranCell_id CONSTRAINT +PK_o-ran-smo-teiv-ran_GNBCUCPFunction_id PK_o-ran-smo-teiv-ran_GNBCUCPFunction_id CONSTRAINT +PK_o-ran-smo-teiv-ran_GNBCUUPFunction_id PK_o-ran-smo-teiv-ran_GNBCUUPFunction_id CONSTRAINT +PK_o-ran-smo-teiv-ran_GNBDUFunction_id PK_o-ran-smo-teiv-ran_GNBDUFunction_id CONSTRAINT +PK_o-ran-smo-teiv-ran_LTESectorCarrier_id PK_o-ran-smo-teiv-ran_LTESectorCarrier_id CONSTRAINT +PK_o-ran-smo-teiv-ran_NRCellCU_id PK_o-ran-smo-teiv-ran_NRCellCU_id CONSTRAINT +PK_o-ran-smo-teiv-ran_NRCellDU_id PK_o-ran-smo-teiv-ran_NRCellDU_id CONSTRAINT +PK_o-ran-smo-teiv-ran_NRSectorCarrier_id PK_o-ran-smo-teiv-ran_NRSectorCarrier_id CONSTRAINT +PK_o-ran-smo-teiv-ran_Sector_id PK_o-ran-smo-teiv-ran_Sector_id CONSTRAINT +PK_o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY_id PK_63E61CB6802F21FE7A04A80A095F6AF8ABF067CE CONSTRAINT +REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU COLUMN +REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_CD_decorators_SECTOR_GROUPS_NRCELLDU REL_CD_decorators_SECTOR_GROUPS_NRCELLDU COLUMN +REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU COLUMN +REL_FK_grouped-by-sector REL_FK_grouped-by-sector COLUMN +REL_FK_installed-at-site REL_FK_installed-at-site COLUMN +REL_FK_managed-by-managedElement REL_FK_managed-by-managedElement COLUMN +REL_FK_provided-by-enodebFunction REL_FK_provided-by-enodebFunction COLUMN +REL_FK_provided-by-gnbcucpFunction REL_FK_provided-by-gnbcucpFunction COLUMN +REL_FK_provided-by-gnbduFunction REL_FK_provided-by-gnbduFunction COLUMN +REL_FK_used-antennaCapability REL_FK_used-antennaCapability COLUMN +REL_FK_used-by-euTranCell REL_FK_used-by-euTranCell COLUMN +REL_FK_used-by-nrCellDu REL_FK_used-by-nrCellDu COLUMN +REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_ID_EUTRANCELL_USES_LTESECTORCARRIER REL_ID_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_ID_NRCELLDU_USES_NRSECTORCARRIER REL_ID_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_ID_SECTOR_GROUPS_ANTENNAMODULE REL_ID_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_ID_SECTOR_GROUPS_EUTRANCELL REL_ID_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_ID_SECTOR_GROUPS_NRCELLDU REL_ID_SECTOR_GROUPS_NRCELLDU COLUMN +UNIQUE_o-ran-smo-teiv-equipment_AntennaModule_REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE UNIQUE_9DF414C2F0CD7FA8BFCB3E9BF851784AC4BC49B1 CONSTRAINT +UNIQUE_o-ran-smo-teiv-equipment_AntennaModule_REL_ID_SECTOR_GROUPS_ANTENNAMODULE UNIQUE_78B1D3DCD903AFFB1965D440D87B2D194CA028A0 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_ENodeBFunction_REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION UNIQUE_A30444B7D036FA579730F0D2853E52FD08DEDCF0 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_EUtranCell_REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL UNIQUE_CA88C7E60C1A332FA7561FC965ED41DD4125CDED CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_EUtranCell_REL_ID_SECTOR_GROUPS_EUTRANCELL UNIQUE_0513FE4A675A02C31E5EDD6BCB3728911FBDA2FA CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_GNBCUCPFunction_REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION UNIQUE_50E9E4A87D93AC833B1D1AC05E3B58805909E20E CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_GNBCUUPFunction_REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION UNIQUE_0CA05800AC7D277BDCB5CF0097DC35978E9311F4 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_GNBDUFunction_REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION UNIQUE_5BD09ED226520A0BE27904AEAF0557416808E7E2 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_LTESectorCarrier_REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER UNIQUE_FD943EE596337B11E0C640E1176CADF9CD69E19A CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_LTESectorCarrier_REL_ID_EUTRANCELL_USES_LTESECTORCARRIER UNIQUE_0A76398FBBC8E01A2D3BA602AB47835794E997E5 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_LTESectorCarrier_REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY UNIQUE_EA18F1D278EAFE834B8A80BCF8A7D8355CD013DF CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRCellCU_REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU UNIQUE_EA2A6F5BA36ABB0DA357542E05AA2D07415E127A CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRCellDU_REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU UNIQUE_C3D8E5331EC71D46D4B8CED29FE5F6CEB1D8E67A CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRCellDU_REL_ID_SECTOR_GROUPS_NRCELLDU UNIQUE_AC1C114ABED77D6DEC3F3AE3F9EBE8231924AEF4 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRSectorCarrier_REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER UNIQUE_0AC16A840F6ACDC50136E71EC6D4F3D4E04B8198 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRSectorCarrier_REL_ID_NRCELLDU_USES_NRSECTORCARRIER UNIQUE_1AB577E5AC207ED4C99A9A96BA1C9C35544AFD25 CONSTRAINT +UNIQUE_o-ran-smo-teiv-ran_NRSectorCarrier_REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY UNIQUE_A799EC9DA6624651081E1DA21B5F0C2D38F6A192 CONSTRAINT +aSide_AntennaModule aSide_AntennaModule COLUMN +antennaBeamWidth antennaBeamWidth COLUMN +antennaModelNumber antennaModelNumber COLUMN +arfcnDL arfcnDL COLUMN +arfcnUL arfcnUL COLUMN +azimuth azimuth COLUMN +bSChannelBwDL bSChannelBwDL COLUMN +bSide_AntennaCapability bSide_AntennaCapability COLUMN +cellId cellId COLUMN +cellLocalId cellLocalId COLUMN +channelBandwidth channelBandwidth COLUMN +dUpLMNId dUpLMNId COLUMN +dlChannelBandwidth dlChannelBandwidth COLUMN +duplexType duplexType COLUMN +eNBId eNBId COLUMN +eNodeBPlmnId eNodeBPlmnId COLUMN +eUtranFqBands eUtranFqBands COLUMN +earfcn earfcn COLUMN +earfcndl earfcndl COLUMN +earfcnul earfcnul COLUMN +electricalAntennaTilt electricalAntennaTilt COLUMN +frequencyDL frequencyDL COLUMN +frequencyUL frequencyUL COLUMN +gNBCUName gNBCUName COLUMN +gNBDUId gNBDUId COLUMN +gNBId gNBId COLUMN +gNBIdLength gNBIdLength COLUMN +geo-location geo-location COLUMN +geranFqBands geranFqBands COLUMN +id id COLUMN +mechanicalAntennaBearing mechanicalAntennaBearing COLUMN +mechanicalAntennaTilt mechanicalAntennaTilt COLUMN +nCI nCI COLUMN +nRFqBands nRFqBands COLUMN +nRPCI nRPCI COLUMN +nRTAC nRTAC COLUMN +name name COLUMN +o-ran-smo-teiv-equipment_AntennaModule o-ran-smo-teiv-equipment_AntennaModule TABLE +o-ran-smo-teiv-equipment_Site o-ran-smo-teiv-equipment_Site TABLE +o-ran-smo-teiv-oam_ManagedElement o-ran-smo-teiv-oam_ManagedElement TABLE +o-ran-smo-teiv-ran_AntennaCapability o-ran-smo-teiv-ran_AntennaCapability TABLE +o-ran-smo-teiv-ran_ENodeBFunction o-ran-smo-teiv-ran_ENodeBFunction TABLE +o-ran-smo-teiv-ran_EUtranCell o-ran-smo-teiv-ran_EUtranCell TABLE +o-ran-smo-teiv-ran_GNBCUCPFunction o-ran-smo-teiv-ran_GNBCUCPFunction TABLE +o-ran-smo-teiv-ran_GNBCUUPFunction o-ran-smo-teiv-ran_GNBCUUPFunction TABLE +o-ran-smo-teiv-ran_GNBDUFunction o-ran-smo-teiv-ran_GNBDUFunction TABLE +o-ran-smo-teiv-ran_LTESectorCarrier o-ran-smo-teiv-ran_LTESectorCarrier TABLE +o-ran-smo-teiv-ran_NRCellCU o-ran-smo-teiv-ran_NRCellCU TABLE +o-ran-smo-teiv-ran_NRCellDU o-ran-smo-teiv-ran_NRCellDU TABLE +o-ran-smo-teiv-ran_NRSectorCarrier o-ran-smo-teiv-ran_NRSectorCarrier TABLE +o-ran-smo-teiv-ran_Sector o-ran-smo-teiv-ran_Sector TABLE +o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY CFC235E0404703D1E4454647DF8AAE2C193DB402 TABLE +pLMNId pLMNId COLUMN +plmnId plmnId COLUMN +positionWithinSector positionWithinSector COLUMN +sectorCarrierType sectorCarrierType COLUMN +sectorId sectorId COLUMN +tac tac COLUMN +totalTilt totalTilt COLUMN +\. + +COPY ties_model.module_reference("name", "namespace", "domain", "includedModules", "revision", "content") FROM stdin; +_3gpp-common-yang-extensions urn:3gpp:sa5:_3gpp-common-yang-extensions \N [] 2019-06-23 bW9kdWxlIF8zZ3BwLWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgewogIHlhbmctdmVyc2lvbiAxLjE7CiAgbmFtZXNwYWNlIHVybjozZ3BwOnNhNTpfM2dwcC1jb21tb24teWFuZy1leHRlbnNpb25zIDsKICBwcmVmaXggeWV4dDNncHAgOwoKICBvcmdhbml6YXRpb24gIjNHUFAgU0E1IjsKICBkZXNjcmlwdGlvbiAiVGhlIG1vZHVsZSBkZWZpbmVzIFlBTkcgZXh0ZW5zaW9ucyBuZWVkZWQKICAgIDNHUFAgWUFORyBtb2RlbGluZy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTkgM0dQUC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBFeHRlbnNpb25zIE1VU1QgYmUgZGVmaW5lZCB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGluIHRoZQogICAgZGVzY3JpcHRpb24gc3RhdGVtZW50OgogICAgICAgIC0gV2hhdCBpcyB0aGlzIHN0YXRlbWVudC4KICAgICAgICAtIE5ld2xpbmUsCiAgICAgICAgLSBUaGlzIHN0YXRlbWVudCBjYW4gYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlIHh4eCBzdGF0ZW1lbnRzIHdpdGgKICAgICAgICBjYXJkaW5hbGl0eSB4Li55LgogICAgICAgIC0gVGhpcyBzdGF0ZW1lbnQgY2FuIGhhdmUgdGhlIGZvbGxvd2luZyBzdWJzdGF0ZW1lbnRzIHdpdGgKICAgICAgICBjYXJkaW5hbGl0eSB4Li55LgogICAgICAgIC0gTmV3bGluZQogICAgICAgIC0gSXMgY2hhbmdpbmcgdGhpcyBzdGF0ZW1lbnQgYW4gZWRpdG9yaWFsLCBCQyhiYWNrd2FyZHMgY29tcGF0aWJsZSkKICAgICAgICBvciBOQkMobm9uLUJDKSBjaGFuZ2U/CiAgICAgICAgLSBOZXdsaW5lLgogICAgICAgIC0gVGhlIGFyZ3VtZW50IGl0cyBtZWFuaW5nIGFuZCB0eXBlLiBQcmVmZXJhYmx5IHVzZSBZQU5HIHR5cGVzIGFuZAogICAgICAgICAgY29uc3RyYWludHMgdG8gZGVmaW5lIHRoZSBhcmd1bWVudCdzIHR5cGUuCgogICAgQW55IGV4dGVuc2lvbiBzdGF0ZW1lbnQgY2FuIGJlIGFkZGVkIHdpdGggYQogICAgZGV2aWF0aW9uL2RldmlhdGUgYWRkIHN0YXRlbWVudC4gSW4gdGhpcyBjYXNlIHRoZSByZXN0cmljdGlvbiBhYm91dAogICAgdGhlIHBhcmVudCBzdGF0ZW1lbnQgb2YgdGhlIGV4dGVuc2lvbiBTSEFMTCBiZSBldmFsdWF0ZWQgYmFzZWQgb24gdGhlCiAgICB0YXJnZXQgb2YgdGhlIGRldmlhdGlvbiBzdGF0ZW1lbnQuCgogICAgU3VwcG9ydCBmb3IgdGhpcyBtb2R1bGUgZG9lcyBub3QgbWVhbiB0aGF0IGEgWUFORyBzZXJ2ZXIgaW1wbGVtZW50cwogICAgc3VwcG9ydCBmb3IgZWFjaCBvZiB0aGVzZSBleHRlbnNpb25zLgogICAgSW1wbGVtZW50ZXJzIG9mIGVhY2ggc3BlY2lmaWMgbW9kdWxlIHVzaW5nIGFuIGV4dGVuc2lvbnMgTVVTVCBjaGVjawogICAgaWYgdGhlIHNlcnZlciBpbXBsZW1lbnRzIHN1cHBvcnQgZm9yIHRoZSB1c2VkIGV4dGVuc2lvbi4KICAgIE5vdGU6IG1vZHVsZXMgdXNlIG1hbnkgZXh0ZW5zaW9ucyB3aGljaCBpbmRpdmlkdWFsCiAgICBpbXBsZW1lbnRhdGlvbnMgTUFZIG9yIE1BWSBOT1Qgc3VwcG9ydC4KICAgIElmIHN1cHBvcnQgZm9yIGFuIGV4dGVuc2lvbiBpcyBtaXNzaW5nIHRoZSBleHRlbnNpb24gc3RhdGVtZW50IG5lZWRzCiAgICBpbmRpdmlkdWFsIGhhbmRsaW5nIG9yIGl0IFNIT1VMRCBiZSByZW1vdmVkIGZyb20gdGhlIG1vZHVsZSB1c2luZwogICAgdGhlIGV4dGVuc2lvbiBlLmcuIHdpdGggYSBkZXZpYXRpb24uCiAgICAgICAgICAiOwoKICByZXZpc2lvbiAiMjAxOS0wNi0yMyIgewogICAgZGVzY3JpcHRpb24gIkluaXRpYWwgdmVyc2lvbiI7CiAgfQoKICBleHRlbnNpb24gaW5WYXJpYW50IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgICJJbmRpY2F0ZXMgdGhhdCB0aGUgdmFsdWUgZm9yIHRoZSBkYXRhIG5vZGUgY2FuIG9ubHkgYmUgc2V0IHdoZW4gaXRzCiAgICAgIHBhcmVudCBkYXRhIG5vZGUgaXMgYmVpbmcgY3JlYXRlZC4gVG8gY2hhbmdlIHRoZSB2YWx1ZSBhZnRlciB0aGF0LCB0aGUKICAgICAgcGFyZW50IGRhdGEgbm9kZSBtdXN0IGJlIGRlbGV0ZWQgYW5kIHJlY3JlYXRlZCB3aXRoIHRoZSBkYXRhIG5vZGUKICAgICAgaGF2aW5nIHRoZSBuZXcgdmFsdWUuCgogICAgICBJdCBpcyB1bm5lY2Vzc2FyeSB0byB1c2UgYW5kIE1VU1QgTk9UIGJlIHVzZWQgZm9yIGtleSBsZWFmcy4KCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgbGVhZiwgbGVhZi1saXN0LCBsaXN0CiAgICAgIHN0YXRlbWVudHMgdGhhdCBpcyBjb25maWc9dHJ1ZS4KICAgICAgWmVybyBvciBvbmUgaW5WYXJpYW50IHN0YXRlbWVudCBpcyBhbGxvd2VkIHBlciBwYXJlbnQgc3RhdGVtZW50LgogICAgICBOTyBzdWJzdGF0ZW1lbnRzIGFyZSBhbGxvd2VkLgoKICAgICAgQWRkaW5nIHRoaXMgc3RhdGVtZW50IGlzIGFuIE5CQyBjaGFuZ2UsIHJlbW92aW5nIGl0IGlzIEJDLiI7CiAgfQoKICBleHRlbnNpb24gaW5pdGlhbC12YWx1ZSB7CiAgICBkZXNjcmlwdGlvbiAiU3BlY2lmaWVzIGEgdmFsdWUgdGhhdCB0aGUgc3lzdGVtIHdpbGwgc2V0IGZvciBhIGxlYWYKICAgICAgbGVhZi1saXN0IGlmIGEgdmFsdWUgaXMgbm90IHNwZWNpZmllZCBmb3IgaXQgd2hlbiBpdHMgcGFyZW50IGxpc3QKICAgICAgb3IgY29udGFpbmVyIGlzIGNyZWF0ZWQuIFRoZSB2YWx1ZSBoYXMgbm8gZWZmZWN0IGluIGFueSBvdGhlcgogICAgICBtb2RpZmljYXRpb24gZS5nLiBjaGFuZ2luZyBvciByZW1vdmluZyB0aGUgdmFsdWUuCgogICAgICBUaGUgZGVzY3JpcHRpb24gc3RhdGVtZW50IG9mIHRoZSBwYXJlbnQgc3RhdGVtZW50IFNIT1VMRCBjb250YWluCiAgICAgIHRoZSBsYWJlbCAnSW5pdGlhbC12YWx1ZTogJyBmb2xsb3dlZCBieSB0aGUgdGV4dCBmcm9tIHRoZSBhcmd1bWVudC4KCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgbGVhZiBvciBsZWFmLWxpc3QuCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBOT1QgYmUgcHJlc2VudCBpZiB0aGUgbGVhZiBvciB0aGUgbGVhZi1saXN0CiAgICAgIGhhcyBhIGRlZmF1bHQgc3RhdGVtZW50IG9yIHRoZSB0eXBlIHVzZWQgZm9yIHRoZSBkYXRhIG5vZGUKICAgICAgaGFzIGEgZGVmYXVsdCB2YWx1ZS4KICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIE5PVCBiZSB1c2VkIGZvciBjb25maWc9ZmFsc2UgZGF0YSBvciBpbiBhbgogICAgICBhY3Rpb24sIHJwYyBvciBub3RpZmljYXRpb24uCiAgICAgIFplcm8gb3Igb25lIGluaXRpYWwtdmFsdWUgc3RhdGVtZW50cyBhcmUgYWxsb3dlZCBmb3IgYSBsZWFmIHBhcmVudAogICAgICBzdGF0ZW1lbnQuIFplcm8gb3IgbW9yZSBpbml0aWFsLXZhbHVlIHN0YXRlbWVudHMgYXJlIGFsbG93ZWQgZm9yIGEKICAgICAgbGVhZi1saXN0IHBhcmVudCBzdGF0ZW1lbnQuIElmIHRoZSBsZWFmLWxpc3QgaXMgb3JkZXJlZC1ieSB1c2VyLCB0aGUKICAgICAgaW5pdGlhbCB2YWx1ZXMgYXJlIHN0b3JlZCBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW4gdGhlIFlBTkcgZGVmaW5pdGlvbi4KICAgICAgTk8gc3Vic3RhdGVtZW50cyBhcmUgYWxsb3dlZC4KCiAgICAgIEFsd2F5cyBjb25zaWRlciB1c2luZyBhIFlBTkctZGVmYXVsdCBzdGF0ZW1lbnQgaW5zdGVhZC4KCiAgICAgIE1vZGlmaWNhdGlvbiBvZiB0aGUgaW5pdGlhbC12YWx1ZSBpcyBhIG5vbi1iYWNrd2FyZHMtY29tcGF0aWJsZSBjaGFuZ2UuCgogICAgICBUaGUgYXJndW1lbnQgc3BlY2lmaWVzIGEgc2luZ2xlIGluaXRpYWwgdmFsdWUgZm9yIGEgbGVhZiBvciBsZWFmLWxpc3QuCiAgICAgIFRoZSB2YWx1ZSBNVVNUIGJlIHBhcnQgb2YgdGhlIHZhbHVlc3BhY2Ugb2YgdGhlIGxlYWYvbGVhZi1saXN0LgogICAgICBJdCBmb2xsb3dzIHRoZSBzYW1lIHJ1bGVzIGFzIHRoZSBhcmd1bWVudCBvZiB0aGUgZGVmYXVsdCBzdGF0ZW1lbnQuIjsKCiAgICBhcmd1bWVudCAiaW5pdGlhbC12YWx1ZSI7CiAgfQp9Cg== +_3gpp-common-yang-types urn:3gpp:sa5:_3gpp-common-yang-types \N [] 2023-11-06 bW9kdWxlIF8zZ3BwLWNvbW1vbi15YW5nLXR5cGVzIHsKICB5YW5nLXZlcnNpb24gMS4xOwogIG5hbWVzcGFjZSAidXJuOjNncHA6c2E1Ol8zZ3BwLWNvbW1vbi15YW5nLXR5cGVzIjsKICBwcmVmaXggInR5cGVzM2dwcCI7CgogIGltcG9ydCBpZXRmLWluZXQtdHlwZXMgeyBwcmVmaXggaW5ldDsgfQogIGltcG9ydCBpZXRmLXlhbmctdHlwZXMgeyBwcmVmaXggeWFuZzsgfQogIGltcG9ydCBfM2dwcC1jb21tb24teWFuZy1leHRlbnNpb25zIHsgcHJlZml4IHlleHQzZ3BwOyB9CgogIG9yZ2FuaXphdGlvbiAiM0dQUCBTQTUiOwogIGNvbnRhY3QgImh0dHBzOi8vd3d3LjNncHAub3JnL0R5bmFSZXBvcnQvVFNHLVdHLS1TNS0tb2ZmaWNpYWxzLmh0bT9JdGVtaWQ9NDY0IjsKICBkZXNjcmlwdGlvbiAiVGhlIG1vZGVsIGRlZmluZXMgYSBZQU5HIG1hcHBpbmcgb2YgdGhlIHRvcCBsZXZlbAogICAgaW5mb3JtYXRpb24gY2xhc3NlcyB1c2VkIGZvciBtYW5hZ2VtZW50IG9mIDVHIG5ldHdvcmtzIGFuZAogICAgbmV0d29yayBzbGljaW5nLgogICAgQ29weXJpZ2h0IDIwMjMsIDNHUFAgT3JnYW5pemF0aW9uYWwgUGFydG5lcnMgKEFSSUIsIEFUSVMsIENDU0EsIEVUU0ksIFRTRFNJLAogICAgVFRBLCBUVEMpLiBBbGwgcmlnaHRzIHJlc2VydmVkLiI7CiAgcmVmZXJlbmNlICIzR1BQIFRTIDI4LjYyMyI7CgogIHJldmlzaW9uIDIwMjMtMTEtMDYgeyByZWZlcmVuY2UgQ1ItMDMwNTsgfQogIHJldmlzaW9uIDIwMjMtMDktMTggeyByZWZlcmVuY2UgQ1ItMDI3MSA7IH0KICByZXZpc2lvbiAyMDIzLTA4LTA5IHsgcmVmZXJlbmNlIENSLTAyNjY7IH0KICByZXZpc2lvbiAyMDIzLTA1LTEwIHsgcmVmZXJlbmNlIENSLTAyNTA7IH0KICByZXZpc2lvbiAyMDIzLTAyLTE0IHsgcmVmZXJlbmNlIENSLTAyMzQ7IH0KICByZXZpc2lvbiAyMDIyLTExLTA0IHsgcmVmZXJlbmNlICJDUi0wMTk0IjsgfQogIHJldmlzaW9uIDIwMjItMTAtMjQgeyByZWZlcmVuY2UgQ1ItMDE5NjsgIH0KICByZXZpc2lvbiAyMDIyLTA3LTI2IHsgcmVmZXJlbmNlICJDUi0wMTgwIiA7IH0KICByZXZpc2lvbiAyMDIyLTAyLTA5IHsgcmVmZXJlbmNlICJDUi0wMTQ0IjsgfQogIHJldmlzaW9uIDIwMjEtMTEtMDEgeyByZWZlcmVuY2UgIkNSLTAxNDEiOyB9CgogIHJldmlzaW9uIDIwMjEtMDktMzAgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIExvbmdpdHVkZSwgTGF0aXR1ZGUsIFRlbnRoT2ZEZWdyZWVzLCBPbk9mZi4iOwogICAgcmVmZXJlbmNlICJDUi0wMTM4IjsKICB9CgogIHJldmlzaW9uIDIwMjAtMTEtMDYgewogICAgZGVzY3JpcHRpb24gIlJlbW92ZWQgaW5jb3JyZWN0IFMtTlNTQUkgZGVmaW5pdGlvbnMuIjsKICAgIHJlZmVyZW5jZSAiQ1ItMDExOCI7CiAgfQoKICByZXZpc2lvbiAyMDIwLTAzLTEwIHsKICAgIGRlc2NyaXB0aW9uICJSZW1vdmVkIGZhdWx0eSB3aGVuIHN0YXRlbWVudHMuIjsKICAgIHJlZmVyZW5jZSAiU1AtMjAwMjI5IjsKICB9CgogIHJldmlzaW9uIDIwMTktMTAtMjUgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIE1hbmFnZWRORlByb2ZpbGUuIjsKICAgIHJlZmVyZW5jZSAiUzUtMTk0NDU3IjsKICB9CgogIHJldmlzaW9uIDIwMTktMTAtMTYgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIFNBUCBhbmQgdXNhZ2VTdGF0ZS4iOwogICAgcmVmZXJlbmNlICJTNS0xOTM1MTgiOwogIH0KCiAgcmV2aXNpb24gMjAxOS0wNi0yMyB7CiAgICByZWZlcmVuY2UgICJJbml0aWFsIHZlcnNpb24uIjsKICB9CgogIHR5cGVkZWYgRW5hYmxlZERpc2FibGVkIHsKICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICBlbnVtIERJU0FCTEVEIDsKICAgICAgZW51bSBFTkFCTEVEIDsKICAgIH0KICB9CgogIGdyb3VwaW5nIG5hbWVWYWx1ZVBhaXIgewogICAgbGVhZiBuYW1lIHsgdHlwZSBzdHJpbmc7IH0KICAgIGxlYWYgdmFsdWUgeyB0eXBlIHN0cmluZzsgfQogIH0KCiAgZ3JvdXBpbmcgUHJvY2Vzc01vbml0b3JHcnAgewogICAgZGVzY3JpcHRpb24gIlByb3ZpZGVzIGF0dHJpYnV0ZXMgdG8gbW9uaXRvciB0aGUgcHJvZ3Jlc3Mgb2YgcHJvY2Vzc2VzCiAgICAgIHdpdGggc3BlY2lmaWMgcHVycG9zZSBhbmQgbGltaXRlZCBsaWZldGltZSBydW5uaW5nIG9uIE1uUyBwcm9kdWNlcnMuCiAgICAgIEl0IG1heSBiZSB1c2VkIGFzIGRhdGEgdHlwZSBmb3IgZGVkaWNhdGVkIHByb2dyZXNzIG1vbml0b3IgYXR0cmlidXRlcwogICAgICB3aGVuIHNwZWNpZnlpbmcgdGhlIG1hbmFnZW1lbnQgcmVwcmVzZW50YXRpb24gb2YgdGhlc2UgcHJvY2Vzc2VzLgogICAgICBUaGUgYXR0cmlidXRlcyBpbiB0aGlzIGNsYXVzZSBhcmUgZGVmaW5lZCBpbiBhIGdlbmVyaWMgd2F5LgogICAgICBGb3Igc29tZSBhdHRyaWJ1dGVzIHNwZWNpYWxpc2F0aW9ucyBtYXkgYmUgcHJvdmlkZWQgd2hlbiBzcGVjaWZ5aW5nIGEKICAgICAgY29uY3JldGUgcHJvY2VzcyByZXByZXNlbnRhdGlvbi4KCiAgICAgIElmIGEgbWFuYWdlbWVudCBvcGVyYXRpb24gb24gc29tZSBJT0NzIHRyaWdnZXJzIGFuIGFzc29jaWF0ZWQKICAgICAgYXN5bmNocm9ub3VzIHByb2Nlc3MgKHdob3NlIHByb2dyZXNzIHNoYWxsIGJlIG1vbml0b3JlZCksIHRoaXMgc2hvdWxkCiAgICAgIGFsc28gcmVzdWx0IGluIGNyZWF0aW5nIGFuIGF0dHJpYnV0ZSBuYW1lZCAncHJvY2Vzc01vbml0b3InIChvZiB0eXBlCiAgICAgICdQcm9jZXNzTW9uaXRvcicpIGluIHRoZXNlIElPQyhzKS4gVGhlIHByb2Nlc3NNb25pdG9yIGF0dHJpYnV0ZSBtYXkgYmUKICAgICAgYWNjb21wYW5pZWQgYnkgdXNlLWNhc2Ugc3BlY2lmaWMgYWRkaXRpb25hbCBkYXRhIGl0ZW1zLgoKICAgICAgVGhlIHByb2dyZXNzIG9mIHRoZSBwcm9jZXNzIGlzIGRlc2NyaWJlZCBieSB0aGUgJ3N0YXR1cycgYW5kCiAgICAgICdwcm9ncmVzc1BlcmNlbnRhZ2UnIGF0dHJpYnV0ZXMuIEFkZGl0aW9uYWwgdGV4dHVhbCBxdWFsaWZpY2F0aW9ucyBmb3IKICAgICAgdGhlICdzdGF0dXMnIGF0dHJpYnV0ZSBtYXkgYmUgcHJvdmlkZWQgYnkgdGhlICdwcm9ncmVzc1N0YXRlSW5mbycgYW5kCiAgICAgICdyZXN1bHRTdGF0ZUluZm8nIGF0dHJpYnV0ZXMuCgogICAgICBXaGVuIHRoZSBwcm9jZXNzIGlzIGluc3RhbnRpYXRlZCwgdGhlICdzdGF0dXMnIGlzIHNldCB0byAnTk9UX1JVTk5JTkcnCiAgICAgIGFuZCB0aGUgJ3Byb2dyZXNzUGVyY2VudGFnZScgdG8gJzAnLiBUaGUgTW5TIHByb2R1Y2VyIGRlY2lkZXMgd2hlbiB0bwogICAgICBzdGFydCBleGVjdXRpbmcgdGhlIHByb2Nlc3MgYW5kIHRvIHRyYW5zaXRpb24gaW50byB0aGUgJ1JVTk5JTkcnIHN0YXRlLgogICAgICBUaGlzIHRpbWUgaXMgY2FwdHVyZWQgaW4gdGhlICdzdGFydFRpbWUnIGF0dHJpYnV0ZS4gQWx0ZXJuYXRpdmVseSwgdGhlCiAgICAgIHByb2Nlc3MgbWF5IHN0YXJ0IHRvIGV4ZWN1dGUgZGlyZWN0bHkgdXBvbiBpdHMgaW5zdGFudGlhdGlvbi4gT25lCiAgICAgIGFsdGVybmF0aXZlIG11c3QgYmUgc2VsZWN0ZWQgd2hlbiB1c2luZyB0aGlzIGRhdGEgdHlwZS4KCiAgICAgIER1cmluZyB0aGUgJ1JVTk5JTkcnIHN0YXRlIHRoZSAncHJvZ3Jlc3NQZXJjZW50YWdlJyBhdHRyaWJ1dGUgbWF5IGJlCiAgICAgIHJlcGVhdGVkbHkgdXBkYXRlZC4gVGhlIGV4YWN0IHNlbWFudGljIG9mIHRoaXMgYXR0cmlidXRlIGlzIHN1YmplY3QgdG8KICAgICAgZnVydGhlciBzcGVjaWFsaXNhdGlvbi4gVGhlICdwcm9ncmVzc0luZm8nIGF0dHJpYnV0ZSBtYXkgYmUgdXNlZCB0bwogICAgICBwcm92aWRlIGFkZGl0aW9uYWwgdGV4dHVhbCBpbmZvcm1hdGlvbiBpbiB0aGUgJ05PVF9SVU5OSU5HJywgJ0NBTkNFTExJTkcnCiAgICAgIGFuZCAnUlVOTklORycgc3RhdGVzLiBGdXJ0aGVyIHNwZWNpYWxpc2F0aW9uIG9mCiAgICAgICdwcm9ncmVzc1N0YXRlSW5mbycgbWF5IGJlIHByb3ZpZGVkIHdoZXJlIHRoaXMgZGF0YSB0eXBlIGlzCiAgICAgIHVzZWQuCgogICAgICBVcG9uIHN1Y2Nlc3NmdWwgY29tcGxldGlvbiBvZiB0aGUgcHJvY2VzcywgdGhlICdzdGF0dXMnIGF0dHJpYnV0ZSBpcyBzZXQKICAgICAgdG8gJ0ZJTklTSEVEJywgdGhlICdwcm9ncmVzc1BlcmNlbnRhZ2UnIHRvIDEwMCUuIFRoZSB0aW1lIGlzIGNhcHR1cmVkIGluCiAgICAgIHRoZSAnZW5kVGltZScgYXR0cmlidXRlLiBBZGRpdGlvbmFsIHRleHR1YWwgaW5mb3JtYXRpb24gbWF5IGJlIHByb3ZpZGVkCiAgICAgIGluIHRoZSAncmVzdWx0U3RhdGVJbmZvJyBhdHRyaWJ1dGUuIFRoZSB0eXBlIG9mCiAgICAgICdyZXN1bHRTdGF0ZUluZm8nIGluIHRoaXMgZGF0YSB0eXBlIGRlZmluaXRpb24gaXMgJ1N0cmluZycuCiAgICAgIEZ1cnRoZXIgc3BlY2lhbGlzYXRpb24gb2YgJ3Jlc3VsdFN0YXRlSW5mbycgbWF5IGJlIHByb3ZpZGVkCiAgICAgIHdoZXJlIHRoaXMgZGF0YSB0eXBlIGlzIHVzZWQuCgogICAgICBJbiBjYXNlIHRoZSBwcm9jZXNzIGZhaWxzIHRvIGNvbXBsZXRlIHN1Y2Nlc3NmdWxseSwgdGhlICdzdGF0dXMnCiAgICAgIGF0dHJpYnV0ZSBpcyBzZXQgdG8gJ0ZBSUxFRCcgb3IgJ1BBUlRJQUxMWV9GQUlMRUQnLCB0aGUgY3VycmVudCB2YWx1ZSBvZgogICAgICAncHJvZ3Jlc3NQZXJjZW50YWdlJyBpcyBmcm96ZW4sIGFuZCB0aGUgdGltZSBjYXB0dXJlZCBpbiAnZW5kVGltZScuIFRoZQogICAgICAncmVzdWx0U3RhdGVJbmZvJyBzcGVjaWZpZXMgdGhlIHJlYXNvbiBmb3IgdGhlIGZhaWx1cmUuCiAgICAgIFNwZWNpZmljIGZhaWx1cmUgcmVhc29ucyBtYXkgYmUgc3BlY2lmaWVkIHdoZXJlIHRoZSBkYXRhIHR5cGUgZGVmaW5lZCBpbgogICAgICB0aGlzIGNsYXVzZSBpcyB1c2VkLiBUaGUgZXhhY3Qgc2VtYW50aWMgb2YgZmFpbHVyZSBtYXkgYmUgc3ViamVjdCBmb3IKICAgICAgZnVydGhlciBzcGVjaWFsaXNhdGlvbiBhcyB3ZWxsLgoKICAgICAgSW4gY2FzZSB0aGUgcHJvY2VzcyBpcyBjYW5jZWxsZWQsIHRoZSAnc3RhdHVzJyBhdHRyaWJ1dGUgaXMgZmlyc3Qgc2V0IHRvCiAgICAgICdDQU5DRUxMSU5HJyBhbmQgd2hlbiB0aGUgcHJvY2VzcyBpcyByZWFsbHkgY2FuY2VsbGVkIHRoZW4gdG8gJ0NBTkNFTExFRCcuCiAgICAgIFRoZSB0cmFuc2l0aW9uIHRvICdDQU5DRUxMRUQnIGlzIGNhcHR1cmVkIGluIHRoZSAnZW5kVGltZScgYXR0cmlidXRlLgogICAgICBUaGUgdmFsdWUgb2YgJ3Byb2dyZXNzUGVyY2VudGFnZScgaXMgZnJvemVuLiBBZGRpdGlvbmFsIHRleHR1YWwKICAgICAgaW5mb3JtYXRpb24gbWF5IGJlIHByb3ZpZGVkIGluIHRoZSAncmVzdWx0U3RhdGVJbmZvJyBhdHRyaWJ1dGUuCgogICAgICBUaGUgJ3Jlc3VsdFN0YXRlSW5mbycgYXR0cmlidXRlIGlzIHByb3ZpZGVkIG9ubHkgZm9yIGFkZGl0aW9uYWwgdGV4dHVhbAogICAgICBxdWFsaWZpY2F0aW9uIG9mIHRoZSBzdGF0ZXMgJ0ZJTklTSEVEJywgJ0ZBSUxFRCcsICdQQVJUSUFMTFlfRkFJTEVEJyBvcgogICAgICAnQ0FOQ0VMTEVEJy4gSXQgc2hhbGwgbm90IGJlIHVzZWQgZm9yIG1ha2luZyB0aGUgb3V0Y29tZSwgdGhhdCB0aGUKICAgICAgcHJvY2VzcyBtYXkgcHJvZHVjZSBpbiBjYXNlIG9mIHN1Y2Nlc3MsIGF2YWlsYWJsZS4KCiAgICAgIFRoZSBwcm9jZXNzIG1heSBoYXZlIHRvIGJlIGNvbXBsZXRlZCB3aXRoaW4gYSBjZXJ0YWluIHRpbWUgYWZ0ZXIgaXRzCiAgICAgIGNyZWF0aW9uLCBmb3IgZXhhbXBsZSBiZWNhdXNlIHJlcXVpcmVkIGRhdGEgbWF5IG5vdCBiZSBhdmFpbGFibGUgYW55CiAgICAgIG1vcmUgYWZ0ZXIgYSBjZXJ0YWluIHRpbWUsIG9yIHRoZSBwcm9jZXNzIG91dGNvbWUgaXMgbmVlZGVkIHVudGlsIGEKICAgICAgY2VydGFpbiB0aW1lIGFuZCB3aGVuIG5vdCBwcm92aWRlZCBieSB0aGlzIHRpbWUgaXMgbm90IG5lZWRlZCBhbnkgbW9yZS4KICAgICAgVGhlIHRpbWUgdW50aWwgdGhlIE1uUyBwcm9kdWNlciBhdXRvbWF0aWNhbGx5IGNhbmNlbHMgdGhlIHByb2Nlc3MgaXMKICAgICAgaW5kaWNhdGVkIGJ5IHRoZSAndGltZXInIGF0dHJpYnV0ZS4iOwoKICAgIGxlYWYgaWQgewogICAgICB0eXBlIHN0cmluZzsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIGRlc2NyaXB0aW9uICJJZCBvZiB0aGUgcHJvY2Vzcy4gSXQgaXMgdW5pcXVlIHdpdGhpbiBhIHNpbmdsZQogICAgICAgIG11bHRpdmFsdWUgYXR0cmlidXRlIG9mIHR5cGUgUHJvY2Vzc01vbml0b3IuIjsKICAgIH0KCiAgICBsZWFmIHN0YXR1cyB7CiAgICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICAgIGVudW0gTk9UX1NUQVJURUQgOwogICAgICAgIGVudW0gUlVOTklORyA7CiAgICAgICAgZW51bSBDQU5DRUxMSU5HIDsKICAgICAgICBlbnVtIEZJTklTSEVEIDsKICAgICAgICBlbnVtIEZBSUxFRCA7CiAgICAgICAgZW51bSBQQVJUSUFMTFlfRkFJTEVEIDsKICAgICAgICBlbnVtIENBTkNFTExFRCA7CiAgICAgIH0KICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZWZhdWx0ICBSVU5OSU5HOwogICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyB0aGUgc3RhdHVzIG9mIHRoZSBhc3NvY2lhdGVkIHByb2Nlc3MsCiAgICAgICAgd2hldGhlciBpdCBmYWlscywgc3VjY2VlZHMgZXRjLgogICAgICAgIEl0IGRvZXMgbm90IHJlcHJlc2VudCB0aGUgcmV0dXJuZWQgdmFsdWVzIG9mIGEgc3VjY2Vzc2Z1bGx5IGZpbmlzaGVkCiAgICAgICAgcHJvY2Vzcy4gIjsKICAgIH0KCiAgICBsZWFmIHByb2dyZXNzUGVyY2VudGFnZSB7CiAgICAgIHR5cGUgdWludDggewogICAgICAgIHJhbmdlIDAuLjEwMDsKICAgICAgfQogICAgICBjb25maWcgZmFsc2U7CiAgICAgIGRlc2NyaXB0aW9uICJQcm9ncmVzcyBvZiB0aGUgYXNzb2NpYXRlZCBwcm9jZXNzIGFzIHBlcmNlbnRhZ2UiOwogICAgfQoKICAgIGxlYWYtbGlzdCBwcm9ncmVzc1N0YXRlSW5mbyB7CiAgICAgIHR5cGUgc3RyaW5nOwogICAgICBjb25maWcgZmFsc2U7CiAgICAgIGRlc2NyaXB0aW9uICJBZGRpdGlvbmFsIHRleHR1YWwgcXVhbGlmaWNhdGlvbiBvZiB0aGUgc3RhdGVzCiAgICAgICAgJ05PVF9TVEFSVEVEJywgJ0NBTkNFTExJTkcnIGFuZCAnUlVOTklORycuCgogICAgICAgIEZvciBzcGVjaWZpYyBwcm9jZXNzZXMsIHNwZWNpZmljIHdlbGwtZGVmaW5lZCBzdHJpbmdzIChlLmcuIHN0cmluZwogICAgICAgIHBhdHRlcm5zIG9yIGVudW1zKSBtYXkgYmUgZGVmaW5lZCBhcyBhIHNwZWNpYWxpc2F0aW9uLiI7CiAgICB9CgogICAgbGVhZiByZXN1bHRTdGF0ZUluZm8gewogICAgICB0eXBlIHN0cmluZzsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZXNjcmlwdGlvbiAiQWRkaXRpb25hbCB0ZXh0dWFsIHF1YWxpZmljYXRpb24gb2YgdGhlIHN0YXRlcwogICAgICAgICdGSU5JU0hFRCcsICdGQUlMRUQnLCAnUEFSVElBTExZX0ZBSUxFRCBhbmQgJ0NBTkNFTExFRCcuCiAgICAgICAgRm9yIGV4YW1wbGUsIGluIHRoZSAnRkFJTEVEJyBvciAnUEFSVElBTExZX0ZBSUxFRCcgc3RhdGUgdGhpcwogICAgICAgIGF0dHJpYnV0ZSBtYXkgYmUgdXNlZCB0byBwcm92aWRlIGVycm9yIHJlYXNvbnMuCgogICAgICAgIFRoaXMgYXR0cmlidXRlIHNoYWxsIG5vdCBiZSB1c2VkIHRvIG1ha2UgdGhlIG91dGNvbWUgb2YgdGhlIHByb2Nlc3MKICAgICAgICBhdmFpbGFibGUgZm9yIHJldHJpZXZhbCwgaWYgYW55LiBGb3IgdGhpcyBwdXJwb3NlLCBkZWRpY2F0ZWQKICAgICAgICBhdHRyaWJ1dGVzIHNoYWxsIGJlIHNwZWNpZmllZCB3aGVuIHNwZWNpZnlpbmcgdGhlIHJlcHJlc2VudGF0aW9uIG9mCiAgICAgICAgYSBzcGVjaWZpYyBwcm9jZXNzLgoKICAgICAgICBGb3Igc3BlY2lmaWMgcHJvY2Vzc2VzLCBzcGVjaWZpYyB3ZWxsLWRlZmluZWQgc3RyaW5ncyAoZS5nLiBzdHJpbmcKICAgICAgICBwYXR0ZXJucyBvciBlbnVtcykgbWF5IGJlIGRlZmluZWQgYXMgYSBzcGVjaWFsaXNhdGlvbi4iOwogICAgfQoKICAgIGxlYWYgc3RhcnRUaW1lIHsKICAgICAgdHlwZSB5YW5nOmRhdGUtYW5kLXRpbWU7CiAgICAgIGNvbmZpZyBmYWxzZTsKICAgICAgZGVzY3JpcHRpb24gIlN0YXJ0IHRpbWUgb2YgdGhlIGFzc29jaWF0ZWQgcHJvY2VzcywgaS5lLiB0aGUgdGltZSB3aGVuIHRoZQogICAgICAgIHN0YXR1cyBjaGFuZ2VkIGZyb20gJ05PVF9TVEFSVEVEJyB0byAnUlVOTklORycuIjsKICAgIH0KCiAgICBsZWFmIGVuZFRpbWUgewogICAgICB0eXBlIHlhbmc6ZGF0ZS1hbmQtdGltZTsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZXNjcmlwdGlvbiAiRGF0ZSBhbmQgdGltZSB3aGVuIHN0YXR1cyBjaGFuZ2VkIHRvICdTVUNDRVNTJywgJ0NBTkNFTExFRCcsCiAgICAgICAgJ0ZBSUxFRCcgb3IgJ1BBUlRJQUxMWV9GQUlMRUQnLgoKICAgICAgICBJZiB0aGUgdGltZSBpcyBpbiB0aGUgZnV0dXJlLCBpdCBpcyB0aGUgZXN0aW1hdGVkIHRpbWUKICAgICAgICB0aGUgcHJvY2VzcyB3aWxsIGVuZC4iOwogICAgfQoKICAgIGxlYWYgdGltZXIgewogICAgICB0eXBlIHVpbnQzMjsKICAgICAgdW5pdHMgbWludXRlczsKICAgICAgZGVzY3JpcHRpb24gIlRpbWUgdW50aWwgdGhlIGFzc29jaWF0ZWQgcHJvY2VzcyBpcyBhdXRvbWF0aWNhbGx5IGNhbmNlbGxlZC4KICAgICAgICBJZiBzZXQsIHRoZSBzeXN0ZW0gZGVjcmVhc2VzIHRoZSB0aW1lciB3aXRoIHRpbWUuIFdoZW4gaXQgcmVhY2hlcyB6ZXJvCiAgICAgICAgdGhlIGNhbmNlbGxhdGlvbiBvZiB0aGUgYXNzb2NpYXRlZCBwcm9jZXNzIGlzIGluaXRpYXRlZCBieSB0aGUKICAgICAgICBNblNfUHJvZHVjZXIuCiAgICAgICAgSWYgbm90IHNldCwgdGhlcmUgaXMgbm8gdGltZSBsaW1pdCBmb3IgdGhlIHByb2Nlc3MuCgogICAgICAgIE9uY2UgdGhlIHRpbWVyIGlzIHNldCwgdGhlIGNvbnN1bWVyIGNhbiBub3QgY2hhbmdlIGl0IGFueW1vcmUuCiAgICAgICAgSWYgdGhlIGNvbnN1bWVyIGhhcyBub3Qgc2V0IHRoZSB0aW1lciB0aGUgTW5TIFByb2R1Y2VyIG1heSBzZXQgaXQuIjsKICAgICAgeWV4dDNncHA6bm90Tm90aWZ5YWJsZTsKICAgIH0KICB9CgogIHR5cGVkZWYgVGVudGhPZkRlZ3JlZXMgewogICAgdHlwZSB1aW50MTYgewogICAgICByYW5nZSAwLi4zNjAwOwogICAgfQogICAgdW5pdHMgIjAuMSBkZWdyZWVzIjsKICAgIGRlc2NyaXB0aW9uICJBIHNpbmdsZSBpbnRlZ3JhbCB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIGFuIGFuZ2xlIGluIGRlZ3JlZXMKICAgICAgYmV0d2VlbiAwIGFuZCAzNjAgd2l0aCBhIHJlc29sdXRpb24gb2YgMC4xIGRlZ3JlZXMuIjsKICB9CgogIHR5cGVkZWYgTGF0aXR1ZGUgewogICAgdHlwZSBkZWNpbWFsNjQgewogICAgICBmcmFjdGlvbi1kaWdpdHMgNDsKICAgICAgcmFuZ2UgIi05MC4wMDAwLi4rOTAuMDAwMCI7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiTGF0aXR1ZGUgdmFsdWVzIjsKICB9CgogIHR5cGVkZWYgTG9uZ2l0dWRlIHsKICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgZnJhY3Rpb24tZGlnaXRzIDQ7CiAgICAgIHJhbmdlICItMTgwLjAwMDAuLisxODAuMDAwMCI7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiTG9uZ2l0dWRlIHZhbHVlcyI7CiAgfQoKICB0eXBlZGVmIEFsdGl0dWRlICB7CiAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgIGZyYWN0aW9uLWRpZ2l0cyA2OwogICAgfQogICAgdW5pdHMgIm1ldGVycyI7CiAgICBkZXNjcmlwdGlvbgogICAgICAiSGVpZ2h0IGZyb20gYSByZWZlcmVuY2UgMCB2YWx1ZS4iOwogIH0KCiAgZ3JvdXBpbmcgR2VvZ3JhcGhpY2FsQ29vcmRpbmF0ZXMgewogICAgZGVzY3JpcHRpb24gIlRoaXMgZGF0YXR5cGUgcmVwcmVzZW50cyB0aGUgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIjsKICAgIHJlZmVyZW5jZSAiI0dQUCBUUyAyOC41NTggY2xhdXNlIDYuMy44IjsKCiAgICBsZWFmIGxhdGl0dWRlIHsKICAgICAgdHlwZSBMYXRpdHVkZTsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CgogICAgbGVhZiBsb25naXR1ZGUgewogICAgICB0eXBlIExvbmdpdHVkZTsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CgogICAgbGVhZiBhbHRpdHVkZSB7CiAgICAgIHR5cGUgQWx0aXR1ZGU7CiAgICB9CgogIH0KCiAgdHlwZWRlZiBPbk9mZiB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBPTjsKICAgICAgZW51bSBPRkY7CiAgICB9CiAgfQoKICAvLyBncm91cGluZyBNYW5hZ2VkTkZQcm9maWxlIHdpbGwgYmUgcmVtb3ZlZCBhcyBpdCBpcwogIC8vICBiZWluZyBtb3ZlZCB0byBfM2dwcC01Z2MtbnJtLW5mcHJvZmlsZQogIGdyb3VwaW5nIE1hbmFnZWRORlByb2ZpbGUgewogICAgZGVzY3JpcHRpb24gIkRlZmluZXMgcHJvZmlsZSBmb3IgbWFuYWdlZCBORiI7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuNTAxIjsKCiAgICBsZWFmIGlkeCB7IHR5cGUgdWludDMyIDsgfQoKICAgIGxlYWYgbmZJbnN0YW5jZUlEIHsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSB5YW5nOnV1aWQgOwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBwcm9maWxlIGZvciBtYW5hZ2VkIE5GLgogICAgICAgIFRoZSBmb3JtYXQgb2YgdGhlIE5GIEluc3RhbmNlIElEIHNoYWxsIGJlIGEKICAgICAgICBVbml2ZXJzYWxseSBVbmlxdWUgSWRlbnRpZmllciAoVVVJRCkgdmVyc2lvbiA0LAogICAgICAgIGFzIGRlc2NyaWJlZCBpbiBJRVRGIFJGQyA0MTIyICIgOwogICAgICB5ZXh0M2dwcDppblZhcmlhbnQ7CiAgICB9CgogICAgbGVhZi1saXN0IG5mVHlwZSB7CiAgICAgIGNvbmZpZyBmYWxzZTsKICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgIHR5cGUgTmZUeXBlOwogICAgICBkZXNjcmlwdGlvbiAiVHlwZSBvZiB0aGUgTmV0d29yayBGdW5jdGlvbiIgOwogICAgfQoKICAgIGxlYWYgaG9zdEFkZHIgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSBpbmV0Omhvc3QgOwogICAgICBkZXNjcmlwdGlvbiAiSG9zdCBhZGRyZXNzIG9mIGEgTkYiOwogICAgfQoKICAgIGxlYWYgYXV0aHpJbmZvIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBORiBTcGVjaWZpYyBTZXJ2aWNlIGF1dGhvcml6YXRpb24KICAgICAgICBpbmZvcm1hdGlvbi4gSXQgc2hhbGwgaW5jbHVkZSB0aGUgTkYgdHlwZSAocykgYW5kIE5GIHJlYWxtcy9vcmlnaW5zCiAgICAgICAgYWxsb3dlZCB0byBjb25zdW1lIE5GIFNlcnZpY2Uocykgb2YgTkYgU2VydmljZSBQcm9kdWNlci4iOwogICAgICByZWZlcmVuY2UgIlNlZSBUUyAyMy41MDEiIDsKICAgIH0KCiAgICBsZWFmIGxvY2F0aW9uIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiSW5mb3JtYXRpb24gYWJvdXQgdGhlIGxvY2F0aW9uIG9mIHRoZSBORiBpbnN0YW5jZQogICAgICAgIChlLmcuIGdlb2dyYXBoaWMgbG9jYXRpb24sIGRhdGEgY2VudGVyKSBkZWZpbmVkIGJ5IG9wZXJhdG9yIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmIGNhcGFjaXR5IHsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIHR5cGUgdWludDE2IDsKICAgICAgZGVzY3JpcHRpb24gIlRoaXMgcGFyYW1ldGVyIGRlZmluZXMgc3RhdGljIGNhcGFjaXR5IGluZm9ybWF0aW9uCiAgICAgICAgaW4gdGhlIHJhbmdlIG9mIDAtNjU1MzUsIGV4cHJlc3NlZCBhcyBhIHdlaWdodCByZWxhdGl2ZSB0byBvdGhlcgogICAgICAgIE5GIGluc3RhbmNlcyBvZiB0aGUgc2FtZSB0eXBlOyBpZiBjYXBhY2l0eSBpcyBhbHNvIHByZXNlbnQgaW4gdGhlCiAgICAgICAgbmZTZXJ2aWNlTGlzdCBwYXJhbWV0ZXJzLCB0aG9zZSB3aWxsIGhhdmUgcHJlY2VkZW5jZSBvdmVyIHRoaXMgdmFsdWUuIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmIG5GU3J2R3JvdXBJZCB7CiAgICAgIHR5cGUgc3RyaW5nIDsKICAgICAgZGVzY3JpcHRpb24gIlRoaXMgcGFyYW1ldGVyIGRlZmluZXMgaWRlbnRpdHkgb2YgdGhlIGdyb3VwIHRoYXQgaXMKICAgICAgICBzZXJ2ZWQgYnkgdGhlIE5GIGluc3RhbmNlLgogICAgICAgIE1heSBiZSBjb25maWcgZmFsc2Ugb3IgdHJ1ZSBkZXBlbmRpbmcgb24gdGhlIE1hbmFnZWRGdW5jdGlvbi4KICAgICAgICBDb25maWc9dHJ1ZSBmb3IgVWRyaW5mby4gQ29uZmlnPWZhbHNlIGZvciBVZG1JbmZvIGFuZCBBdXNmSW5mby4KICAgICAgICBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IFVETSBvciBBVVNGIG9yIFVEUi4gIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmLWxpc3Qgc3VwcG9ydGVkRGF0YVNldElkcyB7CiAgICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICAgIGVudW0gU1VCU0NSSVBUSU9OOwogICAgICAgIGVudW0gUE9MSUNZOwogICAgICAgIGVudW0gRVhQT1NVUkU7CiAgICAgICAgZW51bSBBUFBMSUNBVElPTjsKICAgICAgfQogICAgICBkZXNjcmlwdGlvbiAiTGlzdCBvZiBzdXBwb3J0ZWQgZGF0YSBzZXRzIGluIHRoZSBVRFIgaW5zdGFuY2UuCiAgICAgICAgTWF5IGJlIHByZXNlbnQgaWYgLi4vbmZUeXBlID0gVURSIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmLWxpc3Qgc21mU2VydmluZ0FyZWFzIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiRGVmaW5lcyB0aGUgU01GIHNlcnZpY2UgYXJlYShzKSB0aGUgVVBGIGNhbiBzZXJ2ZS4KICAgICAgICBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IFVQRiI7CiAgICAgIHJlZmVyZW5jZSAiVFMgMjkuNTEwIiA7CiAgICB9CgogICAgbGVhZiBwcmlvcml0eSB7CiAgICAgIHR5cGUgdWludDE2OwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBQcmlvcml0eSAocmVsYXRpdmUgdG8gb3RoZXIgTkZzCiAgICAgICAgb2YgdGhlIHNhbWUgdHlwZSkgaW4gdGhlIHJhbmdlIG9mIDAtNjU1MzUsIHRvIGJlIHVzZWQgZm9yIE5GIHNlbGVjdGlvbjsKICAgICAgICBsb3dlciB2YWx1ZXMgaW5kaWNhdGUgYSBoaWdoZXIgcHJpb3JpdHkuIElmIHByaW9yaXR5IGlzIGFsc28gcHJlc2VudAogICAgICAgIGluIHRoZSBuZlNlcnZpY2VMaXN0IHBhcmFtZXRlcnMsIHRob3NlIHdpbGwgaGF2ZSBwcmVjZWRlbmNlIG92ZXIKICAgICAgICB0aGlzIHZhbHVlLiBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IEFNRiAiOwogICAgICByZWZlcmVuY2UgIlRTIDI5LjUxMCIgOwogICAgfQogIH0KCiAgdHlwZWRlZiB1c2FnZVN0YXRlIHsKICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICBlbnVtIElETEU7CiAgICAgIGVudW0gQUNUSVZFOwogICAgICBlbnVtIEJVU1k7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiSXQgZGVzY3JpYmVzIHdoZXRoZXIgb3Igbm90IHRoZSByZXNvdXJjZSBpcyBhY3RpdmVseSBpbgogICAgICB1c2UgYXQgYSBzcGVjaWZpYyBpbnN0YW50LCBhbmQgaWYgc28sIHdoZXRoZXIgb3Igbm90IGl0IGhhcyBzcGFyZQogICAgICBjYXBhY2l0eSBmb3IgYWRkaXRpb25hbCB1c2VycyBhdCB0aGF0IGluc3RhbnQuIFRoZSB2YWx1ZSBpcyBSRUFELU9OTFkuIjsKICAgIHJlZmVyZW5jZSAiSVRVIFQgUmVjb21tZW5kYXRpb24gWC43MzEiOwogIH0KCiAgZ3JvdXBpbmcgU0FQR3JwIHsKICAgIGxlYWYgaG9zdCB7CiAgICAgIHR5cGUgaW5ldDpob3N0OwogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgIH0KICAgIGxlYWYgcG9ydCB7CiAgICAgIHR5cGUgaW5ldDpwb3J0LW51bWJlcjsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiU2VydmljZSBhY2Nlc3MgcG9pbnQuIjsKICAgIHJlZmVyZW5jZSAiVFMgMjguNjIyIjsKICB9CgogIHR5cGVkZWYgTWNjIHsKICAgIGRlc2NyaXB0aW9uICJUaGUgbW9iaWxlIGNvdW50cnkgY29kZSBjb25zaXN0cyBvZiB0aHJlZSBkZWNpbWFsIGRpZ2l0cywKICAgICAgVGhlIGZpcnN0IGRpZ2l0IG9mIHRoZSBtb2JpbGUgY291bnRyeSBjb2RlIGlkZW50aWZpZXMgdGhlIGdlb2dyYXBoaWMKICAgICAgcmVnaW9uICh0aGUgZGlnaXRzIDEgYW5kIDggYXJlIG5vdCB1c2VkKToiOwogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMDItNzldWzAtOV1bMC05XSc7CiAgICB9CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuMDAzIHN1YmNsYXVzZSAyLjIgYW5kIDEyLjEiOwogIH0KCiAgdHlwZWRlZiBNbmMgewogICAgZGVzY3JpcHRpb24gIlRoZSBtb2JpbGUgbmV0d29yayBjb2RlIGNvbnNpc3RzIG9mIHR3byBvciB0aHJlZQogICAgICBkZWNpbWFsIGRpZ2l0cyAoZm9yIGV4YW1wbGU6IE1OQyBvZiAwMDEgaXMgbm90IHRoZSBzYW1lIGFzIE1OQyBvZiAwMSkiOwogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMC05XVswLTldWzAtOV18WzAtOV1bMC05XSc7CiAgICB9CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuMDAzIHN1YmNsYXVzZSAyLjIgYW5kIDEyLjEiOwogIH0KCiAgZ3JvdXBpbmcgUExNTklkIHsKICAgIGxlYWYgbWNjIHsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIHR5cGUgTWNjOwogICAgfQogICAgbGVhZiBtbmMgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSBNbmM7CiAgICB9CiAgICByZWZlcmVuY2UgIlRTIDM4LjQxMyBjbGF1c2UgOS4zLjMuNSI7CiAgfQoKICB0eXBlZGVmIE5jaSB7CiAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbCBJZGVudGl0eS4gVGhlIE5DSSBzaGFsbCBiZSBvZiBmaXhlZCBsZW5ndGggb2YgMzYgYml0cwogICAgICBhbmQgc2hhbGwgYmUgY29kZWQgdXNpbmcgZnVsbCBoZXhhZGVjaW1hbCByZXByZXNlbnRhdGlvbi4KICAgICAgVGhlIGV4YWN0IGNvZGluZyBvZiB0aGUgTkNJIGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiBlYWNoIFBMTU4gb3BlcmF0b3IiOwogICAgcmVmZXJlbmNlICJUUyAyMy4wMDMiOwogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggMzY7CiAgICAgICAgcGF0dGVybiAnWzAxXSsnOwogICAgICB9CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggOTsKICAgICAgICBwYXR0ZXJuICdbYS1mQS1GMC05XSonOwogICAgICB9CiAgICB9CiAgfQoKICB0eXBlZGVmIE9wZXJhdGlvbmFsU3RhdGUgewogICAgcmVmZXJlbmNlICIzR1BQIFRTIDI4LjYyNSBhbmQgSVRVLVQgWC43MzEiOwogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gRElTQUJMRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyB0b3RhbGx5IGlub3BlcmFibGUuIjsKICAgICAgfQoKICAgICAgZW51bSBFTkFCTEVEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgcGFydGlhbGx5IG9yIGZ1bGx5IG9wZXJhYmxlLiI7CiAgICAgIH0KCiAgICB9CiAgfQoKICB0eXBlZGVmIEJhc2ljQWRtaW5pc3RyYXRpdmVTdGF0ZSB7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjguNjI1IGFuZCBJVFUtVCBYLjczMSI7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBMT0NLRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyBhZG1pbmlzdHJhdGl2ZWx5IHByb2hpYml0ZWQgZnJvbSBwZXJmb3JtaW5nCiAgICAgICAgICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4iOwogICAgICB9CgogICAgICBlbnVtIFVOTE9DS0VEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgYWRtaW5pc3RyYXRpdmVseSBwZXJtaXR0ZWQgdG8gcGVyZm9ybQogICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4gVGhpcyBpcyBpbmRlcGVuZGVudCBvZiBpdHMgaW5oZXJlbnQKICAgICAgICAgIG9wZXJhYmlsaXR5LiI7CiAgICAgIH0KICAgIH0KICB9CgogIHR5cGVkZWYgQWRtaW5pc3RyYXRpdmVTdGF0ZSB7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjguNjI1IGFuZCBJVFUtVCBYLjczMSI7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBMT0NLRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyBhZG1pbmlzdHJhdGl2ZWx5IHByb2hpYml0ZWQgZnJvbSBwZXJmb3JtaW5nCiAgICAgICAgICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4iOwogICAgICB9CgogICAgICBlbnVtIFVOTE9DS0VEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgYWRtaW5pc3RyYXRpdmVseSBwZXJtaXR0ZWQgdG8gcGVyZm9ybQogICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4gVGhpcyBpcyBpbmRlcGVuZGVudCBvZiBpdHMgaW5oZXJlbnQKICAgICAgICAgIG9wZXJhYmlsaXR5LiI7CiAgICAgIH0KCiAgICAgIGVudW0gU0hVVFRJTkdET1dOIHsKICAgICAgICB2YWx1ZSAyOwogICAgICAgIGRlc2NyaXB0aW9uICJVc2Ugb2YgdGhlIHJlc291cmNlIGlzIGFkbWluaXN0cmF0aXZlbHkgcGVybWl0dGVkIHRvCiAgICAgICAgICBleGlzdGluZyBpbnN0YW5jZXMgb2YgdXNlIG9ubHkuIFdoaWxlIHRoZSBzeXN0ZW0gcmVtYWlucyBpbgogICAgICAgICAgdGhlIHNodXR0aW5nIGRvd24gc3RhdGUgdGhlIG1hbmFnZXIgb3IgdGhlIG1hbmFnZWQgZWxlbWVudAogICAgICAgICAgbWF5IGF0IGFueSB0aW1lIGNhdXNlIHRoZSByZXNvdXJjZSB0byB0cmFuc2l0aW9uIHRvIHRoZQogICAgICAgICAgbG9ja2VkIHN0YXRlLiI7CiAgICAgIH0KICAgIH0KICB9CgogIHR5cGVkZWYgQXZhaWxhYmlsaXR5U3RhdHVzIHsKICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICBlbnVtIElOX1RFU1Q7CiAgICAgICAgICBlbnVtIEZBSUxFRDsKICAgICAgICAgIGVudW0gUE9XRVJfT0ZGOwogICAgICAgICAgZW51bSBPRkZfTElORTsKICAgICAgICAgIGVudW0gT0ZGX0RVVFk7CiAgICAgICAgICBlbnVtIERFUEVOREVOQ1k7CiAgICAgICAgICBlbnVtIERFR1JBREVEOwogICAgICAgICAgZW51bSBOT1RfSU5TVEFMTEVEOwogICAgICAgICAgZW51bSBMT0dfRlVMTDsKICAgICAgIH0KICB9CgogIHR5cGVkZWYgQ2VsbFN0YXRlIHsKICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgZW51bSBJRExFOwogICAgICAgIGVudW0gSU5BQ1RJVkU7CiAgICAgICAgZW51bSBBQ1RJVkU7CiAgICAgfQogIH0KCiAgdHlwZWRlZiBOcnBjaSB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uICJQaHlzaWNhbCBDZWxsIElkZW50aXR5IChQQ0kpIG9mIHRoZSBOUiBjZWxsLiI7CiAgICByZWZlcmVuY2UgIlRTIDM2LjIxMSBzdWJjbGF1c2UgNi4xMSI7CiAgfQoKICB0eXBlZGVmIFRhYyB7CiAgICB0eXBlIGludDMyIHsKICAgICAgcmFuZ2UgMC4uMTY3NzcyMTUgOwogICAgfQogICAgZGVzY3JpcHRpb24gIlRyYWNraW5nIEFyZWEgQ29kZSI7CiAgICByZWZlcmVuY2UgIlRTIDIzLjAwMyBjbGF1c2UgMTkuNC4yLjMiOwogIH0KCiAgZ3JvdXBpbmcgVGFpR3JwIHsKICAgIGRlc2NyaXB0aW9uICJUaGlzIDw8ZGF0YVR5cGU+PiBkZWZpbmVzIGEgVHJhY2tpbmcgQXJlYSBJZGVudGl0eSAoVEFJKQogICAgICBhcyBzcGVjaWZpZWQgaW4gY2xhdXNlIDI4LjYgb2YgVFMgMjMuMDAzLCBjbGF1c2UgOC4yIG9mIFRTIDM4LjMwMAogICAgICBhbmQgY2xhdXNlIDkuMy4zLjExIG9mIFRTIDM4LjQxMy4gSXQgaXMgY29tcG9zZWQgb2YgdGhlIFBMTU4KICAgICAgaWRlbnRpZmllciAoUExNTi1JZCwgd2hpY2ggaXMgY29tcG9zZWQgb2YgdGhlIE1DQyBhbmQgTU5DKSBhbmQKICAgICAgdGhlIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKS4gIjsKICAgIGxpc3QgcGxtbklkIHsKICAgICAgZGVzY3JpcHRpb24gIlBMTU4gSWRlbnRpdHkuIjsKICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgIG1heC1lbGVtZW50cyAxOwogICAgICBrZXkgIm1jYyBtbmMiOwogICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICB9CgogICAgbGVhZiB0YWMgeyB0eXBlIFRhYzsgfQogIH0KCiAgZ3JvdXBpbmcgR2VvQ29vcmRpbmF0ZUdycCB7CiAgICBkZXNjcmlwdGlvbiAiR2VvZ3JhcGhpY2FsIGxvY2F0aW9uIG9uIGVhcnRoIjsKICAgIGxlYWYgbGF0aXR1ZGUgewogICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDQ7CiAgICAgICAgcmFuZ2UgLTkwLi45MCA7CiAgICAgIH0KICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIGRlc2NyaXB0aW9uICJMYXRpdHVkZSBiYXNlZCBvbiBXb3JsZCBHZW9kZXRpYyBTeXN0ZW0gKDE5ODQgdmVyc2lvbikKICAgICAgICBnbG9iYWwgcmVmZXJlbmNlIGZyYW1lIChXR1MgODQpLiBQb3NpdGl2ZSB2YWx1ZXMgY29ycmVzcG9uZCB0byB0aGUKICAgICAgICBub3J0aGVybiBoZW1pc3BoZXJlLiI7CiAgICAgIH0KCiAgICBsZWFmIGxvbmdpdHVkZSB7CiAgICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNDsKICAgICAgICByYW5nZSAtMTgwLi4xODAgOwogICAgICB9CiAgICAgIG1hbmRhdG9yeSB0cnVlOwogICAgICBkZXNjcmlwdGlvbiAiTG9uZ2l0dWRlIGJhc2VkIG9uIFdvcmxkIEdlb2RldGljIFN5c3RlbSAoMTk4NCB2ZXJzaW9uKQogICAgICAgIGdsb2JhbCByZWZlcmVuY2UgZnJhbWUgKFdHUyA4NCkuIFBvc2l0aXZlIHZhbHVlcyBjb3JyZXNwb25kIHRvCiAgICAgICAgZGVncmVlcyBlYXN0IG9mIDAgZGVncmVlcyBsb25naXR1ZGUuIjsKICAgIH0KICB9CgogIGdyb3VwaW5nIEdlb0FyZWFHcnAgewogICAgZGVzY3JpcHRpb24gIlRoaXMgZGF0YSB0eXBlIGRlZmluZXMgYSBnZW9ncmFwaGljYWwgYXJlYS4KICAgICAgVGhlIGdlby1hcmVhIGlzIGRlZmluZWQgdXNpbmcgYSBjb252ZXggcG9seWdvbiBpbiB0aGUgYXR0cmlidXRlCiAgICAgICdjb252ZXhHZW9Qb2x5Z29uJy4iOwoKICAgIGxpc3QgY29udmV4R2VvUG9seWdvbiB7CiAgICAgIGRlc2NyaXB0aW9uICJTcGVjaWZpZXMgdGhlIGdlb2dyYXBoaWNhbCBhcmVhIHdpdGggYSBjb252ZXggcG9seWdvbi4KICAgICAgICBUaGUgY29udmV4IHBvbHlnb24gaXMgc3BlY2lmaWVkIGJ5IGl0cyBjb3JuZXJzLiI7CiAgICAgICAga2V5ICJsYXRpdHVkZSBsb25naXR1ZGUiOwogICAgICBtaW4tZWxlbWVudHMgMzsKICAgICAgb3JkZXJlZC1ieSB1c2VyOwoKICAgICAgdXNlcyBHZW9Db29yZGluYXRlR3JwOwogICAgfQogIH0KCiAgdHlwZWRlZiBBbWZSZWdpb25JZCB7CiAgICB0eXBlIHVuaW9uIHsKICAgICAgdHlwZSB1aW50OCA7CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggODsKICAgICAgICBwYXR0ZXJuICdbMDFdKic7CiAgICAgIH0KICAgIH0KICAgIHJlZmVyZW5jZSAiY2xhdXNlIDIuMTAuMSBvZiAzR1BQIFRTIDIzLjAwMyI7CiAgfQoKICB0eXBlZGVmIEFtZlNldElkIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIHVpbnQxNiB7CiAgICAgICAgcmFuZ2UgJzAuLjEwMjMnOwogICAgICB9CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggODsKICAgICAgICBwYXR0ZXJuICdbMDFdKic7CiAgICAgIH0KICAgIH0KICAgIHJlZmVyZW5jZSAiY2xhdXNlIDIuMTAuMSBvZiAzR1BQIFRTIDIzLjAwMyI7CiAgfQoKICB0eXBlZGVmIEFtZlBvaW50ZXIgewogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgdWludDggewogICAgICAgIHJhbmdlICcwLi42Myc7CiAgICAgIH0KICAgICAgdHlwZSBzdHJpbmcgewogICAgICAgIGxlbmd0aCA2OwogICAgICAgIHBhdHRlcm4gJ1swMV0qJzsKICAgICAgfQogICAgfQogICAgcmVmZXJlbmNlICJjbGF1c2UgMi4xMC4xIG9mIDNHUFAgVFMgMjMuMDAzIjsKICB9CgogIGdyb3VwaW5nIEFtZklkZW50aWZpZXIgewogICAgbGVhZiBhbWZSZWdpb25JZCB7CiAgICAgIHR5cGUgQW1mUmVnaW9uSWQ7CiAgICB9CiAgICBsZWFmIGFtZlNldElkIHsKICAgICAgdHlwZSBBbWZTZXRJZDsKICAgIH0KICAgIGxlYWYgYW1mUG9pbnRlciB7CiAgICAgIHR5cGUgQW1mUG9pbnRlcjsKICAgIH0KICAgIGRlc2NyaXB0aW9uICJUaGUgQU1GSSBpcyBjb25zdHJ1Y3RlZCBmcm9tIGFuIEFNRiBSZWdpb24gSUQsCiAgICAgIGFuIEFNRiBTZXQgSUQgYW5kIGFuIEFNRiBQb2ludGVyLgogICAgICBUaGUgQU1GIFJlZ2lvbiBJRCBpZGVudGlmaWVzIHRoZSByZWdpb24sCiAgICAgIHRoZSBBTUYgU2V0IElEIHVuaXF1ZWx5IGlkZW50aWZpZXMgdGhlIEFNRiBTZXQgd2l0aGluIHRoZSBBTUYgUmVnaW9uLCBhbmQKICAgICAgdGhlIEFNRiBQb2ludGVyIHVuaXF1ZWx5IGlkZW50aWZpZXMgdGhlIEFNRiB3aXRoaW4gdGhlIEFNRiBTZXQuICI7CiAgfQoKLy8gdHlwZSBkZWZpbml0aW9ucyBlc3BlY2lhbGx5IGZvciBjb3JlIE5GcwoKICB0eXBlZGVmIE5mVHlwZSB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBOUkY7CiAgICAgIGVudW0gVURNOwogICAgICBlbnVtIEFNRjsKICAgICAgZW51bSBTTUY7CiAgICAgIGVudW0gQVVTRjsKICAgICAgZW51bSBORUY7CiAgICAgIGVudW0gUENGOwogICAgICBlbnVtIFNNU0Y7CiAgICAgIGVudW0gTlNTRjsKICAgICAgZW51bSBVRFI7CiAgICAgIGVudW0gTE1GOwogICAgICBlbnVtIEdNTEM7CiAgICAgIGVudW0gNUdfRUlSOwogICAgICBlbnVtIFNFUFA7CiAgICAgIGVudW0gVVBGOwogICAgICBlbnVtIE4zSVdGOwogICAgICBlbnVtIEFGOwogICAgICBlbnVtIFVEU0Y7CiAgICAgIGVudW0gQlNGOwogICAgICBlbnVtIENIRjsKICAgIH0KICB9CgogIHR5cGVkZWYgTm90aWZpY2F0aW9uVHlwZSB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBOMV9NRVNTQUdFUzsKICAgICAgZW51bSBOMl9JTkZPUk1BVElPTjsKICAgICAgZW51bSBMT0NBVElPTl9OT1RJRklDQVRJT047CiAgICB9CiAgfQoKICB0eXBlZGVmIExvYWQgewogICAgZGVzY3JpcHRpb24gIkxhdGVzdCBrbm93biBsb2FkIGluZm9ybWF0aW9uIG9mIHRoZSBORiwgcGVyY2VudGFnZSAiOwogICAgdHlwZSB1aW50OCB7CiAgICAgIHJhbmdlIDAuLjEwMDsKICAgIH0KICB9CgogIHR5cGVkZWYgTjFNZXNzYWdlQ2xhc3MgewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gNUdNTTsKICAgICAgZW51bSBTTTsKICAgICAgZW51bSBMUFA7CiAgICAgIGVudW0gU01TOwogICAgfQogIH0KCiAgdHlwZWRlZiBOMkluZm9ybWF0aW9uQ2xhc3MgewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gU007CiAgICAgIGVudW0gTlJQUEE7CiAgICAgIGVudW0gUFdTOwogICAgICBlbnVtIFBXU19CQ0FMOwogICAgICBlbnVtIFBXU19SRjsKICAgIH0KICB9CgogIGdyb3VwaW5nIERlZmF1bHROb3RpZmljYXRpb25TdWJzY3JpcHRpb24gewoKICAgIGxlYWYgbm90aWZpY2F0aW9uVHlwZSB7CiAgICAgIHR5cGUgTm90aWZpY2F0aW9uVHlwZTsKICAgIH0KCiAgICBsZWFmIGNhbGxiYWNrVXJpIHsKICAgICAgdHlwZSBpbmV0OnVyaTsKICAgIH0KCiAgICBsZWFmIG4xTWVzc2FnZUNsYXNzIHsKICAgICAgdHlwZSBOMU1lc3NhZ2VDbGFzczsKICAgIH0KCiAgICBsZWFmIG4ySW5mb3JtYXRpb25DbGFzcyB7CiAgICAgIHR5cGUgTjJJbmZvcm1hdGlvbkNsYXNzOwogICAgfQogIH0KCiAgZ3JvdXBpbmcgSXB2NEFkZHJlc3NSYW5nZSB7CiAgbGVhZiBzdGFydCB7CiAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzOwogICAgfQogIGxlYWYgZW5kIHsKICAgIHR5cGUgaW5ldDppcHY0LWFkZHJlc3M7CiAgICB9CiAgfQoKICBncm91cGluZyBJcHY2UHJlZml4UmFuZ2UgewogIGxlYWYgc3RhcnQgewogICAgdHlwZSBpbmV0OmlwdjYtcHJlZml4OwogICAgfQogIGxlYWYgZW5kIHsKICAgIHR5cGUgaW5ldDppcHY2LXByZWZpeDsKICAgIH0KICB9CgogIHR5cGVkZWYgTnNpSWQgewogICAgdHlwZSBzdHJpbmc7CiAgfQoKICB0eXBlZGVmIFVlTW9iaWxpdHlMZXZlbCB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBTVEFUSU9OQVJZOwogICAgICBlbnVtIE5PTUFESUM7CiAgICAgIGVudW0gUkVTVFJJQ1RFRF9NT0JJTElUWTsKICAgICAgZW51bSBGVUxMWV9NT0JJTElUWTsKICAgIH0KICB9CgogIHR5cGVkZWYgUmVzb3VyY2VTaGFyaW5nTGV2ZWwgewogICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICBlbnVtIFNIQVJFRDsKICAgICAgICBlbnVtIE5PVF9TSEFSRUQ7CiAgICAgIH0KICB9CgogIHR5cGVkZWYgVHhEaXJlY3Rpb24gewogICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICBlbnVtIERMOwogICAgICAgIGVudW0gVUw7CiAgICAgICAgZW51bSBETF9BTkRfVUw7CiAgICAgIH0KICB9CgogIGdyb3VwaW5nIEFkZHJlc3NXaXRoVmxhbiB7CiAgICBsZWFmIGlwQWRkcmVzcyB7CiAgICAgIHR5cGUgaW5ldDppcC1hZGRyZXNzOwogICAgfQogICAgbGVhZiB2bGFuSWQgewogICAgICAgdHlwZSB1aW50MTY7CiAgICB9CiAgfQoKICAvKiBEaXN0aW5ndWlzaGVkTmFtZSBwYXR0ZXJuIGlzIGJ1aWx0IHVwIGJhc2VkIG9uIHRoZQogICAgRUJORiBpbiAzMi4zMDAgY2xhdXNlIDcuMyAgRUJORiBvZiBETiBTdHJpbmcgUmVwcmVzZW50YXRpb24KCiAgICBsZWFmIEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vICBTYW1lIHBhdHRlcm4gYXMgTG9jYWxETgogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPygsW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKj0oW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pKic7CiAgICB9IH0KCiAgICBsZWFmIGZ1bGxMb2NhbEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIExvY2FsUkROICwgeyBSRE5TZXBhcmF0b3IgLCBMb2NhbFJETiB9ICAgIFJETlNlcGFyYXRvciBpcyBhIHNpbmdsZSAsIG5vIHNwYWNlIG9yIFxSIGFsbG93ZWQgICBNZS5teWtleT0xIGFsbG93ZWQKICAgICAgLy8gIChmdWxsTG9jYWxSRE4pKCwoZnVsbExvY2FsUkROKSkqCiAgICAgIHBhdHRlcm4gJygoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKikpPSgoW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pKSgsKChbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qfChbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qXC5bYS16XVteLD0rPD4jO1xcIlxyXG4qLl0qKSk9KChbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykpKSonOwogICAgfSB9CgogICAgbGVhZiBMb2NhbEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIExvY2FsUkROICwgeyBSRE5TZXBhcmF0b3IgLCBMb2NhbFJETiB9ICAgIFJETlNlcGFyYXRvciBpcyBhIHNpbmdsZSAsIG5vIHNwYWNlIG9yIFxSIGFsbG93ZWQKICAgICAgLy8gIExvY2FsUkROKCxMb2NhbFJETikqCiAgICAgIHBhdHRlcm4gJ1tBLVpdW14sPSs8PiM7XFwiXHJcbiouXSo9KFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/KCxbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykqJzsKICAgIH0gfQoKICAgIGxlYWYgZnVsbExvY2FsUkROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIHNhbWUgYXMgZnVsbExvY2FsRE5BdHRyaWJ1dGVUeXBlQW5kVmFsdWUKICAgICAgcGF0dGVybiAnKFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSp8KFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSpcLlthLXpdW14sPSs8PiM7XFwiXHJcbiouXSopKT0oKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/KSc7CiAgICB9IH0KCiAgICBsZWFmIExvY2FsUkROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIHNhbWUgYXMgTG9jYWxETkF0dHJpYnV0ZVR5cGVBbmRWYWx1ZQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPyc7CiAgICB9IH0KCiAgICBsZWFmIGZ1bGxMb2NhbEROQXR0cmlidXRlVHlwZUFuZFZhbHVlIHsgdHlwZSBzdHJpbmcgeyAvLyBMb2NhbEROQXR0cmlidXRlVHlwZSAsIEF0dHJpYnV0ZVR5cGVBbmRWYWx1ZVNlcGFyYXRvciAsIFJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICAvLyBwYXR0ZXJuIExvY2FsRE5BdHRyaWJ1dGVUeXBlPVJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICBwYXR0ZXJuICcoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKikpPSgoW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pJzsKICAgIH0gfQoKICAgICAgLy8gbGltaXRhdGlvbjogTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlbm90IHN1cHBvcnRlZCBNZS5teWtleT0xCiAgICBsZWFmIExvY2FsRE5BdHRyaWJ1dGVUeXBlQW5kVmFsdWUgeyB0eXBlIHN0cmluZyB7CiAgICAgIC8vIGVibmYxICAgICAgICAgIExvY2FsRE5BdHRyaWJ1dGVUeXBlICwgQXR0cmlidXRlVHlwZUFuZFZhbHVlU2VwYXJhdG9yICwgUmVndWxhckF0dHJpYnV0ZVZhbHVlCiAgICAgIC8vIGVibmYyLWxpbWl0ZWQgIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlICwgQXR0cmlidXRlVHlwZUFuZFZhbHVlU2VwYXJhdG9yICwgUmVndWxhckF0dHJpYnV0ZVZhbHVlCiAgICAgIC8vIHBhdHRlcm4gICAgICAgIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlPVJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPyc7CiAgICB9IH0KCiAgICBsZWFmIExvY2FsRE5BdHRyaWJ1dGVUeXBlIHsgdHlwZSBzdHJpbmcgeyAgIC8vIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlIHwgTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlICBSRE5TZXBhcmF0b3IgaXMgYSBzaW5nbGUgLCBubyBzcGFjZSBvciBcUiBhbGxvd2VkCiAgICAgIC8vICBOYW1lT2ZDbGFzc1dpdGhJZEF0dHJpYnV0ZXxOYW1lc09mQ2xhc3NBbmROYW1pbmdBdHRyaWJ1dGUKICAgICAgcGF0dGVybiAnW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKiknOwogICAgfSB9CgogICAgbGVhZiBSZWd1bGFyQXR0cmlidXRlVmFsdWUgeyB0eXBlIHN0cmluZyB7ICAgICAgIC8vICggQXR0cmlidXRlVmFsdWVDaGFyIC0gU3BhY2VDaGFyICkgLCBbIHsgQXR0cmlidXRlVmFsdWVDaGFyIH0gLCAoIEF0dHJpYnV0ZVZhbHVlQ2hhciAtIFNwYWNlQ2hhciApIF0KICAgICAgcGF0dGVybiAnKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/JyA7CiAgICB9IH0KCiAgICBsZWFmIE5hbWVzT2ZDbGFzc0FuZE5hbWluZ0F0dHJpYnV0ZSAgeyB0eXBlIHN0cmluZyB7ICAvLyBDbGFzc05hbWUgLCBDbGFzc05hbWluZ0F0dHJpYnV0ZVNlcGFyYXRvciAsIE5hbWluZ0F0dHJpYnV0ZU5hbWUKICAgICAgLy8gcGF0dGVybjogQ2xhc3NOYW1lXC5OYW1pbmdBdHRyaWJ1dGVOYW1lCiAgICAgIHBhdHRlcm4gJ1tBLVpdW14sPSs8PiM7XFwiXHJcbiouXSpcLlthLXpdW14sPSs8PiM7XFwiXHJcbiouXSonIDsKICAgIH0gfQoKICAgIGxlYWYgcmVzdHJpY3RpdmVDbGFzc05hbWUgeyB0eXBlIHN0cmluZyB7ICAgICAvLwogICAgICBwYXR0ZXJuICdbYS16QS1aXVthLXpBLVowLTktX10qJyA7CiAgICB9IH0KCiAgICBsZWFmIENsYXNzTmFtZSB7IHR5cGUgc3RyaW5nIHsgICAgIC8vIENhcGl0YWxMZXR0ZXJDaGFyICwgeyBMb2NhbEROQXR0cmlidXRlVHlwZUNoYXIgfQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qJyA7CiAgICB9IH0KCiAgICBsZWFmIE5hbWluZ0F0dHJpYnV0ZU5hbWUgeyB0eXBlIHN0cmluZyB7ICAgLy8gU21hbGxMZXR0ZXJDaGFyICwgeyBMb2NhbEROQXR0cmlidXRlVHlwZUNoYXIgfQogICAgICBwYXR0ZXJuICdbYS16XVteLD0rPD4jO1xcIlxyXG4qLl0qJyA7CiAgICB9IH0KCiAgKi8KICB0eXBlZGVmIERpc3Rpbmd1aXNoZWROYW1lIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKj0oW14sPSs8PiM7XFwiXHJcbiogXXwnCiAgICAgICsgJyhcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKicKICAgICAgKyAnKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/JwogICAgICArICcoLFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSo9KFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKScKICAgICAgKyAnKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSonCiAgICAgICsgJyhbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykqJzsKICAgIH0KICAgIGRlc2NyaXB0aW9uICJSZXByZXNlbnRzIHRoZSAzR1BQIHN0YW5kYXJkIGZvciBEaXN0aW5ndWlzaGVkTmFtZS4KCiAgICAgIExpbWl0YXRpb25zOgogICAgICAtIFJETlNlcGFyYXRvcjogZG9uJ3QgYWxsb3cgU3BhY2VDaGFyIG9yIENhcnJpYWdlUmV0dXJuQ2hhcgogICAgICAtIE51bGxETjogRGlzYWxsb3cgbnVsbEROIHRoYXQgaXMgdGhlIHNhbWUgYXMgbm90IHByb3ZpZGluZyBhIEROCiAgICAgIC0gTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlIGZvcm1hdCBub3QgYWxsb3dlZAogICAgICAgIChlZy4gTWFuYWdlZEVsZW1lbnQubXlrZXk9MzQ1NDM2KSI7CiAgICByZWZlcmVuY2UgICIzR1BQIFRTIDMyLjMwMCI7CiAgfQoKICB0eXBlZGVmIFFPZmZzZXRSYW5nZSAgewogICAgdHlwZSBpbnQ4IHsKICAgICAgcmFuZ2UgIi0yNCB8IC0yMiB8IC0yMCB8IC0xOCB8IC0xNiB8IC0xNCB8IC0xMiB8IC0xMCB8IC04IHwgLTYgfCAiICsKICAgICAgICAiIC01IHwgLTQgfCAtMyB8IC0yIHwgLTEgfCAwIHwgMSB8IDIgfCAzIHwgNCB8IDUgfCA2IHwgOCB8IDEwIHwgIiArCiAgICAgICAgIiAxMiB8IDE0IHwgMTYgfCAxOCB8IDIwIHwgMjIgfCAyNCI7CiAgICB9CiAgICB1bml0cyBkQjsKICB9CgogIGdyb3VwaW5nIFJlcG9ydGluZ0N0cmwgewogICAgY2hvaWNlIHJlcG9ydGluZ0N0cmwgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgZGVzY3JpcHRpb24gIgogICAgICAgIFRoaXMgY2hvaWNlIGRlZmluZXMgdGhlIG1ldGhvZCBmb3IgcmVwb3J0aW5nIGNvbGxlY3RlZCBwZXJmb3JtYW5jZQogICAgICAgIG1ldHJpY3MgdG8gTW5TIGNvbnN1bWVycyBhcyB3ZWxsIGFzIHRoZSBwYXJhbWV0ZXJzIGZvciBjb25maWd1cmluZyB0aGUKICAgICAgICByZXBvcnRpbmcgZnVuY3Rpb24uIEl0IGlzIGEgY2hvaWNlIGJldHdlZW4gdGhlIGNvbnRyb2wgcGFyYW1ldGVyCiAgICAgICAgcmVxdWlyZWQgZm9yIHRoZSByZXBvcnRpbmcgbWV0aG9kcywgd2hvc2UgcHJlc2VuY2Ugc2VsZWN0cyB0aGUKICAgICAgICByZXBvcnRpbmcgbWV0aG9kIGFzIGZvbGxvd3M6CgogICAgICAgIC0gV2hlbiBvbmx5IHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGF0dHJpYnV0ZSBpcyBwcmVzZW50LCB0aGUgTW5TCiAgICAgICAgcHJvZHVjZXIgc2hhbGwgc3RvcmUgZmlsZXMgb24gdGhlIE1uUyBwcm9kdWNlciBhdCBhIGxvY2F0aW9uIHNlbGVjdGVkCiAgICAgICAgYnkgdGhlIE1uUyBwcm9kdWNlciBhbmQsIG9uIGNvbmRpdGlvbiB0aGF0IGFuIGFwcHJvcHJpYXRlIHN1YnNjcmlwdGlvbgogICAgICAgIGlzIGluIHBsYWNlLCBpbmZvcm0gdGhlIE1uUyBjb25zdW1lciBhYm91dCB0aGUgYXZhaWxhYmlsaXR5IG9mIG5ldwogICAgICAgIGZpbGVzIGFuZCB0aGUgZmlsZSBsb2NhdGlvbiB1c2luZyB0aGUgbm90aWZ5RmlsZVJlYWR5IG5vdGlmaWNhdGlvbi4KICAgICAgICBJbiBjYXNlIHRoZSBwcmVwYXJhdGlvbiBvZiBhIGZpbGUgZmFpbHMsICdub3RpZnlGaWxlUHJlcGFyYXRpb25FcnJvcicKICAgICAgICBzaGFsbCBiZSBzZW50IGluc3RlYWQuCgogICAgICAgIC0gV2hlbiB0aGUgJ2ZpbGVSZXBvcnRpbmdQZXJpb2QnIGFuZCAnbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcycKICAgICAgICBhdHRyaWJ1dGVzIGFyZSBwcmVzZW50LCB0aGVuIHRoZSBNblMgcHJvZHVjZXIgc2hhbGwgYmVoYXZlIGxpa2UKICAgICAgICBkZXNjcmliZWQgZm9yIHRoZSBjYXNlIHRoYXQgb25seSB0aGUgJ2ZpbGVSZXBvcnRpbmdQZXJpb2QnIGlzIHByZXNlbnQuCiAgICAgICAgSW4gYWRkaXRpb24sIHRoZSBNblMgcHJvZHVjZXIgc2hhbGwgY3JlYXRlIG9uIGJlaGFsZiBvZiB0aGUgTW5TCiAgICAgICAgY29uc3VtZXIgYSBzdWJzY3JpcHRpb24sIHVzaW5nICdOdGZTdWJzY3JpcHRpb25Db250cm9sJywgZm9yIHRoZQogICAgICAgIG5vdGlmaWNhdGlvbiB0eXBlcyAnbm90aWZ5TU9JQ3JlYXRpb24nIGFuZCAnbm90aWZ5TU9JRGVsZXRpb24nIHJlbGF0ZWQKICAgICAgICB0byB0aGUgJ0ZpbGUnIGluc3RhbmNlcyB0aGF0IHdpbGwgYmUgcHJvZHVjZWQgbGF0ZXIuIEluIGNhc2UgYW4gZXhpc3RpbmcKICAgICAgICBzdWJzY3JpcHRpb24gZG9lcyBhbHJlYWR5IGluY2x1ZGUgdGhlICdGaWxlJyBpbnN0YW5jZXMgdG8gYmUgcHJvZHVjZWQsCiAgICAgICAgbm8gbmV3IHN1YnNjcmlwdGlvbiBzaGFsbCBiZSBjcmVhdGVkLiBUaGUKICAgICAgICAnbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcycgYXR0cmlidXRlIGluIHRoZSBjcmVhdGVkCiAgICAgICAgJ050ZlN1YnNjcmlwdGlvbkNvbnRyb2wnIGluc3RhbmNlIHNoYWxsIGJlIHNldCB0byB0aGUgdmFsdWUgb2YgdGhlCiAgICAgICAgJ25vdGlmaWNhdGlvblJlY2lwaWVudEFkZHJlc3MnIGluIHRoZSByZWxhdGVkICdQZXJmTWV0cmljSm9iJy4gVGhpcwogICAgICAgIGZlYXR1cmUgaXMgY2FsbGVkIGltcGxpY2l0IG5vdGlmaWNhdGlvbiBzdWJzY3JpcHRpb24sIGFzIG9wcG9zZWQgdG8gdGhlCiAgICAgICAgY2FzZSB3aGVyZSB0aGUgTW5TIGNvbnN1bWVyIGNyZWF0ZXMgdGhlIHN1YnNjcmlwdGlvbiAoZXhwbGljaXQKICAgICAgICBub3RpZmljYXRpb24gc3Vic2NyaXB0aW9uKS4gV2hlbiB0aGUgcmVsYXRlZCAnUGVyZk1ldHJpY0pvYicgaXMKICAgICAgICBkZWxldGVkLCB0aGUgJ050ZlN1YnNjcmlwdGlvbkNvbnRyb2wnIGluc3RhbmNlIGNyZWF0ZWQgZHVlIHRvIHRoZQogICAgICAgIHJlcXVlc3QgZm9yIGltcGxpY2l0IHN1YnNjcmlwdGlvbiBzaGFsbCBiZSBkZWxldGVkIGFzIHdlbGwuCgogICAgICAgIC0gV2hlbiBvbmx5IHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGFuZCBmaWxlTG9jYXRpb24gYXR0cmlidXRlcyBhcmUKICAgICAgICBwcmVzZW50LCB0aGUgTW5TIHByb2R1Y2VyIHNoYWxsIHN0b3JlIHRoZSBmaWxlcyBvbiBhIE1uUyBjb25zdW1lciwgdGhhdAogICAgICAgIGNhbiBiZSBhbnkgZW50aXR5IHN1Y2ggYXMgYSBmaWxlIHNlcnZlciwgYXQgdGhlIGxvY2F0aW9uIHNwZWNpZmllZCBieQogICAgICAgIGZpbGVMb2NhdGlvbi4gTm8gbm90aWZpY2F0aW9uIGlzIGVtaXR0ZWQgYnkgdGhlIE1uUyBwcm9kdWNlci4KCiAgICAgICAgLSBXaGVuIG9ubHkgdGhlIHN0cmVhbVRhcmdldCBhdHRyaWJ1dGUgaXMgcHJlc2VudCwgdGhlIE1uUyBwcm9kdWNlcgogICAgICAgIHNoYWxsIHN0cmVhbSB0aGUgZGF0YSB0byB0aGUgbG9jYXRpb24gc3BlY2lmaWVkIGJ5IHN0cmVhbVRhcmdldC4KCiAgICAgICAgRm9yIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2RzIHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGF0dHJpYnV0ZQogICAgICAgIHNwZWNpZmllcyB0aGUgdGltZSB3aW5kb3cgZHVyaW5nIHdoaWNoIGNvbGxlY3RlZCBtZWFzdXJlbWVudHMgYXJlCiAgICAgICAgc3RvcmVkIGludG8gdGhlIHNhbWUgZmlsZSBiZWZvcmUgdGhlIGZpbGUgaXMgY2xvc2VkIGFuZCBhIG5ldyBmaWxlIGlzCiAgICAgICAgb3BlbmVkLiI7CgogICAgICBjYXNlIGZpbGUtYmFzZWQtcmVwb3J0aW5nIHsKICAgICAgICBsZWFmIGZpbGVSZXBvcnRpbmdQZXJpb2QgewogICAgICAgICAgdHlwZSB1aW50MzIgewogICAgICAgICAgICByYW5nZSAxLi5tYXg7CiAgICAgICAgICB9CiAgICAgICAgICB1bml0cyBtaW51dGVzOwogICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgICBkZXNjcmlwdGlvbiAiRm9yIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2QgdGhpcyBpcyB0aGUgdGltZQogICAgICAgICAgICB3aW5kb3cgZHVyaW5nIHdoaWNoIGNvbGxlY3RlZCBtZWFzdXJlbWVudHMgYXJlIHN0b3JlZCBpbnRvIHRoZSBzYW1lCiAgICAgICAgICAgIGZpbGUgYmVmb3JlIHRoZSBmaWxlIGlzIGNsb3NlZCBhbmQgYSBuZXcgZmlsZSBpcyBvcGVuZWQuCiAgICAgICAgICAgIFRoZSB0aW1lLXBlcmlvZCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgdGhlIGdyYW51bGFyaXR5UGVyaW9kLgoKICAgICAgICAgICAgQXBwbGljYWJsZSB3aGVuIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2QgaXMgc3VwcG9ydGVkLiI7CiAgICAgICAgfQogICAgICAgIGNob2ljZSByZXBvcnRpbmctdGFyZ2V0IHsKICAgICAgICAgIGNhc2UgZmlsZS10YXJnZXQgewogICAgICAgICAgICBsZWFmIGZpbGVMb2NhdGlvbiB7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nIDsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFwcGxpY2FibGUgYW5kIG11c3QgYmUgcHJlc2VudCB3aGVuIHRoZSBmaWxlLWJhc2VkCiAgICAgICAgICAgICAgcmVwb3J0aW5nIG1ldGhvZCBpcyBzdXBwb3J0ZWQsIGFuZCB0aGUgZmlsZXMgYXJlIHN0b3JlZCBvbiB0aGUgTW5TCiAgICAgICAgICAgICAgY29uc3VtZXIuIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY2FzZSBub3RpZmljYXRpb24tdGFyZ2V0IHsKICAgICAgICAgICAgbGVhZiBub3RpZmljYXRpb25SZWNpcGllbnRBZGRyZXNzIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNdXN0IGJlIHByZXNlbnQgd2hlbiB0aGUgbm90aWZpY2F0aW9uLWJhc2VkIHJlcG9ydGluZwogICAgICAgICAgICAgIG1ldGhvZCBpcyBzdXBwb3J0ZWQsIGFuZCB0aGUgdGhlIGZpbGVzIGFyZSBhdmFpbGFibGUgYXMKICAgICAgICAgICAgICBub3RpZmljYXRpb25zIGZvciB0aGUgTW5TIGNvbnN1bWVyIHRvIHN1YnNjcmliZSB0by4iOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgZGVzY3JpcHRpb24gIldoZW4gbmV0aWhlciBmaWxlTG9jYXRpb24gb3Igbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcwogICAgICAgICAgYXJlIHByZXNlbnQsIHRoZSBmaWxlcyBhcmUgc3RvcmVkIGFuZCBhdmFpbGFibGUgdG8gdGhlIE1uUyBjb25zdW1lcgogICAgICAgICAgaWYgdGhlIE1uUyBzdWJzY3JpYmVzIHRvIHRoZSBub3RpZnlGaWxlUmVhZHkgbm90aWZpY2F0aW9uLiI7CiAgICAgICAgfQogICAgICB9CgogICAgICBjYXNlIHN0cmVhbS1iYXNlZC1yZXBvcnRpbmcgewogICAgICAgIGxlYWYgc3RyZWFtVGFyZ2V0IHsKICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgICBkZXNjcmlwdGlvbiAiQXBwbGljYWJsZSB3aGVuIHN0cmVhbS1iYXNlZCByZXBvcnRpbmcgbWV0aG9kIGlzCiAgICAgICAgICAgIHN1cHBvcnRlZC4iOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KfQo= +ietf-geo-location urn:ietf:params:xml:ns:yang:ietf-geo-location \N [] 2022-02-11 bW9kdWxlIGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjppZXRmOnBhcmFtczp4bWw6bnM6eWFuZzppZXRmLWdlby1sb2NhdGlvbiI7CiAgICBwcmVmaXggZ2VvOwogICAgaW1wb3J0IGlldGYteWFuZy10eXBlcyB7CiAgICBwcmVmaXggeWFuZzsKICAgIHJlZmVyZW5jZSAiUkZDIDY5OTE6IENvbW1vbiBZQU5HIERhdGEgVHlwZXMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbgogICAgIklFVEYgTkVUTU9EIFdvcmtpbmcgR3JvdXAgKE5FVE1PRCkiOwogICAgY29udGFjdAogICAgIldHIFdlYjogICA8aHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy93Zy9uZXRtb2QvPgogICAgV0cgTGlzdDogIDxtYWlsdG86bmV0bW9kQGlldGYub3JnPgoKICAgIEVkaXRvcjogICBDaHJpc3RpYW4gSG9wcHMKICAgICAgICAgICAgICAgIDxtYWlsdG86Y2hvcHBzQGNob3Bwcy5vcmc+IjsKCiAgICBkZXNjcmlwdGlvbgogICAgIlRoaXMgbW9kdWxlIGRlZmluZXMgYSBncm91cGluZyBvZiBhIGNvbnRhaW5lciBvYmplY3QgZm9yCiAgICBzcGVjaWZ5aW5nIGEgbG9jYXRpb24gb24gb3IgYXJvdW5kIGFuIGFzdHJvbm9taWNhbCBvYmplY3QgKGUuZy4sCiAgICAnZWFydGgnKS4KCiAgICBUaGUga2V5IHdvcmRzICdNVVNUJywgJ01VU1QgTk9UJywgJ1JFUVVJUkVEJywgJ1NIQUxMJywgJ1NIQUxMCiAgICBOT1QnLCAnU0hPVUxEJywgJ1NIT1VMRCBOT1QnLCAnUkVDT01NRU5ERUQnLCAnTk9UIFJFQ09NTUVOREVEJywKICAgICdNQVknLCBhbmQgJ09QVElPTkFMJyBpbiB0aGlzIGRvY3VtZW50IGFyZSB0byBiZSBpbnRlcnByZXRlZCBhcwogICAgZGVzY3JpYmVkIGluIEJDUCAxNCAoUkZDIDIxMTkpIChSRkMgODE3NCkgd2hlbiwgYW5kIG9ubHkgd2hlbiwKICAgIHRoZXkgYXBwZWFyIGluIGFsbCBjYXBpdGFscywgYXMgc2hvd24gaGVyZS4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjIgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3JtcywKICAgIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywKICAgIGFuZCBzdWJqZWN0IHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlCiAgICBSZXZpc2VkIEJTRCBMaWNlbnNlIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUKICAgIElFVEYgVHJ1c3QncyBMZWdhbCBQcm92aXNpb25zIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cHM6Ly90cnVzdGVlLmlldGYub3JnL2xpY2Vuc2UtaW5mbykuCgogICAgVGhpcyB2ZXJzaW9uIG9mIHRoaXMgWUFORyBtb2R1bGUgaXMgcGFydCBvZiBSRkMgOTE3OQogICAgKGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL2luZm8vcmZjOTE3OSk7IHNlZSB0aGUgUkZDIGl0c2VsZgogICAgZm9yIGZ1bGwgbGVnYWwgbm90aWNlcy4iOwoKICAgIHJldmlzaW9uIDIwMjItMDItMTEgewogICAgZGVzY3JpcHRpb24KICAgICAgICAiSW5pdGlhbCBSZXZpc2lvbiI7CiAgICByZWZlcmVuY2UKICAgICAgICAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIGZlYXR1cmUgYWx0ZXJuYXRlLXN5c3RlbXMgewogICAgZGVzY3JpcHRpb24KICAgICAgICAiVGhpcyBmZWF0dXJlIG1lYW5zIHRoZSBkZXZpY2Ugc3VwcG9ydHMgc3BlY2lmeWluZyBsb2NhdGlvbnMKICAgICAgICB1c2luZyBhbHRlcm5hdGUgc3lzdGVtcyBmb3IgcmVmZXJlbmNlIGZyYW1lcy4iOwogICAgfQoKICAgIGdyb3VwaW5nIGdlby1sb2NhdGlvbiB7CiAgICBkZXNjcmlwdGlvbgogICAgICAgICJHcm91cGluZyB0byBpZGVudGlmeSBhIGxvY2F0aW9uIG9uIGFuIGFzdHJvbm9taWNhbCBvYmplY3QuIjsKCiAgICBjb250YWluZXIgZ2VvLWxvY2F0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICJBIGxvY2F0aW9uIG9uIGFuIGFzdHJvbm9taWNhbCBib2R5IChlLmcuLCAnZWFydGgnKQogICAgICAgIHNvbWV3aGVyZSBpbiBhIHVuaXZlcnNlLiI7CgogICAgICAgIGNvbnRhaW5lciByZWZlcmVuY2UtZnJhbWUgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgRnJhbWUgb2YgUmVmZXJlbmNlIGZvciB0aGUgbG9jYXRpb24gdmFsdWVzLiI7CgogICAgICAgIGxlYWYgYWx0ZXJuYXRlLXN5c3RlbSB7CiAgICAgICAgICAgIGlmLWZlYXR1cmUgImFsdGVybmF0ZS1zeXN0ZW1zIjsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgc3lzdGVtIGluIHdoaWNoIHRoZSBhc3Ryb25vbWljYWwgYm9keSBhbmQKICAgICAgICAgICAgZ2VvZGV0aWMtZGF0dW0gaXMgZGVmaW5lZC4gIE5vcm1hbGx5LCB0aGlzIHZhbHVlIGlzIG5vdAogICAgICAgICAgICBwcmVzZW50IGFuZCB0aGUgc3lzdGVtIGlzIHRoZSBuYXR1cmFsIHVuaXZlcnNlOyBob3dldmVyLAogICAgICAgICAgICB3aGVuIHByZXNlbnQsIHRoaXMgdmFsdWUgYWxsb3dzIGZvciBzcGVjaWZ5aW5nIGFsdGVybmF0ZQogICAgICAgICAgICBzeXN0ZW1zIChlLmcuLCB2aXJ0dWFsIHJlYWxpdGllcykuICBBbiBhbHRlcm5hdGUtc3lzdGVtCiAgICAgICAgICAgIG1vZGlmaWVzIHRoZSBkZWZpbml0aW9uIChidXQgbm90IHRoZSB0eXBlKSBvZiB0aGUgb3RoZXIKICAgICAgICAgICAgdmFsdWVzIGluIHRoZSByZWZlcmVuY2UgZnJhbWUuIjsKICAgICAgICB9CiAgICAgICAgbGVhZiBhc3Ryb25vbWljYWwtYm9keSB7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICAgICAgcGF0dGVybiAnWyAtQFxbLVxeXy1+XSonOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlZmF1bHQgImVhcnRoIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIkFuIGFzdHJvbm9taWNhbCBib2R5IGFzIG5hbWVkIGJ5IHRoZSBJbnRlcm5hdGlvbmFsCiAgICAgICAgICAgIEFzdHJvbm9taWNhbCBVbmlvbiAoSUFVKSBvciBhY2NvcmRpbmcgdG8gdGhlIGFsdGVybmF0ZQogICAgICAgICAgICBzeXN0ZW0gaWYgc3BlY2lmaWVkLiAgRXhhbXBsZXMgaW5jbHVkZSAnc3VuJyAob3VyIHN0YXIpLAogICAgICAgICAgICAnZWFydGgnIChvdXIgcGxhbmV0KSwgJ21vb24nIChvdXIgbW9vbiksICdlbmNlbGFkdXMnIChhCiAgICAgICAgICAgIG1vb24gb2YgU2F0dXJuKSwgJ2NlcmVzJyAoYW4gYXN0ZXJvaWQpLCBhbmQKICAgICAgICAgICAgJzY3cC9jaHVyeXVtb3YtZ2VyYXNpbWVua28gKGEgY29tZXQpLiAgVGhlIEFTQ0lJIHZhbHVlCiAgICAgICAgICAgIFNIT1VMRCBoYXZlIHVwcGVyY2FzZSBjb252ZXJ0ZWQgdG8gbG93ZXJjYXNlIGFuZCBub3QKICAgICAgICAgICAgaW5jbHVkZSBjb250cm9sIGNoYXJhY3RlcnMgKGkuZS4sIHZhbHVlcyAzMi4uNjQsIGFuZAogICAgICAgICAgICA5MS4uMTI2KS4gIEFueSBwcmVjZWRpbmcgJ3RoZScgaW4gdGhlIG5hbWUgU0hPVUxEIE5PVCBiZQogICAgICAgICAgICBpbmNsdWRlZC4iOwogICAgICAgICAgICByZWZlcmVuY2UKICAgICAgICAgICAgImh0dHBzOi8vd3d3LmlhdS5vcmcvIjsKICAgICAgICB9CiAgICAgICAgY29udGFpbmVyIGdlb2RldGljLXN5c3RlbSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgZ2VvZGV0aWMgc3lzdGVtIG9mIHRoZSBsb2NhdGlvbiBkYXRhLiI7CiAgICAgICAgICAgIGxlYWYgZ2VvZGV0aWMtZGF0dW0gewogICAgICAgICAgICB0eXBlIHN0cmluZyB7CiAgICAgICAgICAgICAgICBwYXR0ZXJuICdbIC1AXFstXF5fLX5dKic7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJBIGdlb2RldGljLWRhdHVtIGRlZmluaW5nIHRoZSBtZWFuaW5nIG9mIGxhdGl0dWRlLAogICAgICAgICAgICAgICAgbG9uZ2l0dWRlLCBhbmQgaGVpZ2h0LiAgVGhlIGRlZmF1bHQgd2hlbiB0aGUKICAgICAgICAgICAgICAgIGFzdHJvbm9taWNhbCBib2R5IGlzICdlYXJ0aCcgaXMgJ3dncy04NCcsIHdoaWNoIGlzCiAgICAgICAgICAgICAgICB1c2VkIGJ5IHRoZSBHbG9iYWwgUG9zaXRpb25pbmcgU3lzdGVtIChHUFMpLiAgVGhlCiAgICAgICAgICAgICAgICBBU0NJSSB2YWx1ZSBTSE9VTEQgaGF2ZSB1cHBlcmNhc2UgY29udmVydGVkIHRvCiAgICAgICAgICAgICAgICBsb3dlcmNhc2UgYW5kIG5vdCBpbmNsdWRlIGNvbnRyb2wgY2hhcmFjdGVycwogICAgICAgICAgICAgICAgKGkuZS4sIHZhbHVlcyAzMi4uNjQsIGFuZCA5MS4uMTI2KS4gIFRoZSBJQU5BIHJlZ2lzdHJ5CiAgICAgICAgICAgICAgICBmdXJ0aGVyIHJlc3RyaWN0cyB0aGUgdmFsdWUgYnkgY29udmVydGluZyBhbGwgc3BhY2VzCiAgICAgICAgICAgICAgICAoJyAnKSB0byBkYXNoZXMgKCctJykuCiAgICAgICAgICAgICAgICBUaGUgc3BlY2lmaWNhdGlvbiBmb3IgdGhlIGdlb2RldGljLWRhdHVtIGluZGljYXRlcwogICAgICAgICAgICAgICAgaG93IGFjY3VyYXRlbHkgaXQgbW9kZWxzIHRoZSBhc3Ryb25vbWljYWwgYm9keSBpbgogICAgICAgICAgICAgICAgcXVlc3Rpb24sIGJvdGggZm9yIHRoZSAnaG9yaXpvbnRhbCcKICAgICAgICAgICAgICAgIGxhdGl0dWRlL2xvbmdpdHVkZSBjb29yZGluYXRlcyBhbmQgZm9yIGhlaWdodAogICAgICAgICAgICAgICAgY29vcmRpbmF0ZXMuIjsKICAgICAgICAgICAgcmVmZXJlbmNlCiAgICAgICAgICAgICAgICAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMsCiAgICAgICAgICAgICAgICBTZWN0aW9uIDYuMSI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVhZiBjb29yZC1hY2N1cmFjeSB7CiAgICAgICAgICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyA2OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGFjY3VyYWN5IG9mIHRoZSBsYXRpdHVkZS9sb25naXR1ZGUgcGFpciBmb3IKICAgICAgICAgICAgICAgIGVsbGlwc29pZGFsIGNvb3JkaW5hdGVzLCBvciB0aGUgWCwgWSwgYW5kIFogY29tcG9uZW50cwogICAgICAgICAgICAgICAgZm9yIENhcnRlc2lhbiBjb29yZGluYXRlcy4gIFdoZW4gY29vcmQtYWNjdXJhY3kgaXMKICAgICAgICAgICAgICAgIHNwZWNpZmllZCwgaXQgaW5kaWNhdGVzIGhvdyBwcmVjaXNlbHkgdGhlIGNvb3JkaW5hdGVzCiAgICAgICAgICAgICAgICBpbiB0aGUgYXNzb2NpYXRlZCBsaXN0IG9mIGxvY2F0aW9ucyBoYXZlIGJlZW4KICAgICAgICAgICAgICAgIGRldGVybWluZWQgd2l0aCByZXNwZWN0IHRvIHRoZSBjb29yZGluYXRlIHN5c3RlbQogICAgICAgICAgICAgICAgZGVmaW5lZCBieSB0aGUgZ2VvZGV0aWMtZGF0dW0uICBGb3IgZXhhbXBsZSwgdGhlcmUKICAgICAgICAgICAgICAgIG1pZ2h0IGJlIHVuY2VydGFpbnR5IGR1ZSB0byBtZWFzdXJlbWVudCBlcnJvciBpZiBhbgogICAgICAgICAgICAgICAgZXhwZXJpbWVudGFsIG1lYXN1cmVtZW50IHdhcyBtYWRlIHRvIGRldGVybWluZSBlYWNoCiAgICAgICAgICAgICAgICBsb2NhdGlvbi4iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlYWYgaGVpZ2h0LWFjY3VyYWN5IHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGFjY3VyYWN5IG9mIHRoZSBoZWlnaHQgdmFsdWUgZm9yIGVsbGlwc29pZGFsCiAgICAgICAgICAgICAgICBjb29yZGluYXRlczsgdGhpcyB2YWx1ZSBpcyBub3QgdXNlZCB3aXRoIENhcnRlc2lhbgogICAgICAgICAgICAgICAgY29vcmRpbmF0ZXMuICBXaGVuIGhlaWdodC1hY2N1cmFjeSBpcyBzcGVjaWZpZWQsIGl0CiAgICAgICAgICAgICAgICBpbmRpY2F0ZXMgaG93IHByZWNpc2VseSB0aGUgaGVpZ2h0cyBpbiB0aGUKICAgICAgICAgICAgICAgIGFzc29jaWF0ZWQgbGlzdCBvZiBsb2NhdGlvbnMgaGF2ZSBiZWVuIGRldGVybWluZWQKICAgICAgICAgICAgICAgIHdpdGggcmVzcGVjdCB0byB0aGUgY29vcmRpbmF0ZSBzeXN0ZW0gZGVmaW5lZCBieSB0aGUKICAgICAgICAgICAgICAgIGdlb2RldGljLWRhdHVtLiAgRm9yIGV4YW1wbGUsIHRoZXJlIG1pZ2h0IGJlCiAgICAgICAgICAgICAgICB1bmNlcnRhaW50eSBkdWUgdG8gbWVhc3VyZW1lbnQgZXJyb3IgaWYgYW4KICAgICAgICAgICAgICAgIGV4cGVyaW1lbnRhbCBtZWFzdXJlbWVudCB3YXMgbWFkZSB0byBkZXRlcm1pbmUgZWFjaAogICAgICAgICAgICAgICAgbG9jYXRpb24uIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY2hvaWNlIGxvY2F0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhlIGxvY2F0aW9uIGRhdGEgZWl0aGVyIGluIGxhdGl0dWRlL2xvbmdpdHVkZSBvcgogICAgICAgICAgICBDYXJ0ZXNpYW4gdmFsdWVzIjsKICAgICAgICBjYXNlIGVsbGlwc29pZCB7CiAgICAgICAgICAgIGxlYWYgbGF0aXR1ZGUgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgImRlY2ltYWwgZGVncmVlcyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGxhdGl0dWRlIHZhbHVlIG9uIHRoZSBhc3Ryb25vbWljYWwgYm9keS4gIFRoZQogICAgICAgICAgICAgICAgZGVmaW5pdGlvbiBhbmQgcHJlY2lzaW9uIG9mIHRoaXMgbWVhc3VyZW1lbnQgaXMKICAgICAgICAgICAgICAgIGluZGljYXRlZCBieSB0aGUgcmVmZXJlbmNlLWZyYW1lLiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVhZiBsb25naXR1ZGUgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgImRlY2ltYWwgZGVncmVlcyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGxvbmdpdHVkZSB2YWx1ZSBvbiB0aGUgYXN0cm9ub21pY2FsIGJvZHkuICBUaGUKICAgICAgICAgICAgICAgIGRlZmluaXRpb24gYW5kIHByZWNpc2lvbiBvZiB0aGlzIG1lYXN1cmVtZW50IGlzCiAgICAgICAgICAgICAgICBpbmRpY2F0ZWQgYnkgdGhlIHJlZmVyZW5jZS1mcmFtZS4iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlYWYgaGVpZ2h0IHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiSGVpZ2h0IGZyb20gYSByZWZlcmVuY2UgMCB2YWx1ZS4gIFRoZSBwcmVjaXNpb24gYW5kCiAgICAgICAgICAgICAgICAnMCcgdmFsdWUgaXMgZGVmaW5lZCBieSB0aGUgcmVmZXJlbmNlLWZyYW1lLiI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY2FzZSBjYXJ0ZXNpYW4gewogICAgICAgICAgICBsZWFmIHggewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWCB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZWFmIHkgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWSB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZWFmIHogewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWiB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29udGFpbmVyIHZlbG9jaXR5IHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiSWYgdGhlIG9iamVjdCBpcyBpbiBtb3Rpb24sIHRoZSB2ZWxvY2l0eSB2ZWN0b3IgZGVzY3JpYmVzCiAgICAgICAgICAgIHRoaXMgbW90aW9uIGF0IHRoZSB0aW1lIGdpdmVuIGJ5IHRoZSB0aW1lc3RhbXAuICBGb3IgYQogICAgICAgICAgICBmb3JtdWxhIHRvIGNvbnZlcnQgdGhlc2UgdmFsdWVzIHRvIHNwZWVkIGFuZCBoZWFkaW5nLCBzZWUKICAgICAgICAgICAgUkZDIDkxNzkuIjsKICAgICAgICByZWZlcmVuY2UKICAgICAgICAgICAgIlJGQyA5MTc5OiBBIFlBTkcgR3JvdXBpbmcgZm9yIEdlb2dyYXBoaWMgTG9jYXRpb25zIjsKCiAgICAgICAgbGVhZiB2LW5vcnRoIHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyBwZXIgc2Vjb25kIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgInYtbm9ydGggaXMgdGhlIHJhdGUgb2YgY2hhbmdlIChpLmUuLCBzcGVlZCkgdG93YXJkcwogICAgICAgICAgICB0cnVlIG5vcnRoIGFzIGRlZmluZWQgYnkgdGhlIGdlb2RldGljLXN5c3RlbS4iOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB2LWVhc3QgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyAxMjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIHBlciBzZWNvbmQiOwogICAgICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAidi1lYXN0IGlzIHRoZSByYXRlIG9mIGNoYW5nZSAoaS5lLiwgc3BlZWQpIHBlcnBlbmRpY3VsYXIKICAgICAgICAgICAgdG8gdGhlIHJpZ2h0IG9mIHRydWUgbm9ydGggYXMgZGVmaW5lZCBieQogICAgICAgICAgICB0aGUgZ2VvZGV0aWMtc3lzdGVtLiI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHYtdXAgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyAxMjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIHBlciBzZWNvbmQiOwogICAgICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAidi11cCBpcyB0aGUgcmF0ZSBvZiBjaGFuZ2UgKGkuZS4sIHNwZWVkKSBhd2F5IGZyb20gdGhlCiAgICAgICAgICAgIGNlbnRlciBvZiBtYXNzLiI7CiAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZWFmIHRpbWVzdGFtcCB7CiAgICAgICAgdHlwZSB5YW5nOmRhdGUtYW5kLXRpbWU7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIlJlZmVyZW5jZSB0aW1lIHdoZW4gbG9jYXRpb24gd2FzIHJlY29yZGVkLiI7CiAgICAgICAgfQogICAgICAgIGxlYWYgdmFsaWQtdW50aWwgewogICAgICAgIHR5cGUgeWFuZzpkYXRlLWFuZC10aW1lOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgdGltZXN0YW1wIGZvciB3aGljaCB0aGlzIGdlby1sb2NhdGlvbiBpcyB2YWxpZCB1bnRpbC4KICAgICAgICAgICAgSWYgdW5zcGVjaWZpZWQsIHRoZSBnZW8tbG9jYXRpb24gaGFzIG5vIHNwZWNpZmljCiAgICAgICAgICAgIGV4cGlyYXRpb24gdGltZS4iOwogICAgICAgIH0KICAgIH0KICAgIH0KfQo= +ietf-inet-types urn:ietf:params:xml:ns:yang:ietf-inet-types \N [] 2013-07-15 bW9kdWxlIGlldGYtaW5ldC10eXBlcyB7CgogIG5hbWVzcGFjZSAidXJuOmlldGY6cGFyYW1zOnhtbDpuczp5YW5nOmlldGYtaW5ldC10eXBlcyI7CiAgcHJlZml4ICJpbmV0IjsKCiAgb3JnYW5pemF0aW9uCiAgICJJRVRGIE5FVE1PRCAoTkVUQ09ORiBEYXRhIE1vZGVsaW5nIExhbmd1YWdlKSBXb3JraW5nIEdyb3VwIjsKCiAgY29udGFjdAogICAiV0cgV2ViOiAgIDxodHRwOi8vdG9vbHMuaWV0Zi5vcmcvd2cvbmV0bW9kLz4KICAgIFdHIExpc3Q6ICA8bWFpbHRvOm5ldG1vZEBpZXRmLm9yZz4KCiAgICBXRyBDaGFpcjogRGF2aWQgS2Vzc2VucwogICAgICAgICAgICAgIDxtYWlsdG86ZGF2aWQua2Vzc2Vuc0Buc24uY29tPgoKICAgIFdHIENoYWlyOiBKdWVyZ2VuIFNjaG9lbndhZWxkZXIKICAgICAgICAgICAgICA8bWFpbHRvOmouc2Nob2Vud2FlbGRlckBqYWNvYnMtdW5pdmVyc2l0eS5kZT4KCiAgICBFZGl0b3I6ICAgSnVlcmdlbiBTY2hvZW53YWVsZGVyCiAgICAgICAgICAgICAgPG1haWx0bzpqLnNjaG9lbndhZWxkZXJAamFjb2JzLXVuaXZlcnNpdHkuZGU+IjsKCiAgZGVzY3JpcHRpb24KICAgIlRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiBnZW5lcmFsbHkgdXNlZnVsIGRlcml2ZWQKICAgIFlBTkcgZGF0YSB0eXBlcyBmb3IgSW50ZXJuZXQgYWRkcmVzc2VzIGFuZCByZWxhdGVkIHRoaW5ncy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTMgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvcgogICAgd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywgYW5kIHN1YmplY3QKICAgIHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlIFNpbXBsaWZpZWQgQlNEIExpY2Vuc2UKICAgIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUgSUVURiBUcnVzdCdzIExlZ2FsIFByb3Zpc2lvbnMKICAgIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cDovL3RydXN0ZWUuaWV0Zi5vcmcvbGljZW5zZS1pbmZvKS4KCiAgICBUaGlzIHZlcnNpb24gb2YgdGhpcyBZQU5HIG1vZHVsZSBpcyBwYXJ0IG9mIFJGQyA2OTkxOyBzZWUKICAgIHRoZSBSRkMgaXRzZWxmIGZvciBmdWxsIGxlZ2FsIG5vdGljZXMuIjsKCiAgcmV2aXNpb24gMjAxMy0wNy0xNSB7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHJldmlzaW9uIGFkZHMgdGhlIGZvbGxvd2luZyBuZXcgZGF0YSB0eXBlczoKICAgICAgLSBpcC1hZGRyZXNzLW5vLXpvbmUKICAgICAgLSBpcHY0LWFkZHJlc3Mtbm8tem9uZQogICAgICAtIGlwdjYtYWRkcmVzcy1uby16b25lIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjk5MTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICByZXZpc2lvbiAyMDEwLTA5LTI0IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgIkluaXRpYWwgcmV2aXNpb24uIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjAyMTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgdHlwZXMgcmVsYXRlZCB0byBwcm90b2NvbCBmaWVsZHMgKioqLwoKICB0eXBlZGVmIGlwLXZlcnNpb24gewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gdW5rbm93biB7CiAgICAgICAgdmFsdWUgIjAiOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICJBbiB1bmtub3duIG9yIHVuc3BlY2lmaWVkIHZlcnNpb24gb2YgdGhlIEludGVybmV0CiAgICAgICAgICBwcm90b2NvbC4iOwogICAgICB9CiAgICAgIGVudW0gaXB2NCB7CiAgICAgICAgdmFsdWUgIjEiOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICJUaGUgSVB2NCBwcm90b2NvbCBhcyBkZWZpbmVkIGluIFJGQyA3OTEuIjsKICAgICAgfQogICAgICBlbnVtIGlwdjYgewogICAgICAgIHZhbHVlICIyIjsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAiVGhlIElQdjYgcHJvdG9jb2wgYXMgZGVmaW5lZCBpbiBSRkMgMjQ2MC4iOwogICAgICB9CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHZhbHVlIHJlcHJlc2VudHMgdGhlIHZlcnNpb24gb2YgdGhlIElQIHByb3RvY29sLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIEluZXRWZXJzaW9uIHRleHR1YWwgY29udmVudGlvbiBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgIDc5MTogSW50ZXJuZXQgUHJvdG9jb2wKICAgICAgUkZDIDI0NjA6IEludGVybmV0IFByb3RvY29sLCBWZXJzaW9uIDYgKElQdjYpIFNwZWNpZmljYXRpb24KICAgICAgUkZDIDQwMDE6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIEludGVybmV0IE5ldHdvcmsgQWRkcmVzc2VzIjsKICB9CgogIHR5cGVkZWYgZHNjcCB7CiAgICB0eXBlIHVpbnQ4IHsKICAgICAgcmFuZ2UgIjAuLjYzIjsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBkc2NwIHR5cGUgcmVwcmVzZW50cyBhIERpZmZlcmVudGlhdGVkIFNlcnZpY2VzIENvZGUgUG9pbnQKICAgICAgdGhhdCBtYXkgYmUgdXNlZCBmb3IgbWFya2luZyBwYWNrZXRzIGluIGEgdHJhZmZpYyBzdHJlYW0uCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBEc2NwIHRleHR1YWwgY29udmVudGlvbiBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzI4OTogTWFuYWdlbWVudCBJbmZvcm1hdGlvbiBCYXNlIGZvciB0aGUgRGlmZmVyZW50aWF0ZWQKICAgICAgICAgICAgICAgIFNlcnZpY2VzIEFyY2hpdGVjdHVyZQogICAgICBSRkMgMjQ3NDogRGVmaW5pdGlvbiBvZiB0aGUgRGlmZmVyZW50aWF0ZWQgU2VydmljZXMgRmllbGQKICAgICAgICAgICAgICAgIChEUyBGaWVsZCkgaW4gdGhlIElQdjQgYW5kIElQdjYgSGVhZGVycwogICAgICBSRkMgMjc4MDogSUFOQSBBbGxvY2F0aW9uIEd1aWRlbGluZXMgRm9yIFZhbHVlcyBJbgogICAgICAgICAgICAgICAgdGhlIEludGVybmV0IFByb3RvY29sIGFuZCBSZWxhdGVkIEhlYWRlcnMiOwogIH0KCiAgdHlwZWRlZiBpcHY2LWZsb3ctbGFiZWwgewogICAgdHlwZSB1aW50MzIgewogICAgICByYW5nZSAiMC4uMTA0ODU3NSI7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXB2Ni1mbG93LWxhYmVsIHR5cGUgcmVwcmVzZW50cyB0aGUgZmxvdyBpZGVudGlmaWVyIG9yIEZsb3cKICAgICAgTGFiZWwgaW4gYW4gSVB2NiBwYWNrZXQgaGVhZGVyIHRoYXQgbWF5IGJlIHVzZWQgdG8KICAgICAgZGlzY3JpbWluYXRlIHRyYWZmaWMgZmxvd3MuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgSVB2NkZsb3dMYWJlbCB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDM1OTU6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIElQdjYgRmxvdyBMYWJlbAogICAgICBSRkMgMjQ2MDogSW50ZXJuZXQgUHJvdG9jb2wsIFZlcnNpb24gNiAoSVB2NikgU3BlY2lmaWNhdGlvbiI7CiAgfQoKICB0eXBlZGVmIHBvcnQtbnVtYmVyIHsKICAgIHR5cGUgdWludDE2IHsKICAgICAgcmFuZ2UgIjAuLjY1NTM1IjsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBwb3J0LW51bWJlciB0eXBlIHJlcHJlc2VudHMgYSAxNi1iaXQgcG9ydCBudW1iZXIgb2YgYW4KICAgICAgSW50ZXJuZXQgdHJhbnNwb3J0LWxheWVyIHByb3RvY29sIHN1Y2ggYXMgVURQLCBUQ1AsIERDQ1AsIG9yCiAgICAgIFNDVFAuICBQb3J0IG51bWJlcnMgYXJlIGFzc2lnbmVkIGJ5IElBTkEuICBBIGN1cnJlbnQgbGlzdCBvZgogICAgICBhbGwgYXNzaWdubWVudHMgaXMgYXZhaWxhYmxlIGZyb20gPGh0dHA6Ly93d3cuaWFuYS5vcmcvPi4KCiAgICAgIE5vdGUgdGhhdCB0aGUgcG9ydCBudW1iZXIgdmFsdWUgemVybyBpcyByZXNlcnZlZCBieSBJQU5BLiAgSW4KICAgICAgc2l0dWF0aW9ucyB3aGVyZSB0aGUgdmFsdWUgemVybyBkb2VzIG5vdCBtYWtlIHNlbnNlLCBpdCBjYW4KICAgICAgYmUgZXhjbHVkZWQgYnkgc3VidHlwaW5nIHRoZSBwb3J0LW51bWJlciB0eXBlLgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgSW5ldFBvcnROdW1iZXIgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAgNzY4OiBVc2VyIERhdGFncmFtIFByb3RvY29sCiAgICAgIFJGQyAgNzkzOiBUcmFuc21pc3Npb24gQ29udHJvbCBQcm90b2NvbAogICAgICBSRkMgNDk2MDogU3RyZWFtIENvbnRyb2wgVHJhbnNtaXNzaW9uIFByb3RvY29sCiAgICAgIFJGQyA0MzQwOiBEYXRhZ3JhbSBDb25nZXN0aW9uIENvbnRyb2wgUHJvdG9jb2wgKERDQ1ApCiAgICAgIFJGQyA0MDAxOiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBJbnRlcm5ldCBOZXR3b3JrIEFkZHJlc3NlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgdHlwZXMgcmVsYXRlZCB0byBhdXRvbm9tb3VzIHN5c3RlbXMgKioqLwoKICB0eXBlZGVmIGFzLW51bWJlciB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBhcy1udW1iZXIgdHlwZSByZXByZXNlbnRzIGF1dG9ub21vdXMgc3lzdGVtIG51bWJlcnMKICAgICAgd2hpY2ggaWRlbnRpZnkgYW4gQXV0b25vbW91cyBTeXN0ZW0gKEFTKS4gIEFuIEFTIGlzIGEgc2V0CiAgICAgIG9mIHJvdXRlcnMgdW5kZXIgYSBzaW5nbGUgdGVjaG5pY2FsIGFkbWluaXN0cmF0aW9uLCB1c2luZwogICAgICBhbiBpbnRlcmlvciBnYXRld2F5IHByb3RvY29sIGFuZCBjb21tb24gbWV0cmljcyB0byByb3V0ZQogICAgICBwYWNrZXRzIHdpdGhpbiB0aGUgQVMsIGFuZCB1c2luZyBhbiBleHRlcmlvciBnYXRld2F5CiAgICAgIHByb3RvY29sIHRvIHJvdXRlIHBhY2tldHMgdG8gb3RoZXIgQVNlcy4gIElBTkEgbWFpbnRhaW5zCiAgICAgIHRoZSBBUyBudW1iZXIgc3BhY2UgYW5kIGhhcyBkZWxlZ2F0ZWQgbGFyZ2UgcGFydHMgdG8gdGhlCiAgICAgIHJlZ2lvbmFsIHJlZ2lzdHJpZXMuCgogICAgICBBdXRvbm9tb3VzIHN5c3RlbSBudW1iZXJzIHdlcmUgb3JpZ2luYWxseSBsaW1pdGVkIHRvIDE2CiAgICAgIGJpdHMuICBCR1AgZXh0ZW5zaW9ucyBoYXZlIGVubGFyZ2VkIHRoZSBhdXRvbm9tb3VzIHN5c3RlbQogICAgICBudW1iZXIgc3BhY2UgdG8gMzIgYml0cy4gIFRoaXMgdHlwZSB0aGVyZWZvcmUgdXNlcyBhbiB1aW50MzIKICAgICAgYmFzZSB0eXBlIHdpdGhvdXQgYSByYW5nZSByZXN0cmljdGlvbiBpbiBvcmRlciB0byBzdXBwb3J0CiAgICAgIGEgbGFyZ2VyIGF1dG9ub21vdXMgc3lzdGVtIG51bWJlciBzcGFjZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBJbmV0QXV0b25vbW91c1N5c3RlbU51bWJlciB0ZXh0dWFsIGNvbnZlbnRpb24gb2YKICAgICAgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDE5MzA6IEd1aWRlbGluZXMgZm9yIGNyZWF0aW9uLCBzZWxlY3Rpb24sIGFuZCByZWdpc3RyYXRpb24KICAgICAgICAgICAgICAgIG9mIGFuIEF1dG9ub21vdXMgU3lzdGVtIChBUykKICAgICAgUkZDIDQyNzE6IEEgQm9yZGVyIEdhdGV3YXkgUHJvdG9jb2wgNCAoQkdQLTQpCiAgICAgIFJGQyA0MDAxOiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBJbnRlcm5ldCBOZXR3b3JrIEFkZHJlc3NlcwogICAgICBSRkMgNjc5MzogQkdQIFN1cHBvcnQgZm9yIEZvdXItT2N0ZXQgQXV0b25vbW91cyBTeXN0ZW0gKEFTKQogICAgICAgICAgICAgICAgTnVtYmVyIFNwYWNlIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiB0eXBlcyByZWxhdGVkIHRvIElQIGFkZHJlc3NlcyBhbmQgaG9zdG5hbWVzICoqKi8KCiAgdHlwZWRlZiBpcC1hZGRyZXNzIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzOwogICAgICB0eXBlIGluZXQ6aXB2Ni1hZGRyZXNzOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGlwLWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQIGFkZHJlc3MgYW5kIGlzIElQCiAgICAgIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb24KICAgICAgaW1wbGllcyB0aGUgSVAgdmVyc2lvbi4gIFRoaXMgdHlwZSBzdXBwb3J0cyBzY29wZWQgYWRkcmVzc2VzCiAgICAgIGJ5IGFsbG93aW5nIHpvbmUgaWRlbnRpZmllcnMgaW4gdGhlIGFkZHJlc3MgZm9ybWF0LiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDQwMDc6IElQdjYgU2NvcGVkIEFkZHJlc3MgQXJjaGl0ZWN0dXJlIjsKICB9CgogIHR5cGVkZWYgaXB2NC1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybgogICAgICAgICcoKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSlcLil7M30nCiAgICAgICsgICcoWzAtOV18WzEtOV1bMC05XXwxWzAtOV1bMC05XXwyWzAtNF1bMC05XXwyNVswLTVdKScKICAgICAgKyAnKCVbXHB7Tn1ccHtMfV0rKT8nOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIlRoZSBpcHY0LWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQdjQgYWRkcmVzcyBpbgogICAgICAgZG90dGVkLXF1YWQgbm90YXRpb24uICBUaGUgSVB2NCBhZGRyZXNzIG1heSBpbmNsdWRlIGEgem9uZQogICAgICAgaW5kZXgsIHNlcGFyYXRlZCBieSBhICUgc2lnbi4KCiAgICAgICBUaGUgem9uZSBpbmRleCBpcyB1c2VkIHRvIGRpc2FtYmlndWF0ZSBpZGVudGljYWwgYWRkcmVzcwogICAgICAgdmFsdWVzLiAgRm9yIGxpbmstbG9jYWwgYWRkcmVzc2VzLCB0aGUgem9uZSBpbmRleCB3aWxsCiAgICAgICB0eXBpY2FsbHkgYmUgdGhlIGludGVyZmFjZSBpbmRleCBudW1iZXIgb3IgdGhlIG5hbWUgb2YgYW4KICAgICAgIGludGVyZmFjZS4gIElmIHRoZSB6b25lIGluZGV4IGlzIG5vdCBwcmVzZW50LCB0aGUgZGVmYXVsdAogICAgICAgem9uZSBvZiB0aGUgZGV2aWNlIHdpbGwgYmUgdXNlZC4KCiAgICAgICBUaGUgY2Fub25pY2FsIGZvcm1hdCBmb3IgdGhlIHpvbmUgaW5kZXggaXMgdGhlIG51bWVyaWNhbAogICAgICAgZm9ybWF0IjsKICB9CgogIHR5cGVkZWYgaXB2Ni1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKCg6fFswLTlhLWZBLUZdezAsNH0pOikoWzAtOWEtZkEtRl17MCw0fTopezAsNX0nCiAgICAgICAgICAgICsgJygoKFswLTlhLWZBLUZdezAsNH06KT8oOnxbMC05YS1mQS1GXXswLDR9KSl8JwogICAgICAgICAgICArICcoKCgyNVswLTVdfDJbMC00XVswLTldfFswMV0/WzAtOV0/WzAtOV0pXC4pezN9JwogICAgICAgICAgICArICcoMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdP1swLTldP1swLTldKSkpJwogICAgICAgICAgICArICcoJVtccHtOfVxwe0x9XSspPyc7CiAgICAgIHBhdHRlcm4gJygoW146XSs6KXs2fSgoW146XSs6W146XSspfCguKlwuLiopKSl8JwogICAgICAgICAgICArICcoKChbXjpdKzopKlteOl0rKT86OigoW146XSs6KSpbXjpdKyk/KScKICAgICAgICAgICAgKyAnKCUuKyk/JzsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBpcHY2LWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQdjYgYWRkcmVzcyBpbiBmdWxsLAogICAgICBtaXhlZCwgc2hvcnRlbmVkLCBhbmQgc2hvcnRlbmVkLW1peGVkIG5vdGF0aW9uLiAgVGhlIElQdjYKICAgICAgYWRkcmVzcyBtYXkgaW5jbHVkZSBhIHpvbmUgaW5kZXgsIHNlcGFyYXRlZCBieSBhICUgc2lnbi4KCiAgICAgIFRoZSB6b25lIGluZGV4IGlzIHVzZWQgdG8gZGlzYW1iaWd1YXRlIGlkZW50aWNhbCBhZGRyZXNzCiAgICAgIHZhbHVlcy4gIEZvciBsaW5rLWxvY2FsIGFkZHJlc3NlcywgdGhlIHpvbmUgaW5kZXggd2lsbAogICAgICB0eXBpY2FsbHkgYmUgdGhlIGludGVyZmFjZSBpbmRleCBudW1iZXIgb3IgdGhlIG5hbWUgb2YgYW4KICAgICAgaW50ZXJmYWNlLiAgSWYgdGhlIHpvbmUgaW5kZXggaXMgbm90IHByZXNlbnQsIHRoZSBkZWZhdWx0CiAgICAgIHpvbmUgb2YgdGhlIGRldmljZSB3aWxsIGJlIHVzZWQuCgogICAgICBUaGUgY2Fub25pY2FsIGZvcm1hdCBvZiBJUHY2IGFkZHJlc3NlcyB1c2VzIHRoZSB0ZXh0dWFsCiAgICAgIHJlcHJlc2VudGF0aW9uIGRlZmluZWQgaW4gU2VjdGlvbiA0IG9mIFJGQyA1OTUyLiAgVGhlCiAgICAgIGNhbm9uaWNhbCBmb3JtYXQgZm9yIHRoZSB6b25lIGluZGV4IGlzIHRoZSBudW1lcmljYWwKICAgICAgZm9ybWF0IGFzIGRlc2NyaWJlZCBpbiBTZWN0aW9uIDExLjIgb2YgUkZDIDQwMDcuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDI5MTogSVAgVmVyc2lvbiA2IEFkZHJlc3NpbmcgQXJjaGl0ZWN0dXJlCiAgICAgIFJGQyA0MDA3OiBJUHY2IFNjb3BlZCBBZGRyZXNzIEFyY2hpdGVjdHVyZQogICAgICBSRkMgNTk1MjogQSBSZWNvbW1lbmRhdGlvbiBmb3IgSVB2NiBBZGRyZXNzIFRleHQKICAgICAgICAgICAgICAgIFJlcHJlc2VudGF0aW9uIjsKICB9CgogIHR5cGVkZWYgaXAtYWRkcmVzcy1uby16b25lIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzLW5vLXpvbmU7CiAgICAgIHR5cGUgaW5ldDppcHY2LWFkZHJlc3Mtbm8tem9uZTsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBpcC1hZGRyZXNzLW5vLXpvbmUgdHlwZSByZXByZXNlbnRzIGFuIElQIGFkZHJlc3MgYW5kIGlzCiAgICAgIElQIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb24KICAgICAgaW1wbGllcyB0aGUgSVAgdmVyc2lvbi4gIFRoaXMgdHlwZSBkb2VzIG5vdCBzdXBwb3J0IHNjb3BlZAogICAgICBhZGRyZXNzZXMgc2luY2UgaXQgZG9lcyBub3QgYWxsb3cgem9uZSBpZGVudGlmaWVycyBpbiB0aGUKICAgICAgYWRkcmVzcyBmb3JtYXQuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDAwNzogSVB2NiBTY29wZWQgQWRkcmVzcyBBcmNoaXRlY3R1cmUiOwogIH0KCiAgdHlwZWRlZiBpcHY0LWFkZHJlc3Mtbm8tem9uZSB7CiAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzIHsKICAgICAgcGF0dGVybiAnWzAtOVwuXSonOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIkFuIElQdjQgYWRkcmVzcyB3aXRob3V0IGEgem9uZSBpbmRleC4gIFRoaXMgdHlwZSwgZGVyaXZlZCBmcm9tCiAgICAgICBpcHY0LWFkZHJlc3MsIG1heSBiZSB1c2VkIGluIHNpdHVhdGlvbnMgd2hlcmUgdGhlIHpvbmUgaXMKICAgICAgIGtub3duIGZyb20gdGhlIGNvbnRleHQgYW5kIGhlbmNlIG5vIHpvbmUgaW5kZXggaXMgbmVlZGVkLiI7CiAgfQoKICB0eXBlZGVmIGlwdjYtYWRkcmVzcy1uby16b25lIHsKICAgIHR5cGUgaW5ldDppcHY2LWFkZHJlc3MgewogICAgICBwYXR0ZXJuICdbMC05YS1mQS1GOlwuXSonOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIkFuIElQdjYgYWRkcmVzcyB3aXRob3V0IGEgem9uZSBpbmRleC4gIFRoaXMgdHlwZSwgZGVyaXZlZCBmcm9tCiAgICAgICBpcHY2LWFkZHJlc3MsIG1heSBiZSB1c2VkIGluIHNpdHVhdGlvbnMgd2hlcmUgdGhlIHpvbmUgaXMKICAgICAgIGtub3duIGZyb20gdGhlIGNvbnRleHQgYW5kIGhlbmNlIG5vIHpvbmUgaW5kZXggaXMgbmVlZGVkLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDQyOTE6IElQIFZlcnNpb24gNiBBZGRyZXNzaW5nIEFyY2hpdGVjdHVyZQogICAgICBSRkMgNDAwNzogSVB2NiBTY29wZWQgQWRkcmVzcyBBcmNoaXRlY3R1cmUKICAgICAgUkZDIDU5NTI6IEEgUmVjb21tZW5kYXRpb24gZm9yIElQdjYgQWRkcmVzcyBUZXh0CiAgICAgICAgICAgICAgICBSZXByZXNlbnRhdGlvbiI7CiAgfQoKICB0eXBlZGVmIGlwLXByZWZpeCB7CiAgICB0eXBlIHVuaW9uIHsKICAgICAgdHlwZSBpbmV0OmlwdjQtcHJlZml4OwogICAgICB0eXBlIGluZXQ6aXB2Ni1wcmVmaXg7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXAtcHJlZml4IHR5cGUgcmVwcmVzZW50cyBhbiBJUCBwcmVmaXggYW5kIGlzIElQCiAgICAgIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb25zCiAgICAgIGltcGxpZXMgdGhlIElQIHZlcnNpb24uIjsKICB9CgogIHR5cGVkZWYgaXB2NC1wcmVmaXggewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuCiAgICAgICAgICcoKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSlcLil7M30nCiAgICAgICArICAnKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSknCiAgICAgICArICcvKChbMC05XSl8KFsxLTJdWzAtOV0pfCgzWzAtMl0pKSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXB2NC1wcmVmaXggdHlwZSByZXByZXNlbnRzIGFuIElQdjQgYWRkcmVzcyBwcmVmaXguCiAgICAgIFRoZSBwcmVmaXggbGVuZ3RoIGlzIGdpdmVuIGJ5IHRoZSBudW1iZXIgZm9sbG93aW5nIHRoZQogICAgICBzbGFzaCBjaGFyYWN0ZXIgYW5kIG11c3QgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDMyLgoKICAgICAgQSBwcmVmaXggbGVuZ3RoIHZhbHVlIG9mIG4gY29ycmVzcG9uZHMgdG8gYW4gSVAgYWRkcmVzcwogICAgICBtYXNrIHRoYXQgaGFzIG4gY29udGlndW91cyAxLWJpdHMgZnJvbSB0aGUgbW9zdAogICAgICBzaWduaWZpY2FudCBiaXQgKE1TQikgYW5kIGFsbCBvdGhlciBiaXRzIHNldCB0byAwLgoKICAgICAgVGhlIGNhbm9uaWNhbCBmb3JtYXQgb2YgYW4gSVB2NCBwcmVmaXggaGFzIGFsbCBiaXRzIG9mCiAgICAgIHRoZSBJUHY0IGFkZHJlc3Mgc2V0IHRvIHplcm8gdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlCiAgICAgIElQdjQgcHJlZml4LiI7CiAgfQoKICB0eXBlZGVmIGlwdjYtcHJlZml4IHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKCg6fFswLTlhLWZBLUZdezAsNH0pOikoWzAtOWEtZkEtRl17MCw0fTopezAsNX0nCiAgICAgICAgICAgICsgJygoKFswLTlhLWZBLUZdezAsNH06KT8oOnxbMC05YS1mQS1GXXswLDR9KSl8JwogICAgICAgICAgICArICcoKCgyNVswLTVdfDJbMC00XVswLTldfFswMV0/WzAtOV0/WzAtOV0pXC4pezN9JwogICAgICAgICAgICArICcoMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdP1swLTldP1swLTldKSkpJwogICAgICAgICAgICArICcoLygoWzAtOV0pfChbMC05XXsyfSl8KDFbMC0xXVswLTldKXwoMTJbMC04XSkpKSc7CiAgICAgIHBhdHRlcm4gJygoW146XSs6KXs2fSgoW146XSs6W146XSspfCguKlwuLiopKSl8JwogICAgICAgICAgICArICcoKChbXjpdKzopKlteOl0rKT86OigoW146XSs6KSpbXjpdKyk/KScKICAgICAgICAgICAgKyAnKC8uKyknOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGlwdjYtcHJlZml4IHR5cGUgcmVwcmVzZW50cyBhbiBJUHY2IGFkZHJlc3MgcHJlZml4LgogICAgICBUaGUgcHJlZml4IGxlbmd0aCBpcyBnaXZlbiBieSB0aGUgbnVtYmVyIGZvbGxvd2luZyB0aGUKICAgICAgc2xhc2ggY2hhcmFjdGVyIGFuZCBtdXN0IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byAxMjguCgogICAgICBBIHByZWZpeCBsZW5ndGggdmFsdWUgb2YgbiBjb3JyZXNwb25kcyB0byBhbiBJUCBhZGRyZXNzCiAgICAgIG1hc2sgdGhhdCBoYXMgbiBjb250aWd1b3VzIDEtYml0cyBmcm9tIHRoZSBtb3N0CiAgICAgIHNpZ25pZmljYW50IGJpdCAoTVNCKSBhbmQgYWxsIG90aGVyIGJpdHMgc2V0IHRvIDAuCgogICAgICBUaGUgSVB2NiBhZGRyZXNzIHNob3VsZCBoYXZlIGFsbCBiaXRzIHRoYXQgZG8gbm90IGJlbG9uZwogICAgICB0byB0aGUgcHJlZml4IHNldCB0byB6ZXJvLgoKICAgICAgVGhlIGNhbm9uaWNhbCBmb3JtYXQgb2YgYW4gSVB2NiBwcmVmaXggaGFzIGFsbCBiaXRzIG9mCiAgICAgIHRoZSBJUHY2IGFkZHJlc3Mgc2V0IHRvIHplcm8gdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlCiAgICAgIElQdjYgcHJlZml4LiAgRnVydGhlcm1vcmUsIHRoZSBJUHY2IGFkZHJlc3MgaXMgcmVwcmVzZW50ZWQKICAgICAgYXMgZGVmaW5lZCBpbiBTZWN0aW9uIDQgb2YgUkZDIDU5NTIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNTk1MjogQSBSZWNvbW1lbmRhdGlvbiBmb3IgSVB2NiBBZGRyZXNzIFRleHQKICAgICAgICAgICAgICAgIFJlcHJlc2VudGF0aW9uIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBkb21haW4gbmFtZSBhbmQgVVJJIHR5cGVzICoqKi8KCiAgdHlwZWRlZiBkb21haW4tbmFtZSB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIGxlbmd0aCAiMS4uMjUzIjsKICAgICAgcGF0dGVybgogICAgICAgICcoKChbYS16QS1aMC05X10oW2EtekEtWjAtOVwtX10pezAsNjF9KT9bYS16QS1aMC05XVwuKSonCiAgICAgICsgJyhbYS16QS1aMC05X10oW2EtekEtWjAtOVwtX10pezAsNjF9KT9bYS16QS1aMC05XVwuPyknCiAgICAgICsgJ3xcLic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgZG9tYWluLW5hbWUgdHlwZSByZXByZXNlbnRzIGEgRE5TIGRvbWFpbiBuYW1lLiAgVGhlCiAgICAgIG5hbWUgU0hPVUxEIGJlIGZ1bGx5IHF1YWxpZmllZCB3aGVuZXZlciBwb3NzaWJsZS4KCiAgICAgIEludGVybmV0IGRvbWFpbiBuYW1lcyBhcmUgb25seSBsb29zZWx5IHNwZWNpZmllZC4gIFNlY3Rpb24KICAgICAgMy41IG9mIFJGQyAxMDM0IHJlY29tbWVuZHMgYSBzeW50YXggKG1vZGlmaWVkIGluIFNlY3Rpb24KICAgICAgMi4xIG9mIFJGQyAxMTIzKS4gIFRoZSBwYXR0ZXJuIGFib3ZlIGlzIGludGVuZGVkIHRvIGFsbG93CiAgICAgIGZvciBjdXJyZW50IHByYWN0aWNlIGluIGRvbWFpbiBuYW1lIHVzZSwgYW5kIHNvbWUgcG9zc2libGUKICAgICAgZnV0dXJlIGV4cGFuc2lvbi4gIEl0IGlzIGRlc2lnbmVkIHRvIGhvbGQgdmFyaW91cyB0eXBlcyBvZgogICAgICBkb21haW4gbmFtZXMsIGluY2x1ZGluZyBuYW1lcyB1c2VkIGZvciBBIG9yIEFBQUEgcmVjb3JkcwogICAgICAoaG9zdCBuYW1lcykgYW5kIG90aGVyIHJlY29yZHMsIHN1Y2ggYXMgU1JWIHJlY29yZHMuICBOb3RlCiAgICAgIHRoYXQgSW50ZXJuZXQgaG9zdCBuYW1lcyBoYXZlIGEgc3RyaWN0ZXIgc3ludGF4IChkZXNjcmliZWQKICAgICAgaW4gUkZDIDk1MikgdGhhbiB0aGUgRE5TIHJlY29tbWVuZGF0aW9ucyBpbiBSRkNzIDEwMzQgYW5kCiAgICAgIDExMjMsIGFuZCB0aGF0IHN5c3RlbXMgdGhhdCB3YW50IHRvIHN0b3JlIGhvc3QgbmFtZXMgaW4KICAgICAgc2NoZW1hIG5vZGVzIHVzaW5nIHRoZSBkb21haW4tbmFtZSB0eXBlIGFyZSByZWNvbW1lbmRlZCB0bwogICAgICBhZGhlcmUgdG8gdGhpcyBzdHJpY3RlciBzdGFuZGFyZCB0byBlbnN1cmUgaW50ZXJvcGVyYWJpbGl0eS4KCiAgICAgIFRoZSBlbmNvZGluZyBvZiBETlMgbmFtZXMgaW4gdGhlIEROUyBwcm90b2NvbCBpcyBsaW1pdGVkCiAgICAgIHRvIDI1NSBjaGFyYWN0ZXJzLiAgU2luY2UgdGhlIGVuY29kaW5nIGNvbnNpc3RzIG9mIGxhYmVscwogICAgICBwcmVmaXhlZCBieSBhIGxlbmd0aCBieXRlcyBhbmQgdGhlcmUgaXMgYSB0cmFpbGluZyBOVUxMCiAgICAgIGJ5dGUsIG9ubHkgMjUzIGNoYXJhY3RlcnMgY2FuIGFwcGVhciBpbiB0aGUgdGV4dHVhbCBkb3R0ZWQKICAgICAgbm90YXRpb24uCgogICAgICBUaGUgZGVzY3JpcHRpb24gY2xhdXNlIG9mIHNjaGVtYSBub2RlcyB1c2luZyB0aGUgZG9tYWluLW5hbWUKICAgICAgdHlwZSBNVVNUIGRlc2NyaWJlIHdoZW4gYW5kIGhvdyB0aGVzZSBuYW1lcyBhcmUgcmVzb2x2ZWQgdG8KICAgICAgSVAgYWRkcmVzc2VzLiAgTm90ZSB0aGF0IHRoZSByZXNvbHV0aW9uIG9mIGEgZG9tYWluLW5hbWUgdmFsdWUKICAgICAgbWF5IHJlcXVpcmUgdG8gcXVlcnkgbXVsdGlwbGUgRE5TIHJlY29yZHMgKGUuZy4sIEEgZm9yIElQdjQKICAgICAgYW5kIEFBQUEgZm9yIElQdjYpLiAgVGhlIG9yZGVyIG9mIHRoZSByZXNvbHV0aW9uIHByb2Nlc3MgYW5kCiAgICAgIHdoaWNoIEROUyByZWNvcmQgdGFrZXMgcHJlY2VkZW5jZSBjYW4gZWl0aGVyIGJlIGRlZmluZWQKICAgICAgZXhwbGljaXRseSBvciBtYXkgZGVwZW5kIG9uIHRoZSBjb25maWd1cmF0aW9uIG9mIHRoZQogICAgICByZXNvbHZlci4KCiAgICAgIERvbWFpbi1uYW1lIHZhbHVlcyB1c2UgdGhlIFVTLUFTQ0lJIGVuY29kaW5nLiAgVGhlaXIgY2Fub25pY2FsCiAgICAgIGZvcm1hdCB1c2VzIGxvd2VyY2FzZSBVUy1BU0NJSSBjaGFyYWN0ZXJzLiAgSW50ZXJuYXRpb25hbGl6ZWQKICAgICAgZG9tYWluIG5hbWVzIE1VU1QgYmUgQS1sYWJlbHMgYXMgcGVyIFJGQyA1ODkwLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDICA5NTI6IERvRCBJbnRlcm5ldCBIb3N0IFRhYmxlIFNwZWNpZmljYXRpb24KICAgICAgUkZDIDEwMzQ6IERvbWFpbiBOYW1lcyAtIENvbmNlcHRzIGFuZCBGYWNpbGl0aWVzCiAgICAgIFJGQyAxMTIzOiBSZXF1aXJlbWVudHMgZm9yIEludGVybmV0IEhvc3RzIC0tIEFwcGxpY2F0aW9uCiAgICAgICAgICAgICAgICBhbmQgU3VwcG9ydAogICAgICBSRkMgMjc4MjogQSBETlMgUlIgZm9yIHNwZWNpZnlpbmcgdGhlIGxvY2F0aW9uIG9mIHNlcnZpY2VzCiAgICAgICAgICAgICAgICAoRE5TIFNSVikKICAgICAgUkZDIDU4OTA6IEludGVybmF0aW9uYWxpemVkIERvbWFpbiBOYW1lcyBpbiBBcHBsaWNhdGlvbnMKICAgICAgICAgICAgICAgIChJRE5BKTogRGVmaW5pdGlvbnMgYW5kIERvY3VtZW50IEZyYW1ld29yayI7CiAgfQoKICB0eXBlZGVmIGhvc3QgewogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgaW5ldDppcC1hZGRyZXNzOwogICAgICB0eXBlIGluZXQ6ZG9tYWluLW5hbWU7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaG9zdCB0eXBlIHJlcHJlc2VudHMgZWl0aGVyIGFuIElQIGFkZHJlc3Mgb3IgYSBETlMKICAgICAgZG9tYWluIG5hbWUuIjsKICB9CgogIHR5cGVkZWYgdXJpIHsKICAgIHR5cGUgc3RyaW5nOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIHVyaSB0eXBlIHJlcHJlc2VudHMgYSBVbmlmb3JtIFJlc291cmNlIElkZW50aWZpZXIKICAgICAgKFVSSSkgYXMgZGVmaW5lZCBieSBTVEQgNjYuCgogICAgICBPYmplY3RzIHVzaW5nIHRoZSB1cmkgdHlwZSBNVVNUIGJlIGluIFVTLUFTQ0lJIGVuY29kaW5nLAogICAgICBhbmQgTVVTVCBiZSBub3JtYWxpemVkIGFzIGRlc2NyaWJlZCBieSBSRkMgMzk4NiBTZWN0aW9ucwogICAgICA2LjIuMSwgNi4yLjIuMSwgYW5kIDYuMi4yLjIuICBBbGwgdW5uZWNlc3NhcnkKICAgICAgcGVyY2VudC1lbmNvZGluZyBpcyByZW1vdmVkLCBhbmQgYWxsIGNhc2UtaW5zZW5zaXRpdmUKICAgICAgY2hhcmFjdGVycyBhcmUgc2V0IHRvIGxvd2VyY2FzZSBleGNlcHQgZm9yIGhleGFkZWNpbWFsCiAgICAgIGRpZ2l0cywgd2hpY2ggYXJlIG5vcm1hbGl6ZWQgdG8gdXBwZXJjYXNlIGFzIGRlc2NyaWJlZCBpbgogICAgICBTZWN0aW9uIDYuMi4yLjEuCgogICAgICBUaGUgcHVycG9zZSBvZiB0aGlzIG5vcm1hbGl6YXRpb24gaXMgdG8gaGVscCBwcm92aWRlCiAgICAgIHVuaXF1ZSBVUklzLiAgTm90ZSB0aGF0IHRoaXMgbm9ybWFsaXphdGlvbiBpcyBub3QKICAgICAgc3VmZmljaWVudCB0byBwcm92aWRlIHVuaXF1ZW5lc3MuICBUd28gVVJJcyB0aGF0IGFyZQogICAgICB0ZXh0dWFsbHkgZGlzdGluY3QgYWZ0ZXIgdGhpcyBub3JtYWxpemF0aW9uIG1heSBzdGlsbCBiZQogICAgICBlcXVpdmFsZW50LgoKICAgICAgT2JqZWN0cyB1c2luZyB0aGUgdXJpIHR5cGUgbWF5IHJlc3RyaWN0IHRoZSBzY2hlbWVzIHRoYXQKICAgICAgdGhleSBwZXJtaXQuICBGb3IgZXhhbXBsZSwgJ2RhdGE6JyBhbmQgJ3VybjonIHNjaGVtZXMKICAgICAgbWlnaHQgbm90IGJlIGFwcHJvcHJpYXRlLgoKICAgICAgQSB6ZXJvLWxlbmd0aCBVUkkgaXMgbm90IGEgdmFsaWQgVVJJLiAgVGhpcyBjYW4gYmUgdXNlZCB0bwogICAgICBleHByZXNzICdVUkkgYWJzZW50JyB3aGVyZSByZXF1aXJlZC4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBVcmkgU01JdjIgdGV4dHVhbCBjb252ZW50aW9uIGRlZmluZWQgaW4gUkZDIDUwMTcuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzk4NjogVW5pZm9ybSBSZXNvdXJjZSBJZGVudGlmaWVyIChVUkkpOiBHZW5lcmljIFN5bnRheAogICAgICBSRkMgMzMwNTogUmVwb3J0IGZyb20gdGhlIEpvaW50IFczQy9JRVRGIFVSSSBQbGFubmluZyBJbnRlcmVzdAogICAgICAgICAgICAgICAgR3JvdXA6IFVuaWZvcm0gUmVzb3VyY2UgSWRlbnRpZmllcnMgKFVSSXMpLCBVUkxzLAogICAgICAgICAgICAgICAgYW5kIFVuaWZvcm0gUmVzb3VyY2UgTmFtZXMgKFVSTnMpOiBDbGFyaWZpY2F0aW9ucwogICAgICAgICAgICAgICAgYW5kIFJlY29tbWVuZGF0aW9ucwogICAgICBSRkMgNTAxNzogTUlCIFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFVuaWZvcm0gUmVzb3VyY2UKICAgICAgICAgICAgICAgIElkZW50aWZpZXJzIChVUklzKSI7CiAgfQoKfQ== +ietf-yang-types urn:ietf:params:xml:ns:yang:ietf-yang-types \N [] 2013-07-15 bW9kdWxlIGlldGYteWFuZy10eXBlcyB7CgogIG5hbWVzcGFjZSAidXJuOmlldGY6cGFyYW1zOnhtbDpuczp5YW5nOmlldGYteWFuZy10eXBlcyI7CiAgcHJlZml4ICJ5YW5nIjsKCiAgb3JnYW5pemF0aW9uCiAgICJJRVRGIE5FVE1PRCAoTkVUQ09ORiBEYXRhIE1vZGVsaW5nIExhbmd1YWdlKSBXb3JraW5nIEdyb3VwIjsKCiAgY29udGFjdAogICAiV0cgV2ViOiAgIDxodHRwOi8vdG9vbHMuaWV0Zi5vcmcvd2cvbmV0bW9kLz4KICAgIFdHIExpc3Q6ICA8bWFpbHRvOm5ldG1vZEBpZXRmLm9yZz4KCiAgICBXRyBDaGFpcjogRGF2aWQgS2Vzc2VucwogICAgICAgICAgICAgIDxtYWlsdG86ZGF2aWQua2Vzc2Vuc0Buc24uY29tPgoKICAgIFdHIENoYWlyOiBKdWVyZ2VuIFNjaG9lbndhZWxkZXIKICAgICAgICAgICAgICA8bWFpbHRvOmouc2Nob2Vud2FlbGRlckBqYWNvYnMtdW5pdmVyc2l0eS5kZT4KCiAgICBFZGl0b3I6ICAgSnVlcmdlbiBTY2hvZW53YWVsZGVyCiAgICAgICAgICAgICAgPG1haWx0bzpqLnNjaG9lbndhZWxkZXJAamFjb2JzLXVuaXZlcnNpdHkuZGU+IjsKCiAgZGVzY3JpcHRpb24KICAgIlRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiBnZW5lcmFsbHkgdXNlZnVsIGRlcml2ZWQKICAgIFlBTkcgZGF0YSB0eXBlcy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTMgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvcgogICAgd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywgYW5kIHN1YmplY3QKICAgIHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlIFNpbXBsaWZpZWQgQlNEIExpY2Vuc2UKICAgIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUgSUVURiBUcnVzdCdzIExlZ2FsIFByb3Zpc2lvbnMKICAgIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cDovL3RydXN0ZWUuaWV0Zi5vcmcvbGljZW5zZS1pbmZvKS4KCiAgICBUaGlzIHZlcnNpb24gb2YgdGhpcyBZQU5HIG1vZHVsZSBpcyBwYXJ0IG9mIFJGQyA2OTkxOyBzZWUKICAgIHRoZSBSRkMgaXRzZWxmIGZvciBmdWxsIGxlZ2FsIG5vdGljZXMuIjsKCiAgcmV2aXNpb24gMjAxMy0wNy0xNSB7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHJldmlzaW9uIGFkZHMgdGhlIGZvbGxvd2luZyBuZXcgZGF0YSB0eXBlczoKICAgICAgLSB5YW5nLWlkZW50aWZpZXIKICAgICAgLSBoZXgtc3RyaW5nCiAgICAgIC0gdXVpZAogICAgICAtIGRvdHRlZC1xdWFkIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjk5MTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICByZXZpc2lvbiAyMDEwLTA5LTI0IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgIkluaXRpYWwgcmV2aXNpb24uIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjAyMTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgY291bnRlciBhbmQgZ2F1Z2UgdHlwZXMgKioqLwoKICB0eXBlZGVmIGNvdW50ZXIzMiB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBjb3VudGVyMzIgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIKICAgICAgdGhhdCBtb25vdG9uaWNhbGx5IGluY3JlYXNlcyB1bnRpbCBpdCByZWFjaGVzIGEKICAgICAgbWF4aW11bSB2YWx1ZSBvZiAyXjMyLTEgKDQyOTQ5NjcyOTUgZGVjaW1hbCksIHdoZW4gaXQKICAgICAgd3JhcHMgYXJvdW5kIGFuZCBzdGFydHMgaW5jcmVhc2luZyBhZ2FpbiBmcm9tIHplcm8uCgogICAgICBDb3VudGVycyBoYXZlIG5vIGRlZmluZWQgJ2luaXRpYWwnIHZhbHVlLCBhbmQgdGh1cywgYQogICAgICBzaW5nbGUgdmFsdWUgb2YgYSBjb3VudGVyIGhhcyAoaW4gZ2VuZXJhbCkgbm8gaW5mb3JtYXRpb24KICAgICAgY29udGVudC4gIERpc2NvbnRpbnVpdGllcyBpbiB0aGUgbW9ub3RvbmljYWxseSBpbmNyZWFzaW5nCiAgICAgIHZhbHVlIG5vcm1hbGx5IG9jY3VyIGF0IHJlLWluaXRpYWxpemF0aW9uIG9mIHRoZQogICAgICBtYW5hZ2VtZW50IHN5c3RlbSwgYW5kIGF0IG90aGVyIHRpbWVzIGFzIHNwZWNpZmllZCBpbiB0aGUKICAgICAgZGVzY3JpcHRpb24gb2YgYSBzY2hlbWEgbm9kZSB1c2luZyB0aGlzIHR5cGUuICBJZiBzdWNoCiAgICAgIG90aGVyIHRpbWVzIGNhbiBvY2N1ciwgZm9yIGV4YW1wbGUsIHRoZSBjcmVhdGlvbiBvZgogICAgICBhIHNjaGVtYSBub2RlIG9mIHR5cGUgY291bnRlcjMyIGF0IHRpbWVzIG90aGVyIHRoYW4KICAgICAgcmUtaW5pdGlhbGl6YXRpb24sIHRoZW4gYSBjb3JyZXNwb25kaW5nIHNjaGVtYSBub2RlCiAgICAgIHNob3VsZCBiZSBkZWZpbmVkLCB3aXRoIGFuIGFwcHJvcHJpYXRlIHR5cGUsIHRvIGluZGljYXRlCiAgICAgIHRoZSBsYXN0IGRpc2NvbnRpbnVpdHkuCgogICAgICBUaGUgY291bnRlcjMyIHR5cGUgc2hvdWxkIG5vdCBiZSB1c2VkIGZvciBjb25maWd1cmF0aW9uCiAgICAgIHNjaGVtYSBub2Rlcy4gIEEgZGVmYXVsdCBzdGF0ZW1lbnQgU0hPVUxEIE5PVCBiZSB1c2VkIGluCiAgICAgIGNvbWJpbmF0aW9uIHdpdGggdGhlIHR5cGUgY291bnRlcjMyLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIENvdW50ZXIzMiB0eXBlIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyNTc4OiBTdHJ1Y3R1cmUgb2YgTWFuYWdlbWVudCBJbmZvcm1hdGlvbiBWZXJzaW9uIDIKICAgICAgICAgICAgICAgIChTTUl2MikiOwogIH0KCiAgdHlwZWRlZiB6ZXJvLWJhc2VkLWNvdW50ZXIzMiB7CiAgICB0eXBlIHlhbmc6Y291bnRlcjMyOwogICAgZGVmYXVsdCAiMCI7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgemVyby1iYXNlZC1jb3VudGVyMzIgdHlwZSByZXByZXNlbnRzIGEgY291bnRlcjMyCiAgICAgIHRoYXQgaGFzIHRoZSBkZWZpbmVkICdpbml0aWFsJyB2YWx1ZSB6ZXJvLgoKICAgICAgQSBzY2hlbWEgbm9kZSBvZiB0aGlzIHR5cGUgd2lsbCBiZSBzZXQgdG8gemVybyAoMCkgb24gY3JlYXRpb24KICAgICAgYW5kIHdpbGwgdGhlcmVhZnRlciBpbmNyZWFzZSBtb25vdG9uaWNhbGx5IHVudGlsIGl0IHJlYWNoZXMKICAgICAgYSBtYXhpbXVtIHZhbHVlIG9mIDJeMzItMSAoNDI5NDk2NzI5NSBkZWNpbWFsKSwgd2hlbiBpdAogICAgICB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIFByb3ZpZGVkIHRoYXQgYW4gYXBwbGljYXRpb24gZGlzY292ZXJzIGEgbmV3IHNjaGVtYSBub2RlCiAgICAgIG9mIHRoaXMgdHlwZSB3aXRoaW4gdGhlIG1pbmltdW0gdGltZSB0byB3cmFwLCBpdCBjYW4gdXNlIHRoZQogICAgICAnaW5pdGlhbCcgdmFsdWUgYXMgYSBkZWx0YS4gIEl0IGlzIGltcG9ydGFudCBmb3IgYSBtYW5hZ2VtZW50CiAgICAgIHN0YXRpb24gdG8gYmUgYXdhcmUgb2YgdGhpcyBtaW5pbXVtIHRpbWUgYW5kIHRoZSBhY3R1YWwgdGltZQogICAgICBiZXR3ZWVuIHBvbGxzLCBhbmQgdG8gZGlzY2FyZCBkYXRhIGlmIHRoZSBhY3R1YWwgdGltZSBpcyB0b28KICAgICAgbG9uZyBvciB0aGVyZSBpcyBubyBkZWZpbmVkIG1pbmltdW0gdGltZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBaZXJvQmFzZWRDb3VudGVyMzIgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgICJSRkMgNDUwMjogUmVtb3RlIE5ldHdvcmsgTW9uaXRvcmluZyBNYW5hZ2VtZW50IEluZm9ybWF0aW9uCiAgICAgICAgICAgICAgICAgQmFzZSBWZXJzaW9uIDIiOwogIH0KCiAgdHlwZWRlZiBjb3VudGVyNjQgewogICAgdHlwZSB1aW50NjQ7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgY291bnRlcjY0IHR5cGUgcmVwcmVzZW50cyBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyCiAgICAgIHRoYXQgbW9ub3RvbmljYWxseSBpbmNyZWFzZXMgdW50aWwgaXQgcmVhY2hlcyBhCiAgICAgIG1heGltdW0gdmFsdWUgb2YgMl42NC0xICgxODQ0Njc0NDA3MzcwOTU1MTYxNSBkZWNpbWFsKSwKICAgICAgd2hlbiBpdCB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIENvdW50ZXJzIGhhdmUgbm8gZGVmaW5lZCAnaW5pdGlhbCcgdmFsdWUsIGFuZCB0aHVzLCBhCiAgICAgIHNpbmdsZSB2YWx1ZSBvZiBhIGNvdW50ZXIgaGFzIChpbiBnZW5lcmFsKSBubyBpbmZvcm1hdGlvbgogICAgICBjb250ZW50LiAgRGlzY29udGludWl0aWVzIGluIHRoZSBtb25vdG9uaWNhbGx5IGluY3JlYXNpbmcKICAgICAgdmFsdWUgbm9ybWFsbHkgb2NjdXIgYXQgcmUtaW5pdGlhbGl6YXRpb24gb2YgdGhlCiAgICAgIG1hbmFnZW1lbnQgc3lzdGVtLCBhbmQgYXQgb3RoZXIgdGltZXMgYXMgc3BlY2lmaWVkIGluIHRoZQogICAgICBkZXNjcmlwdGlvbiBvZiBhIHNjaGVtYSBub2RlIHVzaW5nIHRoaXMgdHlwZS4gIElmIHN1Y2gKICAgICAgb3RoZXIgdGltZXMgY2FuIG9jY3VyLCBmb3IgZXhhbXBsZSwgdGhlIGNyZWF0aW9uIG9mCiAgICAgIGEgc2NoZW1hIG5vZGUgb2YgdHlwZSBjb3VudGVyNjQgYXQgdGltZXMgb3RoZXIgdGhhbgogICAgICByZS1pbml0aWFsaXphdGlvbiwgdGhlbiBhIGNvcnJlc3BvbmRpbmcgc2NoZW1hIG5vZGUKICAgICAgc2hvdWxkIGJlIGRlZmluZWQsIHdpdGggYW4gYXBwcm9wcmlhdGUgdHlwZSwgdG8gaW5kaWNhdGUKICAgICAgdGhlIGxhc3QgZGlzY29udGludWl0eS4KCiAgICAgIFRoZSBjb3VudGVyNjQgdHlwZSBzaG91bGQgbm90IGJlIHVzZWQgZm9yIGNvbmZpZ3VyYXRpb24KICAgICAgc2NoZW1hIG5vZGVzLiAgQSBkZWZhdWx0IHN0YXRlbWVudCBTSE9VTEQgTk9UIGJlIHVzZWQgaW4KICAgICAgY29tYmluYXRpb24gd2l0aCB0aGUgdHlwZSBjb3VudGVyNjQuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgQ291bnRlcjY0IHR5cGUgb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDI1Nzg6IFN0cnVjdHVyZSBvZiBNYW5hZ2VtZW50IEluZm9ybWF0aW9uIFZlcnNpb24gMgogICAgICAgICAgICAgICAgKFNNSXYyKSI7CiAgfQoKICB0eXBlZGVmIHplcm8tYmFzZWQtY291bnRlcjY0IHsKICAgIHR5cGUgeWFuZzpjb3VudGVyNjQ7CiAgICBkZWZhdWx0ICIwIjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSB6ZXJvLWJhc2VkLWNvdW50ZXI2NCB0eXBlIHJlcHJlc2VudHMgYSBjb3VudGVyNjQgdGhhdAogICAgICBoYXMgdGhlIGRlZmluZWQgJ2luaXRpYWwnIHZhbHVlIHplcm8uCgoKCgogICAgICBBIHNjaGVtYSBub2RlIG9mIHRoaXMgdHlwZSB3aWxsIGJlIHNldCB0byB6ZXJvICgwKSBvbiBjcmVhdGlvbgogICAgICBhbmQgd2lsbCB0aGVyZWFmdGVyIGluY3JlYXNlIG1vbm90b25pY2FsbHkgdW50aWwgaXQgcmVhY2hlcwogICAgICBhIG1heGltdW0gdmFsdWUgb2YgMl42NC0xICgxODQ0Njc0NDA3MzcwOTU1MTYxNSBkZWNpbWFsKSwKICAgICAgd2hlbiBpdCB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIFByb3ZpZGVkIHRoYXQgYW4gYXBwbGljYXRpb24gZGlzY292ZXJzIGEgbmV3IHNjaGVtYSBub2RlCiAgICAgIG9mIHRoaXMgdHlwZSB3aXRoaW4gdGhlIG1pbmltdW0gdGltZSB0byB3cmFwLCBpdCBjYW4gdXNlIHRoZQogICAgICAnaW5pdGlhbCcgdmFsdWUgYXMgYSBkZWx0YS4gIEl0IGlzIGltcG9ydGFudCBmb3IgYSBtYW5hZ2VtZW50CiAgICAgIHN0YXRpb24gdG8gYmUgYXdhcmUgb2YgdGhpcyBtaW5pbXVtIHRpbWUgYW5kIHRoZSBhY3R1YWwgdGltZQogICAgICBiZXR3ZWVuIHBvbGxzLCBhbmQgdG8gZGlzY2FyZCBkYXRhIGlmIHRoZSBhY3R1YWwgdGltZSBpcyB0b28KICAgICAgbG9uZyBvciB0aGVyZSBpcyBubyBkZWZpbmVkIG1pbmltdW0gdGltZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBaZXJvQmFzZWRDb3VudGVyNjQgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyODU2OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBBZGRpdGlvbmFsIEhpZ2ggQ2FwYWNpdHkKICAgICAgICAgICAgICAgIERhdGEgVHlwZXMiOwogIH0KCiAgdHlwZWRlZiBnYXVnZTMyIHsKICAgIHR5cGUgdWludDMyOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGdhdWdlMzIgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIsIHdoaWNoCiAgICAgIG1heSBpbmNyZWFzZSBvciBkZWNyZWFzZSwgYnV0IHNoYWxsIG5ldmVyIGV4Y2VlZCBhIG1heGltdW0KICAgICAgdmFsdWUsIG5vciBmYWxsIGJlbG93IGEgbWluaW11bSB2YWx1ZS4gIFRoZSBtYXhpbXVtIHZhbHVlCiAgICAgIGNhbm5vdCBiZSBncmVhdGVyIHRoYW4gMl4zMi0xICg0Mjk0OTY3Mjk1IGRlY2ltYWwpLCBhbmQKICAgICAgdGhlIG1pbmltdW0gdmFsdWUgY2Fubm90IGJlIHNtYWxsZXIgdGhhbiAwLiAgVGhlIHZhbHVlIG9mCiAgICAgIGEgZ2F1Z2UzMiBoYXMgaXRzIG1heGltdW0gdmFsdWUgd2hlbmV2ZXIgdGhlIGluZm9ybWF0aW9uCiAgICAgIGJlaW5nIG1vZGVsZWQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGl0cyBtYXhpbXVtCiAgICAgIHZhbHVlLCBhbmQgaGFzIGl0cyBtaW5pbXVtIHZhbHVlIHdoZW5ldmVyIHRoZSBpbmZvcm1hdGlvbgogICAgICBiZWluZyBtb2RlbGVkIGlzIHNtYWxsZXIgdGhhbiBvciBlcXVhbCB0byBpdHMgbWluaW11bSB2YWx1ZS4KICAgICAgSWYgdGhlIGluZm9ybWF0aW9uIGJlaW5nIG1vZGVsZWQgc3Vic2VxdWVudGx5IGRlY3JlYXNlcwogICAgICBiZWxvdyAoaW5jcmVhc2VzIGFib3ZlKSB0aGUgbWF4aW11bSAobWluaW11bSkgdmFsdWUsIHRoZQogICAgICBnYXVnZTMyIGFsc28gZGVjcmVhc2VzIChpbmNyZWFzZXMpLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIEdhdWdlMzIgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgZ2F1Z2U2NCB7CiAgICB0eXBlIHVpbnQ2NDsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBnYXVnZTY0IHR5cGUgcmVwcmVzZW50cyBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyLCB3aGljaAogICAgICBtYXkgaW5jcmVhc2Ugb3IgZGVjcmVhc2UsIGJ1dCBzaGFsbCBuZXZlciBleGNlZWQgYSBtYXhpbXVtCiAgICAgIHZhbHVlLCBub3IgZmFsbCBiZWxvdyBhIG1pbmltdW0gdmFsdWUuICBUaGUgbWF4aW11bSB2YWx1ZQogICAgICBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuIDJeNjQtMSAoMTg0NDY3NDQwNzM3MDk1NTE2MTUpLCBhbmQKICAgICAgdGhlIG1pbmltdW0gdmFsdWUgY2Fubm90IGJlIHNtYWxsZXIgdGhhbiAwLiAgVGhlIHZhbHVlIG9mCiAgICAgIGEgZ2F1Z2U2NCBoYXMgaXRzIG1heGltdW0gdmFsdWUgd2hlbmV2ZXIgdGhlIGluZm9ybWF0aW9uCiAgICAgIGJlaW5nIG1vZGVsZWQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGl0cyBtYXhpbXVtCiAgICAgIHZhbHVlLCBhbmQgaGFzIGl0cyBtaW5pbXVtIHZhbHVlIHdoZW5ldmVyIHRoZSBpbmZvcm1hdGlvbgogICAgICBiZWluZyBtb2RlbGVkIGlzIHNtYWxsZXIgdGhhbiBvciBlcXVhbCB0byBpdHMgbWluaW11bSB2YWx1ZS4KICAgICAgSWYgdGhlIGluZm9ybWF0aW9uIGJlaW5nIG1vZGVsZWQgc3Vic2VxdWVudGx5IGRlY3JlYXNlcwogICAgICBiZWxvdyAoaW5jcmVhc2VzIGFib3ZlKSB0aGUgbWF4aW11bSAobWluaW11bSkgdmFsdWUsIHRoZQogICAgICBnYXVnZTY0IGFsc28gZGVjcmVhc2VzIChpbmNyZWFzZXMpLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIENvdW50ZXJCYXNlZEdhdWdlNjQgU01JdjIgdGV4dHVhbCBjb252ZW50aW9uIGRlZmluZWQKICAgICAgaW4gUkZDIDI4NTYiOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyODU2OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBBZGRpdGlvbmFsIEhpZ2ggQ2FwYWNpdHkKICAgICAgICAgICAgICAgIERhdGEgVHlwZXMiOwogIH0KCiAgLyoqKiBjb2xsZWN0aW9uIG9mIGlkZW50aWZpZXItcmVsYXRlZCB0eXBlcyAqKiovCgogIHR5cGVkZWYgb2JqZWN0LWlkZW50aWZpZXIgewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICcoKFswLTFdKFwuWzEtM10/WzAtOV0pKXwoMlwuKDB8KFsxLTldXGQqKSkpKScKICAgICAgICAgICAgKyAnKFwuKDB8KFsxLTldXGQqKSkpKic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgb2JqZWN0LWlkZW50aWZpZXIgdHlwZSByZXByZXNlbnRzIGFkbWluaXN0cmF0aXZlbHkKICAgICAgYXNzaWduZWQgbmFtZXMgaW4gYSByZWdpc3RyYXRpb24taGllcmFyY2hpY2FsLW5hbWUgdHJlZS4KCiAgICAgIFZhbHVlcyBvZiB0aGlzIHR5cGUgYXJlIGRlbm90ZWQgYXMgYSBzZXF1ZW5jZSBvZiBudW1lcmljYWwKICAgICAgbm9uLW5lZ2F0aXZlIHN1Yi1pZGVudGlmaWVyIHZhbHVlcy4gIEVhY2ggc3ViLWlkZW50aWZpZXIKICAgICAgdmFsdWUgTVVTVCBOT1QgZXhjZWVkIDJeMzItMSAoNDI5NDk2NzI5NSkuICBTdWItaWRlbnRpZmllcnMKICAgICAgYXJlIHNlcGFyYXRlZCBieSBzaW5nbGUgZG90cyBhbmQgd2l0aG91dCBhbnkgaW50ZXJtZWRpYXRlCiAgICAgIHdoaXRlc3BhY2UuCgogICAgICBUaGUgQVNOLjEgc3RhbmRhcmQgcmVzdHJpY3RzIHRoZSB2YWx1ZSBzcGFjZSBvZiB0aGUgZmlyc3QKICAgICAgc3ViLWlkZW50aWZpZXIgdG8gMCwgMSwgb3IgMi4gIEZ1cnRoZXJtb3JlLCB0aGUgdmFsdWUgc3BhY2UKICAgICAgb2YgdGhlIHNlY29uZCBzdWItaWRlbnRpZmllciBpcyByZXN0cmljdGVkIHRvIHRoZSByYW5nZQogICAgICAwIHRvIDM5IGlmIHRoZSBmaXJzdCBzdWItaWRlbnRpZmllciBpcyAwIG9yIDEuICBGaW5hbGx5LAogICAgICB0aGUgQVNOLjEgc3RhbmRhcmQgcmVxdWlyZXMgdGhhdCBhbiBvYmplY3QgaWRlbnRpZmllcgogICAgICBoYXMgYWx3YXlzIGF0IGxlYXN0IHR3byBzdWItaWRlbnRpZmllcnMuICBUaGUgcGF0dGVybgogICAgICBjYXB0dXJlcyB0aGVzZSByZXN0cmljdGlvbnMuCgogICAgICBBbHRob3VnaCB0aGUgbnVtYmVyIG9mIHN1Yi1pZGVudGlmaWVycyBpcyBub3QgbGltaXRlZCwKICAgICAgbW9kdWxlIGRlc2lnbmVycyBzaG91bGQgcmVhbGl6ZSB0aGF0IHRoZXJlIG1heSBiZQogICAgICBpbXBsZW1lbnRhdGlvbnMgdGhhdCBzdGljayB3aXRoIHRoZSBTTUl2MiBsaW1pdCBvZiAxMjgKICAgICAgc3ViLWlkZW50aWZpZXJzLgoKICAgICAgVGhpcyB0eXBlIGlzIGEgc3VwZXJzZXQgb2YgdGhlIFNNSXYyIE9CSkVDVCBJREVOVElGSUVSIHR5cGUKICAgICAgc2luY2UgaXQgaXMgbm90IHJlc3RyaWN0ZWQgdG8gMTI4IHN1Yi1pZGVudGlmaWVycy4gIEhlbmNlLAogICAgICB0aGlzIHR5cGUgU0hPVUxEIE5PVCBiZSB1c2VkIHRvIHJlcHJlc2VudCB0aGUgU01JdjIgT0JKRUNUCiAgICAgIElERU5USUZJRVIgdHlwZTsgdGhlIG9iamVjdC1pZGVudGlmaWVyLTEyOCB0eXBlIFNIT1VMRCBiZQogICAgICB1c2VkIGluc3RlYWQuIjsKICAgIHJlZmVyZW5jZQogICAgICJJU085ODM0LTE6IEluZm9ybWF0aW9uIHRlY2hub2xvZ3kgLS0gT3BlbiBTeXN0ZW1zCiAgICAgIEludGVyY29ubmVjdGlvbiAtLSBQcm9jZWR1cmVzIGZvciB0aGUgb3BlcmF0aW9uIG9mIE9TSQogICAgICBSZWdpc3RyYXRpb24gQXV0aG9yaXRpZXM6IEdlbmVyYWwgcHJvY2VkdXJlcyBhbmQgdG9wCiAgICAgIGFyY3Mgb2YgdGhlIEFTTi4xIE9iamVjdCBJZGVudGlmaWVyIHRyZWUiOwogIH0KCiAgdHlwZWRlZiBvYmplY3QtaWRlbnRpZmllci0xMjggewogICAgdHlwZSBvYmplY3QtaWRlbnRpZmllciB7CiAgICAgIHBhdHRlcm4gJ1xkKihcLlxkKil7MSwxMjd9JzsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoaXMgdHlwZSByZXByZXNlbnRzIG9iamVjdC1pZGVudGlmaWVycyByZXN0cmljdGVkIHRvIDEyOAogICAgICBzdWItaWRlbnRpZmllcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgT0JKRUNUIElERU5USUZJRVIgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgeWFuZy1pZGVudGlmaWVyIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgbGVuZ3RoICIxLi5tYXgiOwogICAgICBwYXR0ZXJuICdbYS16QS1aX11bYS16QS1aMC05XC1fLl0qJzsKICAgICAgcGF0dGVybiAnLnwuLnxbXnhYXS4qfC5bXm1NXS4qfC4uW15sTF0uKic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICAiQSBZQU5HIGlkZW50aWZpZXIgc3RyaW5nIGFzIGRlZmluZWQgYnkgdGhlICdpZGVudGlmaWVyJwogICAgICAgcnVsZSBpbiBTZWN0aW9uIDEyIG9mIFJGQyA2MDIwLiAgQW4gaWRlbnRpZmllciBtdXN0CiAgICAgICBzdGFydCB3aXRoIGFuIGFscGhhYmV0aWMgY2hhcmFjdGVyIG9yIGFuIHVuZGVyc2NvcmUKICAgICAgIGZvbGxvd2VkIGJ5IGFuIGFyYml0cmFyeSBzZXF1ZW5jZSBvZiBhbHBoYWJldGljIG9yCiAgICAgICBudW1lcmljIGNoYXJhY3RlcnMsIHVuZGVyc2NvcmVzLCBoeXBoZW5zLCBvciBkb3RzLgoKICAgICAgIEEgWUFORyBpZGVudGlmaWVyIE1VU1QgTk9UIHN0YXJ0IHdpdGggYW55IHBvc3NpYmxlCiAgICAgICBjb21iaW5hdGlvbiBvZiB0aGUgbG93ZXJjYXNlIG9yIHVwcGVyY2FzZSBjaGFyYWN0ZXIKICAgICAgIHNlcXVlbmNlICd4bWwnLiI7CiAgICByZWZlcmVuY2UKICAgICAgIlJGQyA2MDIwOiBZQU5HIC0gQSBEYXRhIE1vZGVsaW5nIExhbmd1YWdlIGZvciB0aGUgTmV0d29yawogICAgICAgICAgICAgICAgIENvbmZpZ3VyYXRpb24gUHJvdG9jb2wgKE5FVENPTkYpIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiB0eXBlcyByZWxhdGVkIHRvIGRhdGUgYW5kIHRpbWUqKiovCgogIHR5cGVkZWYgZGF0ZS1hbmQtdGltZSB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4gJ1xkezR9LVxkezJ9LVxkezJ9VFxkezJ9OlxkezJ9OlxkezJ9KFwuXGQrKT8nCiAgICAgICAgICAgICsgJyhafFtcK1wtXVxkezJ9OlxkezJ9KSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgZGF0ZS1hbmQtdGltZSB0eXBlIGlzIGEgcHJvZmlsZSBvZiB0aGUgSVNPIDg2MDEKICAgICAgc3RhbmRhcmQgZm9yIHJlcHJlc2VudGF0aW9uIG9mIGRhdGVzIGFuZCB0aW1lcyB1c2luZyB0aGUKICAgICAgR3JlZ29yaWFuIGNhbGVuZGFyLiAgVGhlIHByb2ZpbGUgaXMgZGVmaW5lZCBieSB0aGUKICAgICAgZGF0ZS10aW1lIHByb2R1Y3Rpb24gaW4gU2VjdGlvbiA1LjYgb2YgUkZDIDMzMzkuCgogICAgICBUaGUgZGF0ZS1hbmQtdGltZSB0eXBlIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgZGF0ZVRpbWUgWE1MCiAgICAgIHNjaGVtYSB0eXBlIHdpdGggdGhlIGZvbGxvd2luZyBub3RhYmxlIGV4Y2VwdGlvbnM6CgogICAgICAoYSkgVGhlIGRhdGUtYW5kLXRpbWUgdHlwZSBkb2VzIG5vdCBhbGxvdyBuZWdhdGl2ZSB5ZWFycy4KCiAgICAgIChiKSBUaGUgZGF0ZS1hbmQtdGltZSB0aW1lLW9mZnNldCAtMDA6MDAgaW5kaWNhdGVzIGFuIHVua25vd24KICAgICAgICAgIHRpbWUgem9uZSAoc2VlIFJGQyAzMzM5KSB3aGlsZSAtMDA6MDAgYW5kICswMDowMCBhbmQgWgogICAgICAgICAgYWxsIHJlcHJlc2VudCB0aGUgc2FtZSB0aW1lIHpvbmUgaW4gZGF0ZVRpbWUuCgogICAgICAoYykgVGhlIGNhbm9uaWNhbCBmb3JtYXQgKHNlZSBiZWxvdykgb2YgZGF0YS1hbmQtdGltZSB2YWx1ZXMKICAgICAgICAgIGRpZmZlcnMgZnJvbSB0aGUgY2Fub25pY2FsIGZvcm1hdCB1c2VkIGJ5IHRoZSBkYXRlVGltZSBYTUwKICAgICAgICAgIHNjaGVtYSB0eXBlLCB3aGljaCByZXF1aXJlcyBhbGwgdGltZXMgdG8gYmUgaW4gVVRDIHVzaW5nCiAgICAgICAgICB0aGUgdGltZS1vZmZzZXQgJ1onLgoKICAgICAgVGhpcyB0eXBlIGlzIG5vdCBlcXVpdmFsZW50IHRvIHRoZSBEYXRlQW5kVGltZSB0ZXh0dWFsCiAgICAgIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyIHNpbmNlIFJGQyAzMzM5IHVzZXMgYSBkaWZmZXJlbnQKICAgICAgc2VwYXJhdG9yIGJldHdlZW4gZnVsbC1kYXRlIGFuZCBmdWxsLXRpbWUgYW5kIHByb3ZpZGVzCiAgICAgIGhpZ2hlciByZXNvbHV0aW9uIG9mIHRpbWUtc2VjZnJhYy4KCiAgICAgIFRoZSBjYW5vbmljYWwgZm9ybWF0IGZvciBkYXRlLWFuZC10aW1lIHZhbHVlcyB3aXRoIGEga25vd24gdGltZQogICAgICB6b25lIHVzZXMgYSBudW1lcmljIHRpbWUgem9uZSBvZmZzZXQgdGhhdCBpcyBjYWxjdWxhdGVkIHVzaW5nCiAgICAgIHRoZSBkZXZpY2UncyBjb25maWd1cmVkIGtub3duIG9mZnNldCB0byBVVEMgdGltZS4gIEEgY2hhbmdlIG9mCiAgICAgIHRoZSBkZXZpY2UncyBvZmZzZXQgdG8gVVRDIHRpbWUgd2lsbCBjYXVzZSBkYXRlLWFuZC10aW1lIHZhbHVlcwogICAgICB0byBjaGFuZ2UgYWNjb3JkaW5nbHkuICBTdWNoIGNoYW5nZXMgbWlnaHQgaGFwcGVuIHBlcmlvZGljYWxseQogICAgICBpbiBjYXNlIGEgc2VydmVyIGZvbGxvd3MgYXV0b21hdGljYWxseSBkYXlsaWdodCBzYXZpbmcgdGltZQogICAgICAoRFNUKSB0aW1lIHpvbmUgb2Zmc2V0IGNoYW5nZXMuICBUaGUgY2Fub25pY2FsIGZvcm1hdCBmb3IKICAgICAgZGF0ZS1hbmQtdGltZSB2YWx1ZXMgd2l0aCBhbiB1bmtub3duIHRpbWUgem9uZSAodXN1YWxseQogICAgICByZWZlcnJpbmcgdG8gdGhlIG5vdGlvbiBvZiBsb2NhbCB0aW1lKSB1c2VzIHRoZSB0aW1lLW9mZnNldAogICAgICAtMDA6MDAuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzMzOTogRGF0ZSBhbmQgVGltZSBvbiB0aGUgSW50ZXJuZXQ6IFRpbWVzdGFtcHMKICAgICAgUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyCiAgICAgIFhTRC1UWVBFUzogWE1MIFNjaGVtYSBQYXJ0IDI6IERhdGF0eXBlcyBTZWNvbmQgRWRpdGlvbiI7CiAgfQoKICB0eXBlZGVmIHRpbWV0aWNrcyB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSB0aW1ldGlja3MgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgdGhhdAogICAgICByZXByZXNlbnRzIHRoZSB0aW1lLCBtb2R1bG8gMl4zMiAoNDI5NDk2NzI5NiBkZWNpbWFsKSwgaW4KICAgICAgaHVuZHJlZHRocyBvZiBhIHNlY29uZCBiZXR3ZWVuIHR3byBlcG9jaHMuICBXaGVuIGEgc2NoZW1hCiAgICAgIG5vZGUgaXMgZGVmaW5lZCB0aGF0IHVzZXMgdGhpcyB0eXBlLCB0aGUgZGVzY3JpcHRpb24gb2YKICAgICAgdGhlIHNjaGVtYSBub2RlIGlkZW50aWZpZXMgYm90aCBvZiB0aGUgcmVmZXJlbmNlIGVwb2Nocy4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBUaW1lVGlja3MgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgdGltZXN0YW1wIHsKICAgIHR5cGUgeWFuZzp0aW1ldGlja3M7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgdGltZXN0YW1wIHR5cGUgcmVwcmVzZW50cyB0aGUgdmFsdWUgb2YgYW4gYXNzb2NpYXRlZAogICAgICB0aW1ldGlja3Mgc2NoZW1hIG5vZGUgYXQgd2hpY2ggYSBzcGVjaWZpYyBvY2N1cnJlbmNlCiAgICAgIGhhcHBlbmVkLiAgVGhlIHNwZWNpZmljIG9jY3VycmVuY2UgbXVzdCBiZSBkZWZpbmVkIGluIHRoZQogICAgICBkZXNjcmlwdGlvbiBvZiBhbnkgc2NoZW1hIG5vZGUgZGVmaW5lZCB1c2luZyB0aGlzIHR5cGUuICBXaGVuCiAgICAgIHRoZSBzcGVjaWZpYyBvY2N1cnJlbmNlIG9jY3VycmVkIHByaW9yIHRvIHRoZSBsYXN0IHRpbWUgdGhlCiAgICAgIGFzc29jaWF0ZWQgdGltZXRpY2tzIGF0dHJpYnV0ZSB3YXMgemVybywgdGhlbiB0aGUgdGltZXN0YW1wCiAgICAgIHZhbHVlIGlzIHplcm8uICBOb3RlIHRoYXQgdGhpcyByZXF1aXJlcyBhbGwgdGltZXN0YW1wIHZhbHVlcwogICAgICB0byBiZSByZXNldCB0byB6ZXJvIHdoZW4gdGhlIHZhbHVlIG9mIHRoZSBhc3NvY2lhdGVkIHRpbWV0aWNrcwogICAgICBhdHRyaWJ1dGUgcmVhY2hlcyA0OTcrIGRheXMgYW5kIHdyYXBzIGFyb3VuZCB0byB6ZXJvLgoKICAgICAgVGhlIGFzc29jaWF0ZWQgdGltZXRpY2tzIHNjaGVtYSBub2RlIG11c3QgYmUgc3BlY2lmaWVkCiAgICAgIGluIHRoZSBkZXNjcmlwdGlvbiBvZiBhbnkgc2NoZW1hIG5vZGUgdXNpbmcgdGhpcyB0eXBlLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIFRpbWVTdGFtcCB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBnZW5lcmljIGFkZHJlc3MgdHlwZXMgKioqLwoKICB0eXBlZGVmIHBoeXMtYWRkcmVzcyB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4gJyhbMC05YS1mQS1GXXsyfSg6WzAtOWEtZkEtRl17Mn0pKik/JzsKICAgIH0KCgoKCiAgICBkZXNjcmlwdGlvbgogICAgICJSZXByZXNlbnRzIG1lZGlhLSBvciBwaHlzaWNhbC1sZXZlbCBhZGRyZXNzZXMgcmVwcmVzZW50ZWQKICAgICAgYXMgYSBzZXF1ZW5jZSBvY3RldHMsIGVhY2ggb2N0ZXQgcmVwcmVzZW50ZWQgYnkgdHdvIGhleGFkZWNpbWFsCiAgICAgIG51bWJlcnMuICBPY3RldHMgYXJlIHNlcGFyYXRlZCBieSBjb2xvbnMuICBUaGUgY2Fub25pY2FsCiAgICAgIHJlcHJlc2VudGF0aW9uIHVzZXMgbG93ZXJjYXNlIGNoYXJhY3RlcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgUGh5c0FkZHJlc3MgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyNTc5OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBTTUl2MiI7CiAgfQoKICB0eXBlZGVmIG1hYy1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnWzAtOWEtZkEtRl17Mn0oOlswLTlhLWZBLUZdezJ9KXs1fSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgbWFjLWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElFRUUgODAyIE1BQyBhZGRyZXNzLgogICAgICBUaGUgY2Fub25pY2FsIHJlcHJlc2VudGF0aW9uIHVzZXMgbG93ZXJjYXNlIGNoYXJhY3RlcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgTWFjQWRkcmVzcyB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiSUVFRSA4MDI6IElFRUUgU3RhbmRhcmQgZm9yIExvY2FsIGFuZCBNZXRyb3BvbGl0YW4gQXJlYQogICAgICAgICAgICAgICAgTmV0d29ya3M6IE92ZXJ2aWV3IGFuZCBBcmNoaXRlY3R1cmUKICAgICAgUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBYTUwtc3BlY2lmaWMgdHlwZXMgKioqLwoKICB0eXBlZGVmIHhwYXRoMS4wIHsKICAgIHR5cGUgc3RyaW5nOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhpcyB0eXBlIHJlcHJlc2VudHMgYW4gWFBBVEggMS4wIGV4cHJlc3Npb24uCgogICAgICBXaGVuIGEgc2NoZW1hIG5vZGUgaXMgZGVmaW5lZCB0aGF0IHVzZXMgdGhpcyB0eXBlLCB0aGUKICAgICAgZGVzY3JpcHRpb24gb2YgdGhlIHNjaGVtYSBub2RlIE1VU1Qgc3BlY2lmeSB0aGUgWFBhdGgKICAgICAgY29udGV4dCBpbiB3aGljaCB0aGUgWFBhdGggZXhwcmVzc2lvbiBpcyBldmFsdWF0ZWQuIjsKICAgIHJlZmVyZW5jZQogICAgICJYUEFUSDogWE1MIFBhdGggTGFuZ3VhZ2UgKFhQYXRoKSBWZXJzaW9uIDEuMCI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2Ygc3RyaW5nIHR5cGVzICoqKi8KCiAgdHlwZWRlZiBoZXgtc3RyaW5nIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKFswLTlhLWZBLUZdezJ9KDpbMC05YS1mQS1GXXsyfSkqKT8nOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiQSBoZXhhZGVjaW1hbCBzdHJpbmcgd2l0aCBvY3RldHMgcmVwcmVzZW50ZWQgYXMgaGV4IGRpZ2l0cwogICAgICBzZXBhcmF0ZWQgYnkgY29sb25zLiAgVGhlIGNhbm9uaWNhbCByZXByZXNlbnRhdGlvbiB1c2VzCiAgICAgIGxvd2VyY2FzZSBjaGFyYWN0ZXJzLiI7CiAgfQoKICB0eXBlZGVmIHV1aWQgewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMC05YS1mQS1GXXs4fS1bMC05YS1mQS1GXXs0fS1bMC05YS1mQS1GXXs0fS0nCiAgICAgICAgICAgICsgJ1swLTlhLWZBLUZdezR9LVswLTlhLWZBLUZdezEyfSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJBIFVuaXZlcnNhbGx5IFVuaXF1ZSBJRGVudGlmaWVyIGluIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24KICAgICAgZGVmaW5lZCBpbiBSRkMgNDEyMi4gIFRoZSBjYW5vbmljYWwgcmVwcmVzZW50YXRpb24gdXNlcwogICAgICBsb3dlcmNhc2UgY2hhcmFjdGVycy4KCiAgICAgIFRoZSBmb2xsb3dpbmcgaXMgYW4gZXhhbXBsZSBvZiBhIFVVSUQgaW4gc3RyaW5nIHJlcHJlc2VudGF0aW9uOgogICAgICBmODFkNGZhZS03ZGVjLTExZDAtYTc2NS0wMGEwYzkxZTZiZjYKICAgICAgIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDEyMjogQSBVbml2ZXJzYWxseSBVbmlxdWUgSURlbnRpZmllciAoVVVJRCkgVVJOCiAgICAgICAgICAgICAgICBOYW1lc3BhY2UiOwogIH0KCiAgdHlwZWRlZiBkb3R0ZWQtcXVhZCB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4KICAgICAgICAnKChbMC05XXxbMS05XVswLTldfDFbMC05XVswLTldfDJbMC00XVswLTldfDI1WzAtNV0pXC4pezN9JwogICAgICArICcoWzAtOV18WzEtOV1bMC05XXwxWzAtOV1bMC05XXwyWzAtNF1bMC05XXwyNVswLTVdKSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICAiQW4gdW5zaWduZWQgMzItYml0IG51bWJlciBleHByZXNzZWQgaW4gdGhlIGRvdHRlZC1xdWFkCiAgICAgICBub3RhdGlvbiwgaS5lLiwgZm91ciBvY3RldHMgd3JpdHRlbiBhcyBkZWNpbWFsIG51bWJlcnMKICAgICAgIGFuZCBzZXBhcmF0ZWQgd2l0aCB0aGUgJy4nIChmdWxsIHN0b3ApIGNoYXJhY3Rlci4iOwogIH0KfQ== +o-ran-smo-teiv-common-yang-extensions urn:o-ran:smo-teiv-common-yang-extensions \N [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOm8tcmFuOnNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMiOwogICAgcHJlZml4IG9yLXRlaXYteWV4dDsKCiAgICBvcmdhbml6YXRpb24gIkVyaWNzc29uIEFCIjsKICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOwogICAgZGVzY3JpcHRpb24KICAgICJUb3BvbG9neSBhbmQgSW52ZW50b3J5IFlBTkcgZXh0ZW5zaW9ucyBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyBleHRlbnNpb25zIHRvIHRoZSBZQU5HIGxhbmd1YWdlIHRoYXQgdG9wb2xvZ3kgYW5kCiAgICBpbnZlbnRvcnkgbW9kZWxzIHdpbGwgdXNlIHRvIGRlZmluZSBhbmQgYW5ub3RhdGUgdHlwZXMgYW5kIHJlbGF0aW9uc2hpcHMuIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0yNCIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIGV4dGVuc2lvbiBiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJEZWZpbmVzIGEgYmktZGlyZWN0aW9uYWwgcmVsYXRpb25zaGlwIGluIHRoZSB0b3BvbG9neS4KCiAgICAgICAgICAgIEEgYmktZGlyZWN0aW9uYWwtYXNzb2NpYXRpb24gKEJEQSkgaXMgYSByZWxhdGlvbnNoaXAgY29tcHJpc2luZyBvZgogICAgICAgICAgICBhbiBBLXNpZGUgYW5kIGEgQi1zaWRlLiBUaGUgQS1zaWRlIGlzIGNvbnNpZGVyZWQgdGhlIG9yaWdpbmF0aW5nCiAgICAgICAgICAgIHNpZGUgb2YgdGhlIHJlbGF0aW9uc2hpcDsgdGhlIEItc2lkZSBpcyBjb25zaWRlcmVkIHRoZSB0ZXJtaW5hdGluZwogICAgICAgICAgICBzaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSBvcmRlciBvZiBBLXNpZGUgYW5kIEItc2lkZSBpcyBvZgogICAgICAgICAgICBpbXBvcnRhbmNlIGFuZCBNVVNUIE5PVCBiZSBjaGFuZ2VkIG9uY2UgZGVmaW5lZC4KCiAgICAgICAgICAgIEJvdGggQS1zaWRlIGFuZCBCLXNpZGUgYXJlIGRlZmluZWQgb24gYSB0eXBlLCBhbmQgYXJlIGdpdmVuIGEgcm9sZS4KICAgICAgICAgICAgQSB0eXBlIG1heSBoYXZlIG11bHRpcGxlIG9yaWdpbmF0aW5nIGFuZC9vciB0ZXJtaW5hdGluZyBzaWRlcyBvZiBhCiAgICAgICAgICAgIHJlbGF0aW9uc2hpcCwgYWxsIGRpc3Rpbmd1aXNoZWQgYnkgcm9sZSBuYW1lLgoKICAgICAgICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIG9ubHkgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlICdtb2R1bGUnIHN0YXRlbWVudC4KICAgICAgICAgICAgTXVsdGlwbGUgJ2JpLWRpcmVjdGlvbmFsLXRvcG9sb2d5LXJlbGF0aW9uc2hpcCcgc3RhdGVtZW50cyBhcmUKICAgICAgICAgICAgYWxsb3dlZCBwZXIgcGFyZW50IHN0YXRlbWVudC4KCiAgICAgICAgICAgIFN1YnN0YXRlbWVudHMgdG8gdGhlICdiaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIGRlZmluZQogICAgICAgICAgICB0aGUgQS1zaWRlIGFuZCB0aGUgQi1zaWRlLCByZXNwZWN0aXZlbHksIGFuZCBvcHRpb25hbGx5IHByb3BlcnRpZXMKICAgICAgICAgICAgb2YgdGhlIHJlbGF0aW9uc2hpcC4gRGF0YSBub2RlcyBvZiB0eXBlcyAnbGVhZicgYW5kICdsZWFmLWxpc3QnIGFyZQogICAgICAgICAgICB1c2VkIGZvciB0aGlzIHB1cnBvc2UuIE9uZSBvZiB0aGUgZGF0YSBub2RlcyBNVVNUIGJlIGFubm90YXRlZCB3aXRoCiAgICAgICAgICAgIHRoZSAnYS1zaWRlJyBleHRlbnNpb247IGFub3RoZXIgZGF0YSBub2RlIE1VU1QgYmUgYW5ub3RhdGVkIHdpdGggdGhlCiAgICAgICAgICAgICdiLXNpZGUnIGV4dGVuc2lvbi4gT3RoZXIgZGF0YSBub2RlcyBkZWZpbmUgcHJvcGVydGllcyBvZiB0aGUKICAgICAgICAgICAgcmVsYXRpb25zaGlwLgoKICAgICAgICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSByZWxhdGlvbnNoaXAgbmFtZQogICAgICAgICAgICBpcyBzY29wZWQgdG8gdGhlIG5hbWVzcGFjZSBvZiB0aGUgZGVjbGFyaW5nIG1vZHVsZSBhbmQgTVVTVCBiZQogICAgICAgICAgICB1bmlxdWUgd2l0aGluIHRoZSBzY29wZS4iOwoKICAgICAgICBhcmd1bWVudCByZWxhdGlvbnNoaXBOYW1lOwogICAgfQoKICAgIGV4dGVuc2lvbiBhU2lkZSB7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIkRlZmluZXMgdGhlIEEtc2lkZSBvZiBhIHJlbGF0aW9uc2hpcC4KCiAgICAgICAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgJ2xlYWYnIG9yICdsZWFmLWxpc3QnCiAgICAgICAgICAgIHN0YXRlbWVudCwgd2hpY2ggaXRzZWxmIG11c3QgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlCiAgICAgICAgICAgICd1bmktZGlyZWN0aW9uYWwtdG9wb2xvZ3ktcmVsYXRpb25zaGlwJyBzdGF0ZW1lbnQuCgogICAgICAgICAgICBUaGUgZGF0YSB0eXBlIG9mIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIE1VU1QgYmUKICAgICAgICAgICAgJ2luc3RhbmNlLWlkZW50aWZpZXInLiBDb25zdHJhaW50cyBNQVkgYmUgdXNlZCBhcyBwYXJ0IG9mIHRoZSBwYXJlbnQKICAgICAgICAgICAgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIHRvIGVuZm9yY2UgY2FyZGluYWxpdHkuCgogICAgICAgICAgICBUaGUgaWRlbnRpZmllciBvZiB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBpcyB1c2VkIGFzIG5hbWUKICAgICAgICAgICAgb2YgdGhlIHJvbGUgb2YgdGhlIEEtc2lkZSBvZiB0aGUgcmVsYXRpb25zaGlwLiBUaGUgbmFtZSBvZiB0aGUgcm9sZQogICAgICAgICAgICBpcyBzY29wZWQgdG8gdGhlIHR5cGUgb24gd2hpY2ggdGhlIEEtc2lkZSBpcyBkZWZpbmVkIGFuZCBNVVNUIGJlCiAgICAgICAgICAgIHVuaXF1ZSB3aXRoaW4gdGhlIHNjb3BlLgoKICAgICAgICAgICAgV2hpbGUgdGhlIHBhcmVudCAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgZG9lcyBub3QgcmVzdWx0IGluIGEgcHJvcGVydHkKICAgICAgICAgICAgb2YgdGhlIHJlbGF0aW9uc2hpcCwgaXQgaXMgUkVDT01NRU5ERUQgdG8gYXZvaWQgdXNpbmcgdGhlIG5hbWUgb2YgYW4KICAgICAgICAgICAgZXhpc3RpbmcgdHlwZSBwcm9wZXJ0eSBhcyByb2xlIG5hbWUgdG8gYXZvaWQgcG90ZW50aWFsIGFtYmlndWl0aWVzCiAgICAgICAgICAgIGJldHdlZW4gcHJvcGVydGllcyBvZiBhIHR5cGUsIGFuZCByb2xlcyBvZiBhIHJlbGF0aW9uc2hpcCBvbiB0aGUKICAgICAgICAgICAgdHlwZS4KCiAgICAgICAgICAgIFRoZSBhcmd1bWVudCBpcyB0aGUgbmFtZSBvZiB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQS1zaWRlIHJlc2lkZXMuCiAgICAgICAgICAgIElmIHRoZSB0eXBlIGlzIGRlY2xhcmVkIGluIGFub3RoZXIgbW9kdWxlLCB0aGUgdHlwZSBtdXN0IGJlCiAgICAgICAgICAgIHByZWZpeGVkLCBhbmQgYSBjb3JyZXNwb25kaW5nICdpbXBvcnQnIHN0YXRlbWVudCBiZSB1c2VkIHRvIGRlY2xhcmUKICAgICAgICAgICAgdGhlIHByZWZpeC4iOwoKICAgICAgICBhcmd1bWVudCBhU2lkZVR5cGU7CiAgICB9CgogICAgZXh0ZW5zaW9uIGJTaWRlIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiRGVmaW5lcyB0aGUgQi1zaWRlIG9mIGEgcmVsYXRpb25zaGlwLgoKICAgICAgICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIG9ubHkgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgYSAnbGVhZicgb3IgJ2xlYWYtbGlzdCcKICAgICAgICAgICAgc3RhdGVtZW50LCB3aGljaCBpdHNlbGYgbXVzdCBiZSBhIHN1YnN0YXRlbWVudCBvZiB0aGUKICAgICAgICAgICAgJ3VuaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIHN0YXRlbWVudC4KCiAgICAgICAgICAgIFRoZSBkYXRhIHR5cGUgb2YgdGhlIHBhcmVudCAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgTVVTVCBiZQogICAgICAgICAgICAnaW5zdGFuY2UtaWRlbnRpZmllcicuIENvbnN0cmFpbnRzIE1BWSBiZSB1c2VkIGFzIHBhcnQgb2YgdGhlIHBhcmVudAogICAgICAgICAgICAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgdG8gZW5mb3JjZSBjYXJkaW5hbGl0eS4KCiAgICAgICAgICAgIFRoZSBpZGVudGlmaWVyIG9mIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIGlzIHVzZWQgYXMgbmFtZQogICAgICAgICAgICBvZiB0aGUgcm9sZSBvZiB0aGUgQi1zaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSBuYW1lIG9mIHRoZSByb2xlCiAgICAgICAgICAgIGlzIHNjb3BlZCB0byB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQi1zaWRlIGlzIGRlZmluZWQgYW5kIE1VU1QgYmUKICAgICAgICAgICAgdW5pcXVlIHdpdGhpbiB0aGUgc2NvcGUuCgogICAgICAgICAgICBXaGlsZSB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBkb2VzIG5vdCByZXN1bHQgaW4gYSBwcm9wZXJ0eQogICAgICAgICAgICBvZiB0aGUgcmVsYXRpb25zaGlwLCBpdCBpcyBSRUNPTU1FTkRFRCB0byBhdm9pZCB1c2luZyB0aGUgbmFtZSBvZiBhbgogICAgICAgICAgICBleGlzdGluZyB0eXBlIHByb3BlcnR5IGFzIHJvbGUgbmFtZSB0byBhdm9pZCBwb3RlbnRpYWwgYW1iaWd1aXRpZXMKICAgICAgICAgICAgYmV0d2VlbiBwcm9wZXJ0aWVzIG9mIGEgdHlwZSwgYW5kIHJvbGVzIG9mIGEgcmVsYXRpb25zaGlwIG9uIHRoZQogICAgICAgICAgICB0eXBlLgoKICAgICAgICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSB0eXBlIG9uIHdoaWNoIHRoZSBCLXNpZGUgcmVzaWRlcy4KICAgICAgICAgICAgSWYgdGhlIHR5cGUgaXMgZGVjbGFyZWQgaW4gYW5vdGhlciBtb2R1bGUsIHRoZSB0eXBlIG11c3QgYmUKICAgICAgICAgICAgcHJlZml4ZWQsIGFuZCBhIGNvcnJlc3BvbmRpbmcgJ2ltcG9ydCcgc3RhdGVtZW50IGJlIHVzZWQgdG8gZGVjbGFyZQogICAgICAgICAgICB0aGUgcHJlZml4LiI7CgogICAgICAgIGFyZ3VtZW50IGJTaWRlVHlwZTsKICAgIH0KCiAgICBleHRlbnNpb24gZG9tYWluIHsKICAgICAgICBkZXNjcmlwdGlvbiAiS2V5d29yZCB1c2VkIHRvIGNhcnJ5IGRvbWFpbiBpbmZvcm1hdGlvbi4iOwogICAgICAgIGFyZ3VtZW50IGRvbWFpbk5hbWU7CiAgICB9CgogICAgZXh0ZW5zaW9uIGxhYmVsIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhlIGxhYmVsIGNhbiBiZSB1c2VkIHRvIGdpdmUgbW9kdWxlcyBhbmQgc3VibW9kdWxlcyBhIHNlbWFudGljCiAgICAgICAgICAgIHZlcnNpb24sIGluIGFkZGl0aW9uIHRvIHRoZWlyIHJldmlzaW9uLgoKICAgICAgICAgICAgVGhlIGZvcm1hdCBvZiB0aGUgbGFiZWwgaXMg4oCYeC55LnrigJkg4oCTIGV4cHJlc3NlZCBhcyBwYXR0ZXJuLCBpdCBpcwogICAgICAgICAgICBbMC05XStcXC5bMC05XStcXC5bMC05XSsKCiAgICAgICAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIHRoZSByZXZpc2lvbiBzdGF0ZW1lbnQuCiAgICAgICAgICAgIFplcm8gb3Igb25lIHJldmlzaW9uIGxhYmVsIHN0YXRlbWVudHMgcGVyIHBhcmVudCBzdGF0ZW1lbnQgYXJlCiAgICAgICAgICAgIGFsbG93ZWQuCgogICAgICAgICAgICBSZXZpc2lvbiBsYWJlbHMgTVVTVCBiZSB1bmlxdWUgYW1vbmdzdCBhbGwgcmV2aXNpb25zIG9mIGEgbW9kdWxlIG9yCiAgICAgICAgICAgIHN1Ym1vZHVsZS4iOwoKICAgICAgICBhcmd1bWVudCBzZW12ZXJzaW9uOwogICAgfQp9 +o-ran-smo-teiv-common-yang-types urn:o-ran:smo-teiv-common-yang-types \N [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyI7CiAgICBwcmVmaXggb3ItdGVpdi10eXBlczsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7IHByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgXzNncHAtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggdHlwZXMzZ3BwOyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiVG9wb2xvZ3kgYW5kIEludmVudG9yeSBjb21tb24gdHlwZXMgbW9kZWwuCgogICAgQ29weXJpZ2h0IChjKSAyMDI0IEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKICAgIFRoaXMgbW9kZWwgY29udGFpbnMgcmUtdXNhYmxlIGRhdGEgdHlwZXMgdGhhdCB0b3BvbG9neSBhbmQgaW52ZW50b3J5IG1vZGVscwogICAgd2lsbCBmcmVxdWVudGx5IHVzZSBhcyBwYXJ0IG9mIHR5cGVzIGFuZCByZWxhdGlvbnNoaXBzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBncm91cGluZyBUb3BfR3JwX1R5cGUgewogICAgICAgIGRlc2NyaXB0aW9uICJHcm91cGluZyBjb250YWluaW5nIHRoZSBrZXkgYXR0cmlidXRlIGNvbW1vbiB0byBhbGwgdHlwZXMuCiAgICAgICAgICAgIEFsbCB0eXBlcyBNVVNUIHVzZSB0aGlzIGdyb3VwaW5nLiI7CgogICAgICAgIGxlYWYgaWQgewogICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVuaXF1ZSBpZGVudGlmaWVyIG9mIHRvcG9sb2d5IGVudGl0aWVzLiBSZXByZXNlbnRzIHRoZQogICAgICAgICAgICAgICAgRW50aXR5IEluc3RhbmNlIElkZW50aWZpZXIuIjsKICAgICAgICB9CiAgICB9CgogICAgY29udGFpbmVyIGRlY29yYXRvcnMgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGlzIGNvbnRhaW5lciBzZXJ2ZXMgYXMgZXh0ZW5zaW9uIHBvaW50IGZvciBhcHBsaWNhdGlvbnMgd2lzaGluZwogICAgICAgICAgICB0byBkZWZpbmUgdGhlaXIgb3duIGRlY29yYXRvcnMuIFRoaXMgaXMgZG9uZSB2aWEgYXVnbWVudGF0aW9ucy4gVGhleQogICAgICAgICAgICBjYW4gb25seSBiZSBkZWZpbmVkIGluIG5hbWUgdmFsdWUgcGFpci4KCiAgICAgICAgICAgIFRoaXMgaXMgYSBjb25zdW1lciBkYXRhIGFuZCBjYW4gYmUgYXR0YWNoZWQgdG8gVG9wb2xvZ3kgRW50aXR5IG9yCiAgICAgICAgICAgIFRvcG9sb2d5IFJlbGF0aW9uIGluc3RhbmNlLCBvdXRzaWRlIG9mIHRoZSBkZWNsYXJlZCBUb3BvbG9neSBFbnRpdHkKICAgICAgICAgICAgb3IgVG9wb2xvZ3kgUmVsYXRpb25zaGlwJ3MgYXR0cmlidXRlcy4gVGhpcyBjYW5ub3QgYmUgaW5zdGFudGlhdGVkLAogICAgICAgICAgICBhbmQgaXQgTVVTVCBOT1QgYmUgYXVnbWVudGVkIG9yIGRldmlhdGVkIGluIGFueSB3YXksIHVubGVzcyBzdGF0ZWQKICAgICAgICAgICAgb3RoZXJ3aXNlLiI7CiAgICB9CgogICAgbGVhZi1saXN0IGNsYXNzaWZpZXJzIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiQ29uc3VtZXIgZGVmaW5lZCB0YWdzIHRvIHRvcG9sb2d5IGVudGl0aWVzIGFuZCByZWxhdGlvbnNoaXBzLgoKICAgICAgICAgICAgVGhpcyBpcyBhIGNvbnN1bWVyIGRhdGEgYW5kIGNhbiBiZSBhdHRhY2hlZCB0byBUb3BvbG9neSBFbnRpdHkgb3IKICAgICAgICAgICAgVG9wb2xvZ3kgUmVsYXRpb24gaW5zdGFuY2UsIG91dHNpZGUgb2YgdGhlIGRlY2xhcmVkIFRvcG9sb2d5IEVudGl0eQogICAgICAgICAgICBvciBUb3BvbG9neSBSZWxhdGlvbnNoaXAncyBhdHRyaWJ1dGVzLiBUaGlzIGNhbm5vdCBiZSBpbnN0YW50aWF0ZWQsCiAgICAgICAgICAgIGFuZCBpdCBNVVNUIE5PVCBiZSBhdWdtZW50ZWQgb3IgZGV2aWF0ZWQgaW4gYW55IHdheSwgdW5sZXNzIHN0YXRlZAogICAgICAgICAgICBvdGhlcndpc2UuIjsKCiAgICAgICAgdHlwZSBpZGVudGl0eXJlZiB7IGJhc2UgY2xhc3NpZmllcjsgfQogICAgfQoKICAgIGxlYWYtbGlzdCBzb3VyY2VJZHMgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJBbiBvcmRlcmVkIGxpc3Qgb2YgaWRlbnRpdGllcyB0aGF0IHJlcHJlc2VudCB0aGUgc2V0IG9mIG5hdGl2ZQogICAgICAgICAgICBzb3VyY2UgaWRlbnRpZmllcnMgZm9yIHBhcnRpY2lwYXRpbmcgZW50aXRpZXMuCgogICAgICAgICAgICBUaGlzIGlzIGEgY29uc3VtZXIgZGF0YSBhbmQgY2FuIGJlIGF0dGFjaGVkIHRvIFRvcG9sb2d5IEVudGl0eSBvcgogICAgICAgICAgICBUb3BvbG9neSBSZWxhdGlvbiBpbnN0YW5jZSwgb3V0c2lkZSBvZiB0aGUgZGVjbGFyZWQgVG9wb2xvZ3kgRW50aXR5CiAgICAgICAgICAgIG9yIFRvcG9sb2d5IFJlbGF0aW9uc2hpcCdzIGF0dHJpYnV0ZXMuIFRoaXMgY2Fubm90IGJlIGluc3RhbnRpYXRlZCwKICAgICAgICAgICAgYW5kIGl0IE1VU1QgTk9UIGJlIGF1Z21lbnRlZCBvciBkZXZpYXRlZCBpbiBhbnkgd2F5LCB1bmxlc3Mgc3RhdGVkCiAgICAgICAgICAgIG90aGVyd2lzZS4iOwoKICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICBvcmRlcmVkLWJ5IHVzZXI7CiAgICB9CgogICAgY29udGFpbmVyIG1ldGFkYXRhIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhpcyBjb250YWluZXIgc2VydmVzIGFzIGV4dGVuc2lvbiBwb2ludCB0byBkZWZpbmUgbWV0YWRhdGEuIFRoZXkKICAgICAgICAgICAgY2FuIG9ubHkgYmUgZGVmaW5lZCBpbiBuYW1lIHZhbHVlIHBhaXIuCgogICAgICAgICAgICBUaGlzIGlzIGEgY29uc3VtZXIgZGF0YSBhbmQgY2FuIGJlIGF0dGFjaGVkIHRvIFRvcG9sb2d5IEVudGl0eSBvcgogICAgICAgICAgICBUb3BvbG9neSBSZWxhdGlvbiBpbnN0YW5jZSwgb3V0c2lkZSBvZiB0aGUgZGVjbGFyZWQgVG9wb2xvZ3kgRW50aXR5CiAgICAgICAgICAgIG9yIFRvcG9sb2d5IFJlbGF0aW9uc2hpcCdzIGF0dHJpYnV0ZXMuIFRoaXMgY2Fubm90IGJlIGluc3RhbnRpYXRlZCwKICAgICAgICAgICAgYW5kIGl0IE1VU1QgTk9UIGJlIGF1Z21lbnRlZCBvciBkZXZpYXRlZCBpbiBhbnkgd2F5LCB1bmxlc3Mgc3RhdGVkCiAgICAgICAgICAgIG90aGVyd2lzZS4iOwogICAgfQoKICAgIGlkZW50aXR5IGNsYXNzaWZpZXJ7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjbGFzc2lmaWVyIGlzIHVzZWQgYXMgYSBiYXNlIHRvIHByb3ZpZGUgYWxsIGNsYXNzaWZpZXJzCiAgICAgICAgICAgIHdpdGggaWRlbnRpdHkuICI7CiAgICB9Cn0= +o-ran-smo-teiv-equipment urn:o-ran:smo-teiv-equipment EQUIPMENT [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWVxdWlwbWVudCB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtZXF1aXBtZW50IjsKICAgIHByZWZpeCBvci10ZWl2LWVxdWlwOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgeyBwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgICAgICBwcmVmaXggZ2VvOwogICAgICAgIHJlZmVyZW5jZSAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIkVxdWlwbWVudCB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgRXF1aXBtZW50CiAgICBkb21haW4sIHdoaWNoIGlzIG1vZGVsbGVkIHRvIHVuZGVyc3RhbmQgdGhlIHBoeXNpY2FsIGxvY2F0aW9uIG9mIGVxdWlwbWVudAogICAgc3VjaCBhcyBhbnRlbm5hcyBhc3NvY2lhdGVkIHdpdGggYSBjZWxsL2NhcnJpZXIgYW5kIHRoZWlyIHJlbGV2YW50CiAgICBwcm9wZXJ0aWVzIGUuZy4gdGlsdCwgbWF4IHBvd2VyIGV0Yy4iOwoKICAgIHJldmlzaW9uICIyMDI0LTA1LTI0IiB7CiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmRvbWFpbiBFUVVJUE1FTlQ7CgogICAgbGlzdCBBbnRlbm5hTW9kdWxlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gQW50ZW5uYSBNb2R1bGUgcmVwcmVzZW50cyB0aGUgcGh5c2ljYWwgYXNwZWN0IG9mIGFuCiAgICAgICAgICAgIGFudGVubmEuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBhbnRlbm5hTW9kZWxOdW1iZXIgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlZlbmRvci1zcGVjaWZpYyBhbnRlbm5hIG1vZGVsIGlkZW50aWZpZXIuIFRoaXMKICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGUgaXMgcGFydCBvZiBBSVNHIHYzIEFEQiBTdGFuZGFyZCBhbmQgaGFzIG5vCiAgICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uYWwgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBtZWNoYW5pY2FsQW50ZW5uYUJlYXJpbmcgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgYmVhcmluZyBvbiBhbnRlbm5hIHN1YnVuaXQgd2hlcmUgYW50ZW5uYQogICAgICAgICAgICAgICAgICAgIHVuaXQgaXMgaW5zdGFsbGVkLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG1lY2hhbmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGZpeGVkIGFudGVubmEgdGlsdCBvZiB0aGUgaW5zdGFsbGF0aW9uLCBkZWZpbmVkCiAgICAgICAgICAgICAgICAgICAgYXMgdGhlIGluY2xpbmF0aW9uIG9mIHRoZSBhbnRlbm5hIGVsZW1lbnQgcmVzcGVjdCB0byB0aGUKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbCBwbGFuZS4gSXQgaXMgYSBzaWduZWQgdmFsdWUuIFBvc2l0aXZlIGluZGljYXRlcwogICAgICAgICAgICAgICAgICAgIGRvd250aWx0LCBhbmQgbmVnYXRpdmUgaW5kaWNhdGVzIHVwdGlsdC4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBwb3NpdGlvbldpdGhpblNlY3RvciB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSB1bml0IHBvc2l0aW9uIHdpdGhpbiBzZWN0b3IuIFRoaXMgYXR0cmlidXRlCiAgICAgICAgICAgICAgICAgICAgaXMgcGFydCBvZiBBSVNHIHYzIEFEQiBTdGFuZGFyZCBhbmQgaGFzIG5vIG9wZXJhdGlvbmFsCiAgICAgICAgICAgICAgICAgICAgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiB0b3RhbFRpbHQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRvdGFsIGFudGVubmEgZWxldmF0aW9uIGluY2x1ZGluZyB0aGUgaW5zdGFsbGVkCiAgICAgICAgICAgICAgICAgICAgdGlsdCBhbmQgdGhlIHRpbHQgYXBwbGllZCBieSB0aGUgUmVtb3RlIEVsZWN0cmljYWwKICAgICAgICAgICAgICAgICAgICBUaWx0IChSRVQpLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVsZWN0cmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiRWxlY3RyaWNhbGx5LWNvbnRyb2xsZWQgdGlsdCBvZiBtYWluIGJlYW0gbWF4aW11bQogICAgICAgICAgICAgICAgICAgIHdpdGggcmVzcGVjdCB0byBkaXJlY3Rpb24gb3J0aG9nb25hbCB0byBhbnRlbm5hIGVsZW1lbnQKICAgICAgICAgICAgICAgICAgICBheGlzIChzZWUgM0dQUCBUUyAyNS40NjYpLiBWYWx1ZSBpcyBzaWduZWQ7IHRpbHQgZG93biBpcwogICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlLCB0aWx0IHVwIGlzIG5lZ2F0aXZlLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgYW50ZW5uYUJlYW1XaWR0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGFuZ3VsYXIgc3BhbiBvZiB0aGUgbWFpbiBsb2JlIG9mIHRoZSBhbnRlbm5hCiAgICAgICAgICAgICAgICAgICAgcmFkaWF0aW9uIHBhdHRlcm4gaW4gdGhlIGhvcml6b250YWwgcGxhbmUuIE1lYXN1cmVkIGluCiAgICAgICAgICAgICAgICAgICAgZGVncmVlcy4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHVzZXMgZ2VvOmdlby1sb2NhdGlvbjsKICAgICAgICB9CiAgICB9CgogICAgbGlzdCBTaXRlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBzaXRlIGlzIGEgcGh5c2ljYWwgbG9jYXRpb24gd2hlcmUgYW4gZXF1aXBtZW50IGNhbiBiZQogICAgICAgICAgICBpbnN0YWxsZWQuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBuYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIFNpdGUiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHVzZXMgZ2VvOmdlby1sb2NhdGlvbjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBBTlRFTk5BTU9EVUxFX0lOU1RBTExFRF9BVF9TSVRFIHsgLy8gMC4ubiB0byAwLi4xCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmIGluc3RhbGxlZC1hdC1zaXRlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIGluc3RhbGxlZCBhdCBTaXRlLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgaW5zdGFsbGVkLWFudGVubmFNb2R1bGUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2l0ZSB3aGVyZSBBbnRlbm5hIE1vZHVsZSBpcyBpbnN0YWxsZWQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIFNpdGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9Cn0= +o-ran-smo-teiv-oam urn:o-ran:smo-teiv-oam OAM [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LW9hbSB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtb2FtIjsKICAgIHByZWZpeCBvci10ZWl2LW9hbTsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggb3ItdGVpdi10eXBlczsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHsgcHJlZml4IG9yLXRlaXYteWV4dDsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIk8mTSB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgTyZNIGRvbWFpbiwKICAgIHdoaWNoIGFyZSBpbnRlbmRlZCB0byByZXByZXNlbnQgbWFuYWdlbWVudCBzeXN0ZW1zIGFuZCBtYW5hZ2VtZW50CiAgICBpbnRlcmZhY2VzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIE9BTTsKCiAgICBsaXN0IE1hbmFnZWRFbGVtZW50IHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBNYW5hZ2VkIEVsZW1lbnQgKE1FKSBpcyBhIG5vZGUgaW50byBhIHRlbGVjb21tdW5pY2F0aW9uCiAgICAgICAgICAgIG5ldHdvcmsgcHJvdmlkaW5nIHN1cHBvcnQgYW5kL29yIHNlcnZpY2UgdG8gc3Vic2NyaWJlcnMuIEFuIE1FCiAgICAgICAgICAgIGNvbW11bmljYXRlcyB3aXRoIGEgbWFuYWdlciBhcHBsaWNhdGlvbiAoZGlyZWN0bHkgb3IgaW5kaXJlY3RseSkKICAgICAgICAgICAgb3ZlciBvbmUgb3IgbW9yZSBpbnRlcmZhY2VzIGZvciB0aGUgcHVycG9zZSBvZiBiZWluZyBtb25pdG9yZWQKICAgICAgICAgICAgYW5kL29yIGNvbnRyb2xsZWQuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CiAgICB9Cn0= +o-ran-smo-teiv-ran urn:o-ran:smo-teiv-ran RAN [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJhbiB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtcmFuIjsKICAgIHByZWZpeCBvci10ZWl2LXJhbjsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgXzNncHAtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggdHlwZXMzZ3BwOyB9CgogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgICAgICBwcmVmaXggZ2VvOwogICAgICAgIHJlZmVyZW5jZSAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgUkFOIGRvbWFpbiwKICAgIHdoaWNoIHJlcHJlc2VudHMgdGhlIGZ1bmN0aW9uYWwgY2FwYWJpbGl0eSBvZiB0aGUgZGVwbG95ZWQgUkFOIHRoYXQgYXJlCiAgICByZWxldmFudCB0byByQXBwcyB1c2UgY2FzZXMuIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0yNCIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIG9yLXRlaXYteWV4dDpkb21haW4gUkFOOwoKICAgIGxpc3QgR05CRFVGdW5jdGlvbiB7CiAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQiBEaXN0cmlidXRlZCBVbml0IChnTkItRFUpLgoKICAgICAgICAgICAgQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ2VudHJhbGl6ZWQgVW5pdCAoZ05CLUNVKSBhbmQgYSBnTkItRFUuCiAgICAgICAgICAgIFRoZSBDVSBwcm9jZXNzZXMgbm9uLXJlYWwgdGltZSBwcm90b2NvbHMgYW5kIHNlcnZpY2VzLCBhbmQgdGhlIERVCiAgICAgICAgICAgIHByb2Nlc3NlcyBQSFkgbGV2ZWwgcHJvdG9jb2wgYW5kIHJlYWwgdGltZSBzZXJ2aWNlcy4gVGhlIGdOQi1DVSBhbmQKICAgICAgICAgICAgdGhlIGdOQi1EVSB1bml0cyBhcmUgY29ubmVjdGVkIHZpYSBGMSBsb2dpY2FsIGludGVyZmFjZS4KCiAgICAgICAgICAgIFRoZSBmb2xsb3dpbmcgaXMgdHJ1ZSBmb3IgYSBnTkItRFU6CiAgICAgICAgICAgIElzIGNvbm5lY3RlZCB0byB0aGUgZ05CLUNVLUNQIHRocm91Z2ggdGhlIEYxLUMgaW50ZXJmYWNlLiBJcwogICAgICAgICAgICBjb25uZWN0ZWQgdG8gdGhlIGdOQi1DVS1VUCB0aHJvdWdoIHRoZSBGMS1VIGludGVyZmFjZS4gT25lIGdOQi1EVSBpcwogICAgICAgICAgICBjb25uZWN0ZWQgdG8gb25seSBvbmUgZ05CLUNVLUNQLiBPbmUgZ05CLURVIGNhbiBiZSBjb25uZWN0ZWQgdG8KICAgICAgICAgICAgbXVsdGlwbGUgZ05CLUNVLVVQcyB1bmRlciB0aGUgY29udHJvbCBvZiB0aGUgc2FtZSBnTkItQ1UtQ1AuCgogICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUgZ05CLUNVLVVQcyBhbmQKICAgICAgICAgICAgbXVsdGlwbGUgZ05CLURVcy4gZ05CLURVIGlzIGEgY29uY3JldGUgY2xhc3MgdGhhdCBleHRlbmRzIHRoZSBORy1SQU4KICAgICAgICAgICAgbm9kZSBvYmplY3QuIEluIFRvcG9sb2d5LCB5b3UgY2FuIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlCiAgICAgICAgICAgIHRoZSBnTkItRFUgb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGNvbnRhaW5lciBkVXBMTU5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBpZGVudGlmaWVyIHVzZWQgYXMgcGFydCBvZiBQTSBFdmVudHMgZGF0YSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZ05CRFVJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBEVSB3aXRoaW4gYSBnTm9kZUIiOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEdOQkNVQ1BGdW5jdGlvbiB7CiAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQiBDZW50cmFsaXplZCBVbml0IENvbnRyb2wgUGxhbmUgKGdOQi1DVS1DUCkKCiAgICAgICAgICAgIFRoaXMgaXMgYSBsb2dpY2FsIG5vZGUgaG9zdGluZyB0aGUgUmFkaW8gUmVzb3VyY2UgQ29udHJvbCAoUlJDKSBhbmQKICAgICAgICAgICAgdGhlIGNvbnRyb2wgcGxhbmUgcGFydCBvZiB0aGUgUGFja2V0IERhdGEgQ29udmVyZ2VuY2UgUHJvdG9jb2wKICAgICAgICAgICAgKFBEQ1ApIG9mIHRoZSBnTm9kZUIgQ2VudHJhbGl6ZWQgVW5pdCAoZ05CLUNVKSBmb3IgYW4gRS1VVFJBTiBnTm9kZUIKICAgICAgICAgICAgKGVuLWdOQikgb3IgYSBnTm9kZUIgKGdOQikuIFRoZSBnTkItQ1UtQ1AgdGVybWluYXRlcyB0aGUgRTEKICAgICAgICAgICAgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTkItQ1UtVVAgYW5kIHRoZSBGMS1DIGludGVyZmFjZQogICAgICAgICAgICBjb25uZWN0ZWQgd2l0aCB0aGUgZ05vZGVCIERpc3RyaWJ1dGVkIFVuaXQgKGdOQi1EVSkuCgogICAgICAgICAgICBUaGUgZm9sbG93aW5nIGlzIHRydWUgZm9yIGEgZ05CLUNVLUNQOgogICAgICAgICAgICBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1EVSB0aHJvdWdoIHRoZSBGMS1DIGludGVyZmFjZS4gSXMgY29ubmVjdGVkCiAgICAgICAgICAgIHRvIHRoZSBnTkItQ1UtVVAgdGhyb3VnaCB0aGUgRTEgaW50ZXJmYWNlLiBPbmx5IG9uZSBnTkItQ1UtQ1AgaXMKICAgICAgICAgICAgY29ubmVjdGVkIHRvIG9uZSBnTkItRFUuIE9ubHkgb25lIGdOQi1DVS1DUCBpcyBjb25uZWN0ZWQgdG8gb25lCiAgICAgICAgICAgIGdOQi1DVS1VUC4gT25lIGdOQi1EVSBjYW4gYmUgY29ubmVjdGVkIHRvIG11bHRpcGxlIGdOQi1DVS1VUHMgdW5kZXIKICAgICAgICAgICAgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLk9uZSBnTkItQ1UtVVAgY2FuIGJlIGNvbm5lY3RlZCB0bwogICAgICAgICAgICBtdWx0aXBsZSBEVXMgdW5kZXIgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLgoKICAgICAgICAgICAgTm90ZTogQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ1UtQ1AsIG11bHRpcGxlIGdOQi1DVS1VUHMgYW5kCiAgICAgICAgICAgIG11bHRpcGxlIGdOQi1EVXMuIEEgZ05CLUNVLUNQIGlzIGEgY29uY3JldGUgY2xhc3MgdGhhdCBleHRlbmRzIHRoZQogICAgICAgICAgICBORy1SQU4gbm9kZSBvYmplY3QuIEluIFRvcG9sb2d5LCB5b3UgY2FuIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQKICAgICAgICAgICAgZGVsZXRlIHRoZSBnTkItQ1UtQ1Agb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZ05CQ1VOYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIGdOb2RlQi1DVSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIHBMTU5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBpZGVudGlmaWVyIHRvIGJlIHVzZWQgYXMgcGFydCBvZiBnbG9iYWwgUkFOCiAgICAgICAgICAgICAgICAgICAgbm9kZSBpZGVudGl0eSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBHTkJDVVVQRnVuY3Rpb24gewogICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUIgQ2VudHJhbGl6ZWQgVW5pdCBVc2VyIFBsYW5lIChnTkItQ1UtVVApCgogICAgICAgICAgICBBIGdOQi1DVS1VUCBpcyBhIGxvZ2ljYWwgbm9kZSBob3N0aW5nIHRoZSBVc2VyIFBsYW5lIHBhcnQgb2YgdGhlCiAgICAgICAgICAgIFBhY2tldCBEYXRhIENvbnZlcmdlbmNlLCBQcm90b2NvbCAoUERDUCkgb2YgdGhlIGdOb2RlQiBDZW50cmFsaXplZAogICAgICAgICAgICBVbml0IChnTkItQ1UpIGZvciBhbiBFLVVUUkFOIGdOb2RlQiAoZW4tZ05CKSwgYW5kIHRoZSBVc2VyIFBsYW5lCiAgICAgICAgICAgIHBhcnQgb2YgdGhlIFBEQ1AgcHJvdG9jb2wgYW5kIHRoZSBTZXJ2aWNlIERhdGEgQWRhcHRhdGlvbiBQcm90b2NvbAogICAgICAgICAgICAoU0RBUCkgb2YgdGhlIGdOQi1DVSBmb3IgYSBnTm9kZUIgKGdOQikuIFRoZSBnTkItQ1UtVVAgdGVybWluYXRlcwogICAgICAgICAgICB0aGUgRTEgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTkItQ1UtQ1AgYW5kIHRoZSBGMS1VIGludGVyZmFjZQogICAgICAgICAgICBjb25uZWN0ZWQgd2l0aCB0aGUgZ05vZGVCIERpc3RyaWJ1dGVkIFVuaXQgKGdOQi1EVSkuCgogICAgICAgICAgICBUaGUgZm9sbG93aW5nIGlzIHRydWUgZm9yIGEgZ05CLUNVLVVQOgogICAgICAgICAgICBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1EVSB0aHJvdWdoIHRoZSBGMS1VIGludGVyZmFjZS4gSXMgY29ubmVjdGVkCiAgICAgICAgICAgIHRvIHRoZSBnTkItQ1UtQ1AgdGhyb3VnaCB0aGUgRTEgaW50ZXJmYWNlLiBPbmUgZ05CLUNVLVVQIGlzCiAgICAgICAgICAgIGNvbm5lY3RlZCB0byBvbmx5IG9uZSBnTkItQ1UtQ1AuIE9uZSBnTkItRFUgY2FuIGJlIGNvbm5lY3RlZCB0bwogICAgICAgICAgICBtdWx0aXBsZSBnTkItQ1UtVVBzIHVuZGVyIHRoZSBjb250cm9sIG9mIHRoZSBzYW1lIGdOQi1DVS1DUC4gT25lCiAgICAgICAgICAgIGdOQi1DVS1VUCBjYW4gYmUgY29ubmVjdGVkIHRvIG11bHRpcGxlIERVcyB1bmRlciB0aGUgY29udHJvbCBvZiB0aGUKICAgICAgICAgICAgc2FtZSBnTkItQ1UtQ1AuCgogICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUgZ05CLUNVLVVQcyBhbmQKICAgICAgICAgICAgbXVsdGlwbGUgZ05CLURVcy4gQSBnTkItQ1UtVVAgaXMgYSBjb25jcmV0ZSBjbGFzcyB0aGF0IGV4dGVuZHMgdGhlCiAgICAgICAgICAgIE5HLVJBTiBub2RlIG9iamVjdC4gSW4gVG9wb2xvZ3ksIHlvdSBjYW4gY3JlYXRlLCByZWFkLCB1cGRhdGUsIGFuZAogICAgICAgICAgICBkZWxldGUgdGhlIGdOQi1DVS1VUCBvYmplY3QuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IE5SQ2VsbENVIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyBhbiBOUiBDZWxsIGluIGdOb2RlQi1DVS4KCiAgICAgICAgICAgIDVHIE5SIGlzIGEgbmV3IHJhZGlvIGFjY2VzcyB0ZWNobm9sb2d5IChSQVQpIGRldmVsb3BlZCBieSAzR1BQIGZvcgogICAgICAgICAgICB0aGUgNUcgKGZpZnRoIGdlbmVyYXRpb24pIG1vYmlsZSBuZXR3b3JrLiBJdCBpcyBkZXNpZ25lZCB0byBiZSB0aGUKICAgICAgICAgICAgZ2xvYmFsIHN0YW5kYXJkIGZvciB0aGUgYWlyIGludGVyZmFjZSBvZiA1RyBuZXR3b3Jrcy4KCiAgICAgICAgICAgIDVHIE5SIGhhcyBzeW5jaHJvbml6YXRpb24gc2lnbmFsIHRoYXQgaXMga25vd24gYXMgUHJpbWFyeQogICAgICAgICAgICBTeW5jaHJvbml6YXRpb24gU2lnbmFsIChQU1MpIGFuZCBTZWNvbmRhcnkgU3luY2hyb25pemF0aW9uCiAgICAgICAgICAgIFNpZ25hbCAoU1NTKS4gVGhlc2Ugc2lnbmFscyBhcmUgc3BlY2lmaWMgdG8gTlIgcGh5c2ljYWwgbGF5ZXIgYW5kCiAgICAgICAgICAgIHByb3ZpZGUgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbiByZXF1aXJlZCBieSBVRSBmb3IgZG93bmxpbmsKICAgICAgICAgICAgc3luY2hyb25pemF0aW9uOiBQU1MgcHJvdmlkZXMgUmFkaW8gRnJhbWUgQm91bmRhcnkgKFBvc2l0aW9uIG9mIDFzdAogICAgICAgICAgICBTeW1ib2wgaW4gYSBSYWRpbyBmcmFtZSkgU1NTIHByb3ZpZGVzIFN1YmZyYW1lIEJvdW5kYXJ5IChQb3NpdGlvbiBvZgogICAgICAgICAgICAxc3QgU3ltYm9sIGluIGEgU3ViZnJhbWUpIFBoeXNpY2FsIExheWVyIENlbGwgSUQgKFBDSSkgaW5mb3JtYXRpb24KICAgICAgICAgICAgdXNpbmcgYm90aCBQU1MgYW5kIFNTUy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGNlbGxMb2NhbElkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJVc2VkIHRvZ2V0aGVyIHdpdGggZ05vZGVCIGlkZW50aWZpZXIgdG8gaWRlbnRpZnkgTlIKICAgICAgICAgICAgICAgICAgICBjZWxsIGluIFBMTU4uIFVzZWQgdG9nZXRoZXIgd2l0aCBnTkJJZCB0byBmb3JtIE5DSS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIHBsbW5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBJRCBmb3IgTlIgQ0dJLiBJZiBlbXB0eSwKICAgICAgICAgICAgICAgICAgICBHTkJDVUNQRnVuY3Rpb246OnBMTU5JZCBpcyB1c2VkIGZvciBQTE1OIElEIGluIE5SIENHSSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgbkNJIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsIElkZW50aXR5IjsKICAgICAgICAgICAgICAgIHR5cGUgaW50NjQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgblJUQUMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKSI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTlJDZWxsRFUgewogICAgICAgIGRlc2NyaXB0aW9uICJSZXByZXNlbnRzIGFuIE5SIENlbGwgaW4gZ05vZGVCLURVLgoKICAgICAgICAgICAgNUcgTlIgaXMgYSBuZXcgcmFkaW8gYWNjZXNzIHRlY2hub2xvZ3kgKFJBVCkgZGV2ZWxvcGVkIGJ5IDNHUFAgZm9yCiAgICAgICAgICAgIHRoZSA1RyAoZmlmdGggZ2VuZXJhdGlvbikgbW9iaWxlIG5ldHdvcmsuIEl0IGlzIGRlc2lnbmVkIHRvIGJlIHRoZQogICAgICAgICAgICBnbG9iYWwgc3RhbmRhcmQgZm9yIHRoZSBhaXIgaW50ZXJmYWNlIG9mIDVHIG5ldHdvcmtzLgoKICAgICAgICAgICAgNUcgTlIgaGFzIHN5bmNocm9uaXphdGlvbiBzaWduYWwgdGhhdCBpcyBrbm93biBhcyBQcmltYXJ5CiAgICAgICAgICAgIFN5bmNocm9uaXphdGlvbiBzaWduYWwgKFBTUykgYW5kIFNlY29uZGFyeSBTeW5jaHJvbml6YXRpb24gc2lnbmFsCiAgICAgICAgICAgIChTU1MpLiBUaGVzZSBzaWduYWxzIGFyZSBzcGVjaWZpYyB0byBOUiBwaHlzaWNhbCBsYXllciBhbmQgcHJvdmlkZQogICAgICAgICAgICB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uIHJlcXVpcmVkIGJ5IFVFIGZvciBkb3dubGluawogICAgICAgICAgICBzeW5jaHJvbml6YXRpb246IFBTUyBwcm92aWRlcyBSYWRpbyBGcmFtZSBCb3VuZGFyeSAoUG9zaXRpb24gb2YgMXN0CiAgICAgICAgICAgIFN5bWJvbCBpbiBhIFJhZGlvIGZyYW1lKSBTU1MgcHJvdmlkZXMgU3ViZnJhbWUgQm91bmRhcnkgKFBvc2l0aW9uIG9mCiAgICAgICAgICAgIDFzdCBTeW1ib2wgaW4gYSBTdWJmcmFtZSkgUGh5c2ljYWwgTGF5ZXIgQ2VsbCBJRCAoUENJKSBpbmZvcm1hdGlvbgogICAgICAgICAgICB1c2luZyBib3RoIFBTUyBhbmQgU1NTLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgY2VsbExvY2FsSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVzZWQgdG9nZXRoZXIgd2l0aCBnTm9kZUIgaWRlbnRpZmllciB0byBpZGVudGlmeSBOUgogICAgICAgICAgICAgICAgICAgIGNlbGwgaW4gUExNTi4gVXNlZCB0b2dldGhlciB3aXRoIGdOQklkIHRvIGZvcm0gTkNJLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG5DSSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbCBJZGVudGl0eS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBuUlBDSSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIFBoeXNpY2FsIENlbGwgSWRlbnRpdHkgKFBDSSkgb2YgdGhlIE5SIGNlbGwuIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgblJUQUMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEVOb2RlQkZ1bmN0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gRXZvbHZlZCBOb2RlIEIgKGVOb2RlQikgaXMgdGhlIG9ubHkgbWFuZGF0b3J5IG5vZGUgaW4KICAgICAgICAgICAgdGhlIHJhZGlvIGFjY2VzcyBuZXR3b3JrIChSQU4pIG9mIExvbmctVGVybSBFdm9sdXRpb24gKExURSkuIFRoZQogICAgICAgICAgICBlTm9kZUIgaXMgYSBjb21wbGV4IGJhc2Ugc3RhdGlvbiB0aGF0IGhhbmRsZXMgcmFkaW8gY29tbXVuaWNhdGlvbnMKICAgICAgICAgICAgaW4gdGhlIGNlbGwgYW5kIGNhcnJpZXMgb3V0IHJhZGlvIHJlc291cmNlIG1hbmFnZW1lbnQgYW5kIGhhbmRvdmVyCiAgICAgICAgICAgIGRlY2lzaW9ucy4gVW5saWtlIDIvM0cgd2lyZWxlc3MgUkFOLCB0aGVyZSBpcyBubyBjZW50cmFsaXplZCByYWRpbwogICAgICAgICAgICBuZXR3b3JrIGNvbnRyb2xsZXIgaW4gTFRFLiBJdCBpcyB0aGUgaGFyZHdhcmUgdGhhdCBpcyBjb25uZWN0ZWQgdG8KICAgICAgICAgICAgdGhlIG1vYmlsZSBwaG9uZSBuZXR3b3JrIHRoYXQgY29tbXVuaWNhdGVzIGRpcmVjdGx5IHdpdGggbW9iaWxlCiAgICAgICAgICAgIGhhbmRzZXRzIChVc2VyIEVxdWlwbWVudCksIGxpa2UgYSBiYXNlIHRyYW5zY2VpdmVyIHN0YXRpb24gKEJUUykgaW4KICAgICAgICAgICAgR1NNIG5ldHdvcmtzLiBUaGlzIHNpbXBsaWZpZXMgdGhlIGFyY2hpdGVjdHVyZSBhbmQgYWxsb3dzIGxvd2VyCiAgICAgICAgICAgIHJlc3BvbnNlIHRpbWVzLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZU5CSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgSUQgdGhhdCBmb3JtcyBwYXJ0IG9mIHRoZSBDZWxsIEdsb2JhbAogICAgICAgICAgICAgICAgICAgIElkZW50aXR5LCBhbmQgaXMgYWxzbyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBub2RlIG92ZXIgdGhlIFMxCiAgICAgICAgICAgICAgICAgICAgaW50ZXJmYWNlIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBlTm9kZUJQbG1uSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgUHVibGljIExhbmQgTW9iaWxlIE5ldHdvcmsgKFBMTU4pIElECiAgICAgICAgICAgICAgICAgICAgdGhhdCBmb3JtcyBwYXJ0IG9mIHRoZSBFTm9kZUIgR2xvYmFsIElEIHVzZWQgdG8gaWRlbnRpZnkgdGhlCiAgICAgICAgICAgICAgICAgICAgbm9kZSBvdmVyIHRoZSBTMSBpbnRlcmZhY2UuIE5vdGU6IFRoZSB2YWx1ZQogICAgICAgICAgICAgICAgICAgIChNQ0M9MDAxLCBNTkM9MDEpIGluZGljYXRlcyB0aGF0IHRoZSBQTE1OIGlzIG5vdCBpbml0aWF0ZWQuCiAgICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIGNhbiBub3QgYmUgdXNlZCBhcyBhIHZhbGlkIFBMTU4gSWRlbnRpdHkuIjsKCiAgICAgICAgICAgICAgICBsZWFmIG1jYyB7CiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBNQ0MgcGFydCBvZiBhIFBMTU4gaWRlbnRpdHkgdXNlZCBpbiB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgcmFkaW8gbmV0d29yay4iOwogICAgICAgICAgICAgICAgICAgIHR5cGUgaW50MzIgewogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSAwLi45OTk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGVhZiBtbmMgewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTU5DIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5IHVzZWQgaW4gdGhlCiAgICAgICAgICAgICAgICAgICAgICAgIHJhZGlvIG5ldHdvcmsuIjsKICAgICAgICAgICAgICAgICAgICB0eXBlIGludDMyIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgMC4uOTk5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxlYWYgbW5jTGVuZ3RoIHsKICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGxlbmd0aCBvZiB0aGUgTU5DIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5CiAgICAgICAgICAgICAgICAgICAgICAgIHVzZWQgaW4gdGhlIHJhZGlvIG5ldHdvcmsuIjsKICAgICAgICAgICAgICAgICAgICB0eXBlIGludDMyIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgMi4uMzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBFVXRyYW5DZWxsIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyBhbiBGREQgb3IgVEREIEVVdHJhbkNlbGwgYW5kCiAgICAgICAgICAgICAgICAgICAgY29udGFpbnMgcGFyYW1ldGVycyBuZWVkZWQgYnkgdGhlIGNlbGwuCiAgICAgICAgICAgICAgICAgICAgSXQgYWxzbyBjb250YWlucyBwYXJhbWV0ZXJzIGZvciB0aGUKICAgICAgICAgICAgICAgICAgICBtYW5kYXRvcnkgY29tbW9uIGNoYW5uZWxzLiBBbiBFVVRSQU4gc3RhbmRzCiAgICAgICAgICAgICAgICAgICAgZm9yIEV2b2x2ZWQgVW5pdmVyc2FsIE1vYmlsZSBUZWxlY29tbXVuaWNhdGlvbnMKICAgICAgICAgICAgICAgICAgICBTeXN0ZW0gKFVNVFMpIFRlcnJlc3RyaWFsIFJhZGlvIEFjY2VzcyBOZXR3b3JrCiAgICAgICAgICAgICAgICAgICAgd2hpY2ggY29udGFpbnMgYW4gZU5vZGVCLiBUaGUgZU5vZGVCIGNvbmNyZXRlCiAgICAgICAgICAgICAgICAgICAgY2xhc3MgaXMgZXh0ZW5kZWQgZnJvbSB0aGUgRVVUUkFOIE5vZGUgYWJzdHJhY3QgY2xhc3MuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBjZWxsSWR7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUkJTIGludGVybmFsIElEIGF0dHJpYnV0ZSBmb3IgRVV0cmFuQ2VsbC4gTXVzdCBiZQogICAgICAgICAgICAgICAgICAgIHVuaXF1ZSBpbiB0aGUgUkJTLiBUb2dldGhlciB3aXRoIHRoZSBOb2RlIElEIGFuZCBQdWJsaWMKICAgICAgICAgICAgICAgICAgICBMYW5kIE1vYmlsZSBOZXR3b3JrIChQTE1OKSB0aGlzIGlzIGEgdW5pdmVyc2FsbHkgdW5pcXVlCiAgICAgICAgICAgICAgICAgICAgY2VsbCBJRCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVhcmZjbmRsIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgY2hhbm5lbCBudW1iZXIgZm9yIHRoZSBjZW50cmFsIGRvd25saW5rCiAgICAgICAgICAgICAgICAgICAgZnJlcXVlbmN5LiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVhcmZjbnVsIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJDaGFubmVsIG51bWJlciBmb3IgdGhlIGNlbnRyYWwgdXBsaW5rIGZyZXF1ZW5jeSI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGRsQ2hhbm5lbEJhbmR3aWR0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGRvd25saW5rIGNoYW5uZWwgYmFuZHdpZHRoIGluIHRoZSBGREQgY2VsbC4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBlYXJmY24gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFLVVUUkEgQWJzb2x1dGUgUmFkaW8gRnJlcXVlbmN5IENoYW5uZWwgTnVtYmVyCiAgICAgICAgICAgICAgICAgICAgKEVBUkZDTikgZm9yIHRoZSBUREQgY2VsbCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGNoYW5uZWxCYW5kd2lkdGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjaGFubmVsIGJhbmR3aWR0aCBpbiB0aGUgVEREIGNlbGwuIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgdGFjIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUcmFja2luZyBBcmVhIENvZGUgZm9yIHRoZSBFVXRyYW4gQ2VsbCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGR1cGxleFR5cGUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkluZGljYXRvciBvZiBFVXRyYW5DZWxsIHR5cGUsIEZERCBvciBUREQiOwogICAgICAgICAgICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgZW51bSBmZGQgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAwOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiRkREIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSB0ZGQgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAxOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVEREIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBOUlNlY3RvckNhcnJpZXIgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTlIgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZSBhdHRyaWJ1dGVzIGZvcgogICAgICAgICAgICBkZWZpbmluZyB0aGUgbG9naWNhbCBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBjYXJyaWVyIChjZWxsKSBpbiBhCiAgICAgICAgICAgIHNlY3Rvci4gQSBzZWN0b3IgaXMgYSBjb3ZlcmFnZSBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbgogICAgICAgICAgICBoYXZpbmcgaXRzIG93biBhbnRlbm5hcywgcmFkaW8gcG9ydHMsIGFuZCBjb250cm9sIGNoYW5uZWxzLiBUaGUKICAgICAgICAgICAgY29uY2VwdCBvZiBzZWN0b3JzIHdhcyBkZXZlbG9wZWQgdG8gaW1wcm92ZSBjby1jaGFubmVsIGludGVyZmVyZW5jZQogICAgICAgICAgICBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zIHVzZSB0aHJlZSBzZWN0b3IKICAgICAgICAgICAgY2VsbHMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBhcmZjbkRMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBBYnNvbHV0ZSBSYWRpbyBGcmVxdWVuY3kgQ2hhbm5lbCBOdW1iZXIKICAgICAgICAgICAgICAgICAgICAoTlItQVJGQ04pIGZvciBkb3dubGluayI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGFyZmNuVUwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIEFic29sdXRlIFJhZGlvIGZyZXF1ZW5jeSBDaGFubmVsIE51bWJlcgogICAgICAgICAgICAgICAgICAgIChOUi1BUkZDTikgZm9yIHVwbGluay4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBmcmVxdWVuY3lETCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUkYgUmVmZXJlbmNlIEZyZXF1ZW5jeSBvZiBkb3dubGluayBjaGFubmVsIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZnJlcXVlbmN5VUwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlJGIFJlZmVyZW5jZSBGcmVxdWVuY3kgb2YgdXBsaW5rIGNoYW5uZWwiOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBiU0NoYW5uZWxCd0RMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJCUyBDaGFubmVsIGJhbmR3aWR0aCBpbiBNSHogZm9yIGRvd25saW5rLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTFRFU2VjdG9yQ2FycmllciB7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBMVEUgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZSBhdHRyaWJ1dGVzIGZvcgogICAgICAgICAgICBkZWZpbmluZyB0aGUgbG9naWNhbCBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBjYXJyaWVyIChjZWxsKSBpbiBhCiAgICAgICAgICAgIHNlY3Rvci4gQSBzZWN0b3IgaXMgYSBjb3ZlcmFnZSBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbgogICAgICAgICAgICBoYXZpbmcgaXRzIG93biBhbnRlbm5hcywgcmFkaW8gcG9ydHMsIGFuZCBjb250cm9sIGNoYW5uZWxzLiBUaGUKICAgICAgICAgICAgY29uY2VwdCBvZiBzZWN0b3JzIHdhcyBkZXZlbG9wZWQgdG8gaW1wcm92ZSBjby1jaGFubmVsIGludGVyZmVyZW5jZQogICAgICAgICAgICBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zIHVzZSB0aHJlZSBzZWN0b3IKICAgICAgICAgICAgY2VsbHMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBzZWN0b3JDYXJyaWVyVHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoZSBzZWN0b3IgY2FycmllcgogICAgICAgICAgICAgICAgICAgIG1vZGVsbGVkIGJ5IE1PIFNlY3RvckNhcnJpZXIgaXMgYSBkaWdpdGFsIHNlY3Rvci4iOwogICAgICAgICAgICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgZW51bSBub3JtYWxfc2VjdG9yIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgMDsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5vdCBhIGRpZ2l0YWwgc2VjdG9yIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBsZWZ0X2RpZ2l0YWxfc2VjdG9yIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgMTsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxlZnQgZGlnaXRhbCBzZWN0b3IgZm9yIDJEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gcmlnaHRfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAyOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmlnaHQgZGlnaXRhbCBzZWN0b3IgZm9yIDJEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gbGVmdF9kaWdpdGFsX3NlY3Rvcl8zZHMgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAzOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVmdCBkaWdpdGFsIHNlY3RvciBmb3IgM0RTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSByaWdodF9kaWdpdGFsX3NlY3Rvcl8zZHMgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA0OwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmlnaHQgZGlnaXRhbCBzZWN0b3IgZm9yIDNEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gbWlkZGxlX2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDU7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNaWRkbGUgZGlnaXRhbCBzZWN0b3IgZm9yIDNEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgQW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIE1PIHNlcnZlcyBhcyBhIG1hcHBpbmcgYmV0d2VlbiB0aGUgY2VsbCBhbmQgdGhlIFJCUwogICAgICAgICAgICBlcXVpcG1lbnQgdXNlZCB0byBwcm92aWRlIGNvdmVyYWdlIGluIGEgY2VydGFpbiBnZW9ncmFwaGljYWwgYXJlYS4KICAgICAgICAgICAgVGhlIE1PIGFsc28gY29udHJvbHMgdGhlIG1heGltdW0gb3V0cHV0IHBvd2VyIG9mIHRoZSBzZWN0b3IuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZi1saXN0IGVVdHJhbkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgTFRFIGZyZXF1ZW5jeSBiYW5kcyB0aGF0IGFzc29jaWF0ZWQKICAgICAgICAgICAgICAgICAgICBoYXJkd2FyZSBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZi1saXN0IGdlcmFuRnFCYW5kcyB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGlzdCBvZiBHRVJBTiBmcmVxdWVuY3kgYmFuZHMgdGhhdCBhc3NvY2lhdGVkCiAgICAgICAgICAgICAgICAgICAgaGFyZHdhcmUgc3VwcG9ydHMiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYtbGlzdCBuUkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgTlIgZnJlcXVlbmN5IGJhbmRzIGFzc29jaWF0ZWQgaGFyZHdhcmUKICAgICAgICAgICAgICAgICAgICBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IFNlY3RvciB7CiAgICAgICAgZGVzY3JpcHRpb24gIkEgZ3JvdXAgb2YgY28tbG9jYXRlZCBDZWxscyB0aGF0IGhhdmUgYSBzaGFyZWQKICAgICAgICAgICAgY292ZXJhZ2UgYXJlYS4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIHNlY3RvcklkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJVbml2ZXJzYWxseSB1bmlxdWUgSUQgZ2VuZXJhdGVkIGJ5IHRoZSBzZWN0b3IncwogICAgICAgICAgICAgICAgICAgIGRpc2NvdmVyeSBtZWNoYW5pc20uIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDY0OwogICAgICAgICAgICB9CgogICAgICAgICAgICB1c2VzIGdlbzpnZW8tbG9jYXRpb247CgogICAgICAgICAgICBsZWFmIGF6aW11dGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkF2ZXJhZ2UgdmFsdWUgb2YgdGhlIGF6aW11dGhzIG9mIHRoZSBjZWxscwogICAgICAgICAgICAgICAgICAgIGNvbXByaXNpbmcgdGhlIHNlY3RvciwgZGV0ZXJtaW5lZCBkdXJpbmcgc2VjdG9yIGRpc2NvdmVyeS4iOwogICAgICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjR7CiAgICAgICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB1bml0cyAiZGVncmVlcyI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfRVVUUkFOQ0VMTCB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIEVVVFJBTiBDZWxsLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBFTm9kZUJGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBwcm92aWRlZC1ieS1lbm9kZWJGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCBwcm92aWRlZCBieSBlTm9kZUIgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEVVdHJhbkNlbGw7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHByb3ZpZGVkIGJ5IGVOb2RlQiBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTFRFU2VjdG9yQ2FycmllcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBHTkJEVUZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTERVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIENlbGwtRFUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIEdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZ25iZHVGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLURVIHByb3ZpZGVkIGJ5IGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CRFVGVU5DVElPTl9QUk9WSURFU19OUlNFQ1RPUkNBUlJJRVIgeyAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBwcm92aWRlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBHTkJEVUZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmR1RnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgU2VjdG9yIENhcnJpZXIgcHJvdmlkZWQgYnkgZ05vZGVCLURVIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUlNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CQ1VDUEZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTENVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsQ3UgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVQ1AgRnVuY3Rpb24gcHJvdmlkZXMgTlIgQ2VsbC1DVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgR05CQ1VDUEZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLUNVIHByb3ZpZGVkIGJ5IGdOb2RlQi1DVUNQIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUkNlbGxDVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBFVVRSQU5DRUxMX1VTRVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHVzZWQtbHRlU2VjdG9yQ2FycmllciB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCB1c2VzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRVV0cmFuQ2VsbDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgRVVUUkFOIENlbGwuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBMVEVTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMVEUgU2VjdG9yIENhcnJpZXIgdXNlcyBBbnRlbm5hIENhcGFiaWxpdHkuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYtbGlzdCB1c2VkLWJ5LWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTFRFIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBBbnRlbm5hQ2FwYWJpbGl0eTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5SQ0VMTERVX1VTRVNfTlJTRUNUT1JDQVJSSUVSIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSB1c2VzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBOUkNlbGxEVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LW5yQ2VsbER1IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgTlIgQ2VsbC1EVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTlJTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBTZWN0b3IgQ2FycmllciB1c2VzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1ieS1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTlIgU2VjdG9yIENhcnJpZXIuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgU0VDVE9SX0dST1VQU19OUkNFTExEVSB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IGdyb3VwZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBOUiBDZWxsLURVLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBTZWN0b3I7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgZ3JvdXBlZC1ieS1zZWN0b3IgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSBncm91cGVkIGJ5IFNlY3Rvci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBTRUNUT1JfR1JPVVBTX0VVVFJBTkNFTEwgeyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBFVVRSQU4gQ2VsbC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgU2VjdG9yOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGdyb3VwZWQtYnktc2VjdG9yIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkVVVFJBTiBDZWxsIGdyb3VwZWQgYnkgU2VjdG9yLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBFVXRyYW5DZWxsOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQp9 +o-ran-smo-teiv-rel-equipment-ran urn:o-ran:smo-teiv-rel-equipment-ran REL_EQUIPMENT_RAN ["o-ran-smo-teiv-equipment", "o-ran-smo-teiv-ran"] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJlbC1lcXVpcG1lbnQtcmFuIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1yZWwtZXF1aXBtZW50LXJhbiI7CiAgICBwcmVmaXggb3ItdGVpdi1yZWwtZXF1aXByYW47CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsgcHJlZml4IG9yLXRlaXYtdHlwZXM7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7IHByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtZXF1aXBtZW50IHsgcHJlZml4IG9yLXRlaXYtZXF1aXA7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtcmFuIHsgcHJlZml4IG9yLXRlaXYtcmFuOyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiRXF1aXBtZW50IGFuZCBSQU4gdG9wb2xvZ3kgcmVsYXRpb24gbW9kZWwuCgogICAgQ29weXJpZ2h0IChjKSAyMDI0IEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKICAgIFRoaXMgbW9kZWwgY29udGFpbnMgdGhlIHRvcG9sb2d5IHJlbGF0aW9ucyBiZXR3ZWVuIEVxdWlwbWVudCBhbmQgUkFOLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIFJFTF9FUVVJUE1FTlRfUkFOOwoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgQU5URU5OQU1PRFVMRV9TRVJWRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLm0KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBzZXJ2aWNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIENhcGFiaWxpdHkgc2VydmljZWQgYnkgdGhpcyBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1lcXVpcDpBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1hbnRlbm5hTW9kdWxlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIHNlcnZlcyB0aGlzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46QW50ZW5uYUNhcGFiaWxpdHk7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBTRUNUT1JfR1JPVVBTX0FOVEVOTkFNT0RVTEUgeyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWFudGVubmFNb2R1bGUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1yYW46U2VjdG9yOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGdyb3VwZWQtYnktc2VjdG9yIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIGdyb3VwZWQgYnkgU2VjdG9yLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LWVxdWlwOkFudGVubmFNb2R1bGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9Cn0= +o-ran-smo-teiv-rel-oam-ran urn:o-ran:smo-teiv-rel-oam-ran REL_OAM_RAN ["o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran"] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJlbC1vYW0tcmFuIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1yZWwtb2FtLXJhbiI7CiAgICBwcmVmaXggb3ItdGVpdi1yZWwtb2FtcmFuOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgeyBwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LW9hbSB7IHByZWZpeCBvci10ZWl2LW9hbTsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1yYW4geyBwcmVmaXggb3ItdGVpdi1yYW47IH0KCiAgICBvcmdhbml6YXRpb24gIk9SQU4iOwogICAgY29udGFjdCAiVGhlIEF1dGhvcnMiOwogICAgZGVzY3JpcHRpb24KICAgICJSQU4gTyZNIHRvIExvZ2ljYWwgdG9wb2xvZ3kgbW9kZWwuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIE8mTSB0byBMb2dpY2FsIHRvcG9sb2d5IHJlbGF0aW9ucwoKICAgIENvcHlyaWdodCAoQykgMjAyNCBFcmljc3NvbgogICAgTW9kaWZpY2F0aW9ucyBDb3B5cmlnaHQgKEMpIDIwMjQgT3BlbkluZnJhIEZvdW5kYXRpb24gRXVyb3BlCgogICAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsKICAgIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4KICAgIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKICAgIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICAgIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywKICAgIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogICAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogICAgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgogICAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAiOwoKICAgIHJldmlzaW9uICIyMDI0LTA1LTI0IiB7CiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmRvbWFpbiBSRUxfT0FNX1JBTjsKCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX01BTkFHRVNfRU5PREVCRlVOQ1RJT04geyAgIC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IG1hbmFnZXMgZU5vZGVCIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBvci10ZWl2LW9hbTpNYW5hZ2VkRWxlbWVudDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBtYW5hZ2VkLWJ5LW1hbmFnZWRFbGVtZW50IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImVOb2RlQiBGdW5jdGlvbiBtYW5hZ2VkIGJ5IE1hbmFnZWQgRWxlbWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46RU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJEVUZVTkNUSU9OIHsgICAgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgbWFuYWdlZC1nbmJkdUZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1hbmFnZWQgRWxlbWVudCBtYW5hZ2VzIGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1vYW06TWFuYWdlZEVsZW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgbWFuYWdlZC1ieS1tYW5hZ2VkRWxlbWVudCB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItRFUgRnVuY3Rpb24gbWFuYWdlZCBieSBNYW5hZ2VkIEVsZW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVUNQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtQ1AgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLUNQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVUNQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVVVQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1dXBGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtVVAgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLVVQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVVVQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQp9 +\. + +COPY ties_model.entity_info("storedAt", "name", "moduleReferenceName") FROM stdin; +o-ran-smo-teiv-equipment_AntennaModule AntennaModule o-ran-smo-teiv-equipment +o-ran-smo-teiv-equipment_Site Site o-ran-smo-teiv-equipment +o-ran-smo-teiv-oam_ManagedElement ManagedElement o-ran-smo-teiv-oam +o-ran-smo-teiv-ran_AntennaCapability AntennaCapability o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_ENodeBFunction ENodeBFunction o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_EUtranCell EUtranCell o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_GNBCUCPFunction GNBCUCPFunction o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_GNBCUUPFunction GNBCUUPFunction o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_GNBDUFunction GNBDUFunction o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_LTESectorCarrier LTESectorCarrier o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_NRCellCU NRCellCU o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_NRCellDU NRCellDU o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_NRSectorCarrier NRSectorCarrier o-ran-smo-teiv-ran +o-ran-smo-teiv-ran_Sector Sector o-ran-smo-teiv-ran +\. + +COPY ties_model.relationship_info("name", "aSideAssociationName", "aSideMOType", "aSideModule", "aSideMinCardinality", "aSideMaxCardinality", "bSideAssociationName", "bSideMOType", "bSideModule", "bSideMinCardinality", "bSideMaxCardinality", "associationKind", "connectSameEntity", "relationshipDataLocation", "storedAt", "moduleReferenceName") FROM stdin; +ANTENNAMODULE_INSTALLED_AT_SITE installed-at-site AntennaModule o-ran-smo-teiv-equipment 0 9223372036854775807 installed-antennaModule Site o-ran-smo-teiv-equipment 0 1 BI_DIRECTIONAL false A_SIDE o-ran-smo-teiv-equipment_AntennaModule o-ran-smo-teiv-equipment +ANTENNAMODULE_SERVES_ANTENNACAPABILITY serviced-antennaCapability AntennaModule o-ran-smo-teiv-equipment 0 9223372036854775807 serving-antennaModule AntennaCapability o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false RELATION o-ran-smo-teiv-rel-equipment-ran_ANTENNAMODULE_SERVES_ANTENNACAPABILITY o-ran-smo-teiv-rel-equipment-ran +ENODEBFUNCTION_PROVIDES_EUTRANCELL provided-euTranCell ENodeBFunction o-ran-smo-teiv-ran 1 1 provided-by-enodebFunction EUtranCell o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_EUtranCell o-ran-smo-teiv-ran +ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER provided-lteSectorCarrier ENodeBFunction o-ran-smo-teiv-ran 1 1 provided-by-enodebFunction LTESectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_LTESectorCarrier o-ran-smo-teiv-ran +EUTRANCELL_USES_LTESECTORCARRIER used-lteSectorCarrier EUtranCell o-ran-smo-teiv-ran 0 1 used-by-euTranCell LTESectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_LTESectorCarrier o-ran-smo-teiv-ran +GNBCUCPFUNCTION_PROVIDES_NRCELLCU provided-nrCellCu GNBCUCPFunction o-ran-smo-teiv-ran 1 1 provided-by-gnbcucpFunction NRCellCU o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_NRCellCU o-ran-smo-teiv-ran +GNBDUFUNCTION_PROVIDES_NRCELLDU provided-nrCellDu GNBDUFunction o-ran-smo-teiv-ran 1 1 provided-by-gnbduFunction NRCellDU o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_NRCellDU o-ran-smo-teiv-ran +GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER provided-nrSectorCarrier GNBDUFunction o-ran-smo-teiv-ran 1 1 provided-by-gnbduFunction NRSectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_NRSectorCarrier o-ran-smo-teiv-ran +LTESECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability LTESectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 used-by-lteSectorCarrier AntennaCapability o-ran-smo-teiv-ran 0 1 BI_DIRECTIONAL false A_SIDE o-ran-smo-teiv-ran_LTESectorCarrier o-ran-smo-teiv-ran +MANAGEDELEMENT_MANAGES_ENODEBFUNCTION managed-enodebFunction ManagedElement o-ran-smo-teiv-oam 1 1 managed-by-managedElement ENodeBFunction o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_ENodeBFunction o-ran-smo-teiv-rel-oam-ran +MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION managed-gnbcucpFunction ManagedElement o-ran-smo-teiv-oam 1 1 managed-by-managedElement GNBCUCPFunction o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_GNBCUCPFunction o-ran-smo-teiv-rel-oam-ran +MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION managed-gnbcuupFunction ManagedElement o-ran-smo-teiv-oam 1 1 managed-by-managedElement GNBCUUPFunction o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_GNBCUUPFunction o-ran-smo-teiv-rel-oam-ran +MANAGEDELEMENT_MANAGES_GNBDUFUNCTION managed-gnbduFunction ManagedElement o-ran-smo-teiv-oam 1 1 managed-by-managedElement GNBDUFunction o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_GNBDUFunction o-ran-smo-teiv-rel-oam-ran +NRCELLDU_USES_NRSECTORCARRIER used-nrSectorCarrier NRCellDU o-ran-smo-teiv-ran 0 1 used-by-nrCellDu NRSectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_NRSectorCarrier o-ran-smo-teiv-ran +NRSECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability NRSectorCarrier o-ran-smo-teiv-ran 0 9223372036854775807 used-by-nrSectorCarrier AntennaCapability o-ran-smo-teiv-ran 0 1 BI_DIRECTIONAL false A_SIDE o-ran-smo-teiv-ran_NRSectorCarrier o-ran-smo-teiv-ran +SECTOR_GROUPS_ANTENNAMODULE grouped-antennaModule Sector o-ran-smo-teiv-ran 0 1 grouped-by-sector AntennaModule o-ran-smo-teiv-equipment 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-equipment_AntennaModule o-ran-smo-teiv-rel-equipment-ran +SECTOR_GROUPS_EUTRANCELL grouped-euTranCell Sector o-ran-smo-teiv-ran 0 1 grouped-by-sector EUtranCell o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_EUtranCell o-ran-smo-teiv-ran +SECTOR_GROUPS_NRCELLDU grouped-nrCellDu Sector o-ran-smo-teiv-ran 0 1 grouped-by-sector NRCellDU o-ran-smo-teiv-ran 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE o-ran-smo-teiv-ran_NRCellDU o-ran-smo-teiv-ran +\. + +; + +COMMIT; \ No newline at end of file diff --git a/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model.sql b/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model.sql index e919b22..91316ec 100644 --- a/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model.sql +++ b/teiv/src/test/resources/pgsqlschema/01_init-oran-smo-teiv-model.sql @@ -19,14 +19,13 @@ -- ============LICENSE_END========================================================= -- +BEGIN; + DROP SCHEMA IF EXISTS ties_model cascade; CREATE SCHEMA IF NOT EXISTS ties_model; -ALTER SCHEMA ties_model OWNER TO :pguser; SET default_tablespace = ''; SET default_table_access_method = heap; -SET ROLE :'pguser'; - CREATE TABLE IF NOT EXISTS ties_model.hash_info ( "name" VARCHAR(511) PRIMARY KEY, "hashedValue" VARCHAR(511), @@ -39,44 +38,34 @@ CREATE TABLE IF NOT EXISTS ties_model.module_reference ( "domain" VARCHAR(511), "includedModules" jsonb, "content" TEXT, - "revision" VARCHAR(511), - "ownerAppId" VARCHAR(511), - "status" VARCHAR(127) + "revision" VARCHAR(511) ); CREATE TABLE IF NOT EXISTS ties_model.entity_info ( - "name" VARCHAR(511) PRIMARY KEY, - "moduleReferenceName" VARCHAR(511), - FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS ties_model.decorators ( - "name" VARCHAR(511) PRIMARY KEY, - "dataType" VARCHAR(511), - "moduleReferenceName" VARCHAR(511), - FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS ties_model.classifiers ( - "name" VARCHAR(511) PRIMARY KEY, + "storedAt" VARCHAR(511) PRIMARY KEY, + "name" VARCHAR(511), "moduleReferenceName" VARCHAR(511), FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS ties_model.relationship_info ( - "name" VARCHAR(511) PRIMARY KEY, - "aSideAssociationName" TEXT, - "aSideMOType" TEXT, - "aSideMinCardinality" BIGINT, - "aSideMaxCardinality" BIGINT, - "bSideAssociationName" TEXT, - "bSideMOType" TEXT, - "bSideMinCardinality" BIGINT, - "bSideMaxCardinality" BIGINT, - "associationKind" TEXT, - "relationshipDataLocation" TEXT, - "connectSameEntity" BOOLEAN, - "moduleReferenceName" TEXT, + "name" VARCHAR(511) NOT NULL, + "aSideAssociationName" TEXT NOT NULL, + "aSideMOType" TEXT NOT NULL, + "aSideModule" TEXT NOT NULL, + "aSideMinCardinality" BIGINT NOT NULL, + "aSideMaxCardinality" BIGINT NOT NULL, + "bSideAssociationName" TEXT NOT NULL, + "bSideMOType" TEXT NOT NULL, + "bSideModule" TEXT NOT NULL, + "bSideMinCardinality" BIGINT NOT NULL, + "bSideMaxCardinality" BIGINT NOT NULL, + "associationKind" TEXT NOT NULL, + "relationshipDataLocation" TEXT NOT NULL, + "connectSameEntity" BOOLEAN NOT NULL, + "storedAt" VARCHAR(511) NOT NULL, + "moduleReferenceName" TEXT NOT NULL, + PRIMARY KEY ("name", "moduleReferenceName"), FOREIGN KEY ("moduleReferenceName") REFERENCES ties_model.module_reference ("name") ON DELETE CASCADE ); @@ -319,6 +308,7 @@ UNIQUE_NRSectorCarrier_REL_ID_NRCELLDU_USES_NRSECTORCARRIER UNIQUE_NRSectorCarri bSide_TestEntityB bSide_TestEntityB COLUMN REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN totalTilt totalTilt COLUMN +antennaBeamWidth antennaBeamWidth COLUMN FK_ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt_REL_FK_deployed-as-cloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm FK_9C091709D40D51DEE4DC87A44695F6EBA2E965DE CONSTRAINT gNBIdLength gNBIdLength COLUMN UNIQUE_ENodeBFunction_REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION UNIQUE_F33037EE8037D0606D15FFB45EE8A27FD6DE30EE CONSTRAINT @@ -345,6 +335,8 @@ PK_TestEntityA_id PK_TestEntityA_id CONSTRAINT FK_CloudNativeApplication_REL_FK_deployed-on-namespace FK_CloudNativeApplication_REL_FK_deployed-on-namespace CONSTRAINT gNBDUId gNBDUId COLUMN CD_sourceIds CD_sourceIds COLUMN +CD_classifiers CD_classifiers COLUMN +CD_decorators CD_decorators COLUMN PK_TESTENTITYA_GROUPS_TESTENTITYB_id PK_TESTENTITYA_GROUPS_TESTENTITYB_id CONSTRAINT REL_ID_SECTOR_GROUPS_ANTENNAMODULE REL_ID_SECTOR_GROUPS_ANTENNAMODULE COLUMN AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee B69D3E92CA22CE61B921AE61BD3CF031791CF714 TABLE @@ -390,96 +382,212 @@ REL_CD_sourceIds_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE REL_CD_sourceIds_C REL_CD_sourceIds_CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE REL_CD_F7E43E0D0F76D6EFED9AB684B84A69E177F591D2 COLUMN REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB REL_CD_sourceIds_TESTENTITYA_USES_TESTENTITYB COLUMN +REL_CD_classifiers_MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM REL_CD_BF4AAC1A1A910D1182505CABF55BAAE822B2BE59 COLUMN +REL_CD_classifiers_MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN REL_CD_7E9F11EFBF8974D7C7DAB02E181A0BE4148091C6 COLUMN +REL_CD_classifiers_MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN REL_CD_744530EF4EB1D281D23ADB3DB4CC926DFBE7A60D COLUMN +REL_CD_classifiers_GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU REL_CD_66AEF506899F14F936A2F48F9444E2202F5D43F9 COLUMN +REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_CD_classifiers_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE REL_CD_C6C6D295144A637110DA4E6121BE13F30EFDBEBF COLUMN +REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_CD_classifiers_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM REL_CD_classifiers_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM COLUMN +REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU COLUMN +REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_classifiers_NAMESPACE_DEPLOYED_ON_NODECLUSTER REL_CD_classifiers_NAMESPACE_DEPLOYED_ON_NODECLUSTER COLUMN +REL_CD_classifiers_NODECLUSTER_LOCATED_AT_CLOUDSITE REL_CD_classifiers_NODECLUSTER_LOCATED_AT_CLOUDSITE COLUMN +REL_CD_classifiers_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE REL_CD_classifiers_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_CD_classifiers_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION REL_CD_CCEBD4C63B90BD1764CB5A15C282D6CDBDF0B1F2 COLUMN +REL_CD_classifiers_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION REL_CD_026A1F92A7D93728916AF3DCC2C013FB79E29D07 COLUMN +REL_CD_classifiers_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE REL_CD_classifiers_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE COLUMN +REL_CD_classifiers_CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE REL_CD_C4349BB0F0292A3CE7E456E3A4C40C86DD6B15DF COLUMN +REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_CD_classifiers_TESTENTITYA_USES_TESTENTITYB REL_CD_classifiers_TESTENTITYA_USES_TESTENTITYB COLUMN +REL_CD_decorators_MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM REL_CD_AE82DD80D666B52D79A314F8B4EE9B046830D009 COLUMN +REL_CD_decorators_MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN REL_CD_FFF7E036187A7605BFC714483D2E60FD2FF6560B COLUMN +REL_CD_decorators_MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN REL_CD_4D1F8113C3096B383582A7A04E68974983B4259E COLUMN +REL_CD_decorators_GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU REL_CD_022F8280C0739C614C5F3293E7D8D349A8A10E30 COLUMN +REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE COLUMN +REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION COLUMN +REL_CD_decorators_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE REL_CD_B369805A0EB24F7C841B0E541A015F85AE2A23B1 COLUMN +REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL COLUMN +REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION COLUMN +REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER COLUMN +REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER COLUMN +REL_CD_decorators_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM REL_CD_decorators_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM COLUMN +REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU COLUMN +REL_CD_decorators_SECTOR_GROUPS_NRCELLDU REL_CD_decorators_SECTOR_GROUPS_NRCELLDU COLUMN +REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU COLUMN +REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER COLUMN +REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER COLUMN +REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY COLUMN +REL_CD_decorators_NAMESPACE_DEPLOYED_ON_NODECLUSTER REL_CD_decorators_NAMESPACE_DEPLOYED_ON_NODECLUSTER COLUMN +REL_CD_decorators_NODECLUSTER_LOCATED_AT_CLOUDSITE REL_CD_decorators_NODECLUSTER_LOCATED_AT_CLOUDSITE COLUMN +REL_CD_decorators_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE REL_CD_decorators_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION COLUMN +REL_CD_decorators_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION REL_CD_21E2495C31F0DBF735976C90F4CD10D1215190E1 COLUMN +REL_CD_decorators_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION REL_CD_D32E90288E1982363B2BD8DA9D2E90AA16F71575 COLUMN +REL_CD_decorators_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE REL_CD_decorators_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE COLUMN +REL_CD_decorators_CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE REL_CD_8AD499BB116F3213C079F643D4B3532035D092D2 COLUMN +REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION COLUMN +REL_CD_decorators_TESTENTITYA_USES_TESTENTITYB REL_CD_decorators_TESTENTITYA_USES_TESTENTITYB COLUMN +o-ran-smo-teiv-ran-oam_ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt fa2dceaf53e045c136ce9db9bc5faae65a29fa4d TABLE +o-ran-smo-teiv-ran-oam_ManagedElement o-ran-smo-teiv-ran-oam_ManagedElement TABLE +o-ran-smo-teiv-ran-cloud_NodeCluster o-ran-smo-teiv-ran-cloud_NodeCluster TABLE +o-ran-smo-teiv-ran-cloud_CloudNativeSystem 163276fa439cdfccabb80f7acacb6fa638e8d314 TABLE +o-ran-smo-teiv-ran-cloud_CloudNativeApplication e01fcb87ad2c34ce66c34420255e25aaca270e5e TABLE +o-ran-smo-teiv-ran-cloud_CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ef701af8e1445ed5d377664ba1d3d1c645e31639 TABLE +o-ran-smo-teiv-ran-cloud_CloudSite o-ran-smo-teiv-ran-cloud_CloudSite TABLE +o-ran-smo-teiv-ran-cloud_Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee bc563e4310b0538e6bdd35f52684160af5b23671 TABLE +o-ran-smo-teiv-ran-cloud_CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 5f8facd51b2bbddc90d9dee9be697907441892d0 TABLE +o-ran-smo-teiv-ran-cloud_Namespace o-ran-smo-teiv-ran-cloud_Namespace TABLE +o-ran-smo-teiv-ran-logical-to-equipment_Sector 22174a23af5d5a96143c83ddfa78654df0acb697 TABLE +o-ran-smo-teiv-ran-logical_GNBCUUPFunction 8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb TABLE +o-ran-smo-teiv-ran-logical_ENodeBFunction o-ran-smo-teiv-ran-logical_ENodeBFunction TABLE +o-ran-smo-teiv-ran-logical_NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 300672c8a708d6af0b9af2f9accdff5e6e005721 TABLE +o-ran-smo-teiv-ran-logical_NRCellDU o-ran-smo-teiv-ran-logical_NRCellDU TABLE +o-ran-smo-teiv-ran-logical_LTESectorCarrier c88307168935f02fdecc084ea5040bb9db16c701 TABLE +o-ran-smo-teiv-ran-logical_GNBDUFunction o-ran-smo-teiv-ran-logical_GNBDUFunction TABLE +o-ran-smo-teiv-ran-logical_NRCellCU o-ran-smo-teiv-ran-logical_NRCellCU TABLE +o-ran-smo-teiv-ran-logical_GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 3fdb9cd7557edf559a0e4de88df220e7545884b5 TABLE +o-ran-smo-teiv-ran-equipment_AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 341622dca4e0350289717b52df5883edc3fa0280 TABLE +o-ran-smo-teiv-ran-logical_EUtranCell o-ran-smo-teiv-ran-logical_EUtranCell TABLE +o-ran-smo-teiv-ran-logical_GNBCUCPFunction c4a425179d3089b5288fdf059079d0ea26977f0f TABLE +o-ran-smo-teiv-ran-logical_NRSectorCarrier 39a335dca201ef99ae06f4ffd1908b534f8c6c39 TABLE +o-ran-smo-teiv-ran-logical_AntennaCapability 88f1bd76c7a935fb505cf235e6819f46c55ec98a TABLE +o-ran-smo-teiv-ran-logical_TestEntityB o-ran-smo-teiv-ran-logical_TestEntityB TABLE +o-ran-smo-teiv-ran-logical_TestEntityA o-ran-smo-teiv-ran-logical_TestEntityA TABLE +o-ran-smo-teiv-ran-equipment_Site o-ran-smo-teiv-ran-equipment_Site TABLE +o-ran-smo-teiv-ran-equipment_AntennaModule f8caf5ebe876c3001d67efe06e4d83abf0babe31 TABLE +o-ran-smo-teiv-ran-equipment_PhysicalNetworkAppliance 57a20807ab3f39c86b0b5bf9a819e0881353fa1e TABLE +o-ran-smo-teiv-ran-logical-to-cloud_GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION 70a4a84bca01ea022ab24d8cb82422c572922675 TABLE +o-ran-smo-teiv-ran-logical-to-equipment_ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE 5b8a47d4a8297a0a1d31e091af06e26d25ef6caf TABLE +o-ran-smo-teiv-ran-logical-to-cloud_GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN f86057a8762a50b1c7fb07af9d5c001bffaefd15 TABLE +o-ran-smo-teiv-ran-logical_TESTENTITYA_PROVIDES_TESTENTITYB 73936e503f137d82d1422c0f08c66c7ff8b90209 TABLE +o-ran-smo-teiv-ran-logical_TESTENTITYA_GROUPS_TESTENTITYB 70003c8082751e1832e7bc5c0d83db6d22c4fcdc TABLE +o-ran-smo-teiv-ran-equipment_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE 5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6 TABLE +o-ran-smo-teiv-ran-equipment_ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE cd39d44beed963d50df42cd301e63d288f911c97 TABLE +o-ran-smo-teiv-ran-equipment_ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE c6f3a3396e9165e886da928c5fe1382fb20dc850 TABLE +o-ran-smo-teiv-ran-logical-to-cloud_GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION 7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7 TABLE +o-ran-smo-teiv-ran-logical-to-cloud_GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION 10484f157f490eb5b27e40dbfaf4d5f2be17c57c TABLE \. -COPY ties_model.module_reference("name", "namespace", "domain", "includedModules", "revision", "content", "ownerAppId", "status") FROM stdin; -o-ran-smo-teiv-common-yang-extensions urn:o-ran:smo-teiv-common-yang-extensions \N [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgewoKICB5YW5nLXZlcnNpb24gMS4xOwogIG5hbWVzcGFjZSAidXJuOm8tcmFuOnNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMiOwogIHByZWZpeCBvci10ZWl2LXlleHQ7CgogIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOwogIGRlc2NyaXB0aW9uCiAgIlRvcG9sb2d5IGFuZCBJbnZlbnRvcnkgWUFORyBleHRlbnNpb25zIG1vZGVsLgoKICBDb3B5cmlnaHQgKGMpIDIwMjMgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogIFRoaXMgbW9kZWwgY29udGFpbnMgZXh0ZW5zaW9ucyB0byB0aGUgWUFORyBsYW5ndWFnZSB0aGF0IHRvcG9sb2d5IGFuZAogIGludmVudG9yeSBtb2RlbHMgd2lsbCB1c2UgdG8gZGVmaW5lIGFuZCBhbm5vdGF0ZSB0eXBlcyBhbmQgcmVsYXRpb25zaGlwcy4iOwoKICByZXZpc2lvbiAiMjAyNC0wNS0wMiIgewogICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICB9CgogIGV4dGVuc2lvbiBiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgewoKICAgIGRlc2NyaXB0aW9uCiAgICAgICJEZWZpbmVzIGEgYmktZGlyZWN0aW9uYWwgcmVsYXRpb25zaGlwIGluIHRoZSB0b3BvbG9neS4KCiAgICAgICBBIGJpLWRpcmVjdGlvbmFsLWFzc29jaWF0aW9uIChCREEpIGlzIGEgcmVsYXRpb25zaGlwIGNvbXByaXNpbmcgb2YgYW4KICAgICAgIEEtc2lkZSBhbmQgYSBCLXNpZGUuIFRoZSBBLXNpZGUgaXMgY29uc2lkZXJlZCB0aGUgb3JpZ2luYXRpbmcgc2lkZSBvZgogICAgICAgdGhlIHJlbGF0aW9uc2hpcDsgdGhlIEItc2lkZSBpcyBjb25zaWRlcmVkIHRoZSB0ZXJtaW5hdGluZyBzaWRlIG9mIHRoZQogICAgICAgcmVsYXRpb25zaGlwLiBUaGUgb3JkZXIgb2YgQS1zaWRlIGFuZCBCLXNpZGUgaXMgb2YgaW1wb3J0YW5jZSBhbmQgTVVTVAogICAgICAgTk9UIGJlIGNoYW5nZWQgb25jZSBkZWZpbmVkLgoKICAgICAgIEJvdGggQS1zaWRlIGFuZCBCLXNpZGUgYXJlIGRlZmluZWQgb24gYSB0eXBlLCBhbmQgYXJlIGdpdmVuIGEgcm9sZS4gQQogICAgICAgdHlwZSBtYXkgaGF2ZSBtdWx0aXBsZSBvcmlnaW5hdGluZyBhbmQvb3IgdGVybWluYXRpbmcgc2lkZXMgb2YgYQogICAgICAgcmVsYXRpb25zaGlwLCBhbGwgZGlzdGluZ3Vpc2hlZCBieSByb2xlIG5hbWUuCgogICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIG9ubHkgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlICdtb2R1bGUnIHN0YXRlbWVudC4KICAgICAgIE11bHRpcGxlICdiaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIHN0YXRlbWVudHMgYXJlIGFsbG93ZWQKICAgICAgIHBlciBwYXJlbnQgc3RhdGVtZW50LgoKICAgICAgIFN1YnN0YXRlbWVudHMgdG8gdGhlICdiaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIGRlZmluZSB0aGUKICAgICAgIEEtc2lkZSBhbmQgdGhlIEItc2lkZSwgcmVzcGVjdGl2ZWx5LCBhbmQgb3B0aW9uYWxseSBwcm9wZXJ0aWVzIG9mIHRoZQogICAgICAgcmVsYXRpb25zaGlwLiBEYXRhIG5vZGVzIG9mIHR5cGVzICdsZWFmJyBhbmQgJ2xlYWYtbGlzdCcgYXJlIHVzZWQgZm9yCiAgICAgICB0aGlzIHB1cnBvc2UuIE9uZSBvZiB0aGUgZGF0YSBub2RlcyBNVVNUIGJlIGFubm90YXRlZCB3aXRoIHRoZSAnYS1zaWRlJwogICAgICAgZXh0ZW5zaW9uOyBhbm90aGVyIGRhdGEgbm9kZSBNVVNUIGJlIGFubm90YXRlZCB3aXRoIHRoZSAnYi1zaWRlJwogICAgICAgZXh0ZW5zaW9uLiBPdGhlciBkYXRhIG5vZGVzIGRlZmluZSBwcm9wZXJ0aWVzIG9mIHRoZSByZWxhdGlvbnNoaXAuCgogICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSByZWxhdGlvbnNoaXAgbmFtZSBpcwogICAgICAgc2NvcGVkIHRvIHRoZSBuYW1lc3BhY2Ugb2YgdGhlIGRlY2xhcmluZyBtb2R1bGUgYW5kIE1VU1QgYmUgdW5pcXVlCiAgICAgICB3aXRoaW4gdGhlIHNjb3BlLiI7CgogICAgYXJndW1lbnQgcmVsYXRpb25zaGlwTmFtZTsKICB9CgogIGV4dGVuc2lvbiBhU2lkZSB7CiAgICBkZXNjcmlwdGlvbgogICAgICAiRGVmaW5lcyB0aGUgQS1zaWRlIG9mIGEgcmVsYXRpb25zaGlwLgoKICAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgJ2xlYWYnIG9yICdsZWFmLWxpc3QnCiAgICAgICBzdGF0ZW1lbnQsIHdoaWNoIGl0c2VsZiBtdXN0IGJlIGEgc3Vic3RhdGVtZW50IG9mIHRoZQogICAgICAgJ3VuaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIHN0YXRlbWVudC4KCiAgICAgICBUaGUgZGF0YSB0eXBlIG9mIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIE1VU1QgYmUKICAgICAgICdpbnN0YW5jZS1pZGVudGlmaWVyJy4gQ29uc3RyYWludHMgTUFZIGJlIHVzZWQgYXMgcGFydCBvZiB0aGUgcGFyZW50CiAgICAgICAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgdG8gZW5mb3JjZSBjYXJkaW5hbGl0eS4KCiAgICAgICBUaGUgaWRlbnRpZmllciBvZiB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBpcyB1c2VkIGFzIG5hbWUgb2YKICAgICAgIHRoZSByb2xlIG9mIHRoZSBBLXNpZGUgb2YgdGhlIHJlbGF0aW9uc2hpcC4gVGhlIG5hbWUgb2YgdGhlIHJvbGUgaXMKICAgICAgIHNjb3BlZCB0byB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQS1zaWRlIGlzIGRlZmluZWQgYW5kIE1VU1QgYmUgdW5pcXVlCiAgICAgICB3aXRoaW4gdGhlIHNjb3BlLgoKICAgICAgIFdoaWxlIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIGRvZXMgbm90IHJlc3VsdCBpbiBhIHByb3BlcnR5IG9mCiAgICAgICB0aGUgcmVsYXRpb25zaGlwLCBpdCBpcyBSRUNPTU1FTkRFRCB0byBhdm9pZCB1c2luZyB0aGUgbmFtZSBvZiBhbgogICAgICAgZXhpc3RpbmcgdHlwZSBwcm9wZXJ0eSBhcyByb2xlIG5hbWUgdG8gYXZvaWQgcG90ZW50aWFsIGFtYmlndWl0aWVzCiAgICAgICBiZXR3ZWVuIHByb3BlcnRpZXMgb2YgYSB0eXBlLCBhbmQgcm9sZXMgb2YgYSByZWxhdGlvbnNoaXAgb24gdGhlIHR5cGUuCgogICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSB0eXBlIG9uIHdoaWNoIHRoZSBBLXNpZGUgcmVzaWRlcy4gSWYgdGhlCiAgICAgICB0eXBlIGlzIGRlY2xhcmVkIGluIGFub3RoZXIgbW9kdWxlLCB0aGUgdHlwZSBtdXN0IGJlIHByZWZpeGVkLCBhbmQgYQogICAgICAgY29ycmVzcG9uZGluZyAnaW1wb3J0JyBzdGF0ZW1lbnQgYmUgdXNlZCB0byBkZWNsYXJlIHRoZSBwcmVmaXguIjsKCiAgICBhcmd1bWVudCBhU2lkZVR5cGU7CiAgfQoKICBleHRlbnNpb24gYlNpZGUgewogICAgZGVzY3JpcHRpb24gIkRlZmluZXMgdGhlIEItc2lkZSBvZiBhIHJlbGF0aW9uc2hpcC4KCiAgICAgICBUaGUgc3RhdGVtZW50IE1VU1Qgb25seSBiZSBhIHN1YnN0YXRlbWVudCBvZiBhICdsZWFmJyBvciAnbGVhZi1saXN0JwogICAgICAgc3RhdGVtZW50LCB3aGljaCBpdHNlbGYgbXVzdCBiZSBhIHN1YnN0YXRlbWVudCBvZiB0aGUKICAgICAgICd1bmktZGlyZWN0aW9uYWwtdG9wb2xvZ3ktcmVsYXRpb25zaGlwJyBzdGF0ZW1lbnQuCgogICAgICAgVGhlIGRhdGEgdHlwZSBvZiB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBNVVNUIGJlCiAgICAgICAnaW5zdGFuY2UtaWRlbnRpZmllcicuIENvbnN0cmFpbnRzIE1BWSBiZSB1c2VkIGFzIHBhcnQgb2YgdGhlIHBhcmVudAogICAgICAgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIHRvIGVuZm9yY2UgY2FyZGluYWxpdHkuCgogICAgICAgVGhlIGlkZW50aWZpZXIgb2YgdGhlIHBhcmVudCAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgaXMgdXNlZCBhcyBuYW1lIG9mCiAgICAgICB0aGUgcm9sZSBvZiB0aGUgQi1zaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSBuYW1lIG9mIHRoZSByb2xlIGlzCiAgICAgICBzY29wZWQgdG8gdGhlIHR5cGUgb24gd2hpY2ggdGhlIEItc2lkZSBpcyBkZWZpbmVkIGFuZCBNVVNUIGJlIHVuaXF1ZQogICAgICAgd2l0aGluIHRoZSBzY29wZS4KCiAgICAgICBXaGlsZSB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBkb2VzIG5vdCByZXN1bHQgaW4gYSBwcm9wZXJ0eSBvZgogICAgICAgdGhlIHJlbGF0aW9uc2hpcCwgaXQgaXMgUkVDT01NRU5ERUQgdG8gYXZvaWQgdXNpbmcgdGhlIG5hbWUgb2YgYW4KICAgICAgIGV4aXN0aW5nIHR5cGUgcHJvcGVydHkgYXMgcm9sZSBuYW1lIHRvIGF2b2lkIHBvdGVudGlhbCBhbWJpZ3VpdGllcwogICAgICAgYmV0d2VlbiBwcm9wZXJ0aWVzIG9mIGEgdHlwZSwgYW5kIHJvbGVzIG9mIGEgcmVsYXRpb25zaGlwIG9uIHRoZSB0eXBlLgoKICAgICAgIFRoZSBhcmd1bWVudCBpcyB0aGUgbmFtZSBvZiB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQi1zaWRlIHJlc2lkZXMuIElmIHRoZQogICAgICAgdHlwZSBpcyBkZWNsYXJlZCBpbiBhbm90aGVyIG1vZHVsZSwgdGhlIHR5cGUgbXVzdCBiZSBwcmVmaXhlZCwgYW5kIGEKICAgICAgIGNvcnJlc3BvbmRpbmcgJ2ltcG9ydCcgc3RhdGVtZW50IGJlIHVzZWQgdG8gZGVjbGFyZSB0aGUgcHJlZml4LiI7CgogICAgYXJndW1lbnQgYlNpZGVUeXBlOwogIH0KCiAgZXh0ZW5zaW9uIGRvbWFpbiB7CiAgICBkZXNjcmlwdGlvbiAiS2V5d29yZCB1c2VkIHRvIGNhcnJ5IGRvbWFpbiBpbmZvcm1hdGlvbi4iOwogICAgYXJndW1lbnQgZG9tYWluTmFtZTsKICB9CgogIGV4dGVuc2lvbiBsYWJlbCB7CiAgICBkZXNjcmlwdGlvbiAiVGhlIGxhYmVsIGNhbiBiZSB1c2VkIHRvIGdpdmUgbW9kdWxlcyBhbmQgc3VibW9kdWxlcyBhIHNlbWFudGljIHZlcnNpb24sIGluIGFkZGl0aW9uIHRvIHRoZWlyIHJldmlzaW9uLgoKICAgICAgVGhlIGZvcm1hdCBvZiB0aGUgbGFiZWwgaXMg4oCYeC55LnrigJkg4oCTIGV4cHJlc3NlZCBhcyBwYXR0ZXJuLCBpdCBpcyBbMC05XStcXC5bMC05XStcXC5bMC05XSsKCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIHRoZSByZXZpc2lvbiBzdGF0ZW1lbnQuICBaZXJvIG9yIG9uZSByZXZpc2lvbiBsYWJlbCBzdGF0ZW1lbnRzCiAgICAgIHBlciBwYXJlbnQgc3RhdGVtZW50IGFyZSBhbGxvd2VkLgoKICAgICAgUmV2aXNpb24gbGFiZWxzIE1VU1QgYmUgdW5pcXVlIGFtb25nc3QgYWxsIHJldmlzaW9ucyBvZiBhIG1vZHVsZSBvciBzdWJtb2R1bGUuIjsKICAgICAgYXJndW1lbnQgc2VtdmVyc2lvbjsKICB9Cn0= BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-oam-to-cloud urn:o-ran:smo-teiv-oam-to-cloud OAM_TO_CLOUD ["o-ran-smo-teiv-oam", "o-ran-smo-teiv-cloud"] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LW9hbS10by1jbG91ZCB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtb2FtLXRvLWNsb3VkIjsKICAgIHByZWZpeCBvci10ZWl2LW9hbXRvY2xvdWQ7CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggb3ItdGVpdi10eXBlczsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LW9hbSB7cHJlZml4IG9yLXRlaXYtb2FtOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNsb3VkIHtwcmVmaXggb3ItdGVpdi1jbG91ZDsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiBPJk0gdG8gQ2xvdWQgdG9wb2xvZ3kgbW9kZWwuCgogICAgQ29weXJpZ2h0IChjKSAyMDIzIEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKICAgIFRoaXMgbW9kZWwgY29udGFpbnMgdGhlIFJBTiBPJk0gdG8gQ2xvdWQgdG9wb2xvZ3kgcmVsYXRpb25zIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0wMiIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIG9yLXRlaXYteWV4dDpkb21haW4gT0FNX1RPX0NMT1VEOwoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfREVQTE9ZRURfQVNfQ0xPVURJRklFRE5GIHsgIC8vIDAuLjEgdG8gMQoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZiBkZXBsb3llZC1hcy1jbG91ZGlmaWVkTkYgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IGRlcGxveWVkIGFzIENsb3VkaWZpZWQgTkYuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGRlcGxveWVkLW1hbmFnZWRFbGVtZW50IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkaWZpZWQgTkYgZGVwbG95cyBNYW5hZ2VkIEVsZW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtY2xvdWQ6Q2xvdWRpZmllZE5GOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgICAgIG1hbmRhdG9yeSB0cnVlOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5GREVQTE9ZTUVOVF9TRVJWRVNfTUFOQUdFREVMRU1FTlQgeyAvLyAxLi5uIHRvIDEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgc2VydmljZWQtbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IHNlcnZpY2VkIGJ5IHRoaXMgTkYgRGVwbG95bWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1jbG91ZDpORkRlcGxveW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1uRkRlcGxveW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTkYgRGVwbG95bWVudCB0aGF0IHNlcnZlcyB0aGlzIE1hbmFnZWQgRWxlbWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1vYW06TWFuYWdlZEVsZW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-common-yang-types urn:o-ran:smo-teiv-common-yang-types \N [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsKCiAgeWFuZy12ZXJzaW9uIDEuMTsKICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyI7CiAgcHJlZml4IG9yLXRlaXYtdHlwZXM7CgogIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogIGltcG9ydCBfM2dwcC1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCB0eXBlczNncHA7IH0KCiAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgZGVzY3JpcHRpb24KICAiVG9wb2xvZ3kgYW5kIEludmVudG9yeSBjb21tb24gdHlwZXMgbW9kZWwuCgogIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgVGhpcyBtb2RlbCBjb250YWlucyByZS11c2FibGUgZGF0YSB0eXBlcyB0aGF0IHRvcG9sb2d5IGFuZCBpbnZlbnRvcnkgbW9kZWxzCiAgd2lsbCBmcmVxdWVudGx5IHVzZSBhcyBwYXJ0IG9mIHR5cGVzIGFuZCByZWxhdGlvbnNoaXBzLiI7CgogIHJldmlzaW9uICIyMDI0LTA1LTAyIiB7CiAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogIH0KCiAgZ3JvdXBpbmcgVG9wX0dycF9UeXBlIHsKCiAgICBkZXNjcmlwdGlvbiAiR3JvdXBpbmcgY29udGFpbmluZyB0aGUga2V5IGF0dHJpYnV0ZSBjb21tb24gdG8gYWxsIHR5cGVzLiBBbGwgdHlwZXMKICAgICAgICAgICAgICAgIE1VU1QgdXNlIHRoaXMgZ3JvdXBpbmcuIjsKCiAgICBsZWFmIGlkIHsKICAgICAgdHlwZSBzdHJpbmc7CiAgICAgIGRlc2NyaXB0aW9uICJVbmlxdWUgaWRlbnRpZmllciBvZiB0b3BvbG9neSBlbnRpdGllcy4gUmVwcmVzZW50cyB0aGUgRW50aXR5IEluc3RhbmNlIElkZW50aWZpZXIuIjsKICAgIH0KICB9CgogIGdyb3VwaW5nIENNX0lEIHsKCiAgICBkZXNjcmlwdGlvbiAiR3JvdXBpbmcgY29udGFpbmluZyB0aGUga2V5IGF0dHJpYnV0ZXMgdG8gbWFrZQogICAgICAgICAgICAgICAgdXNlIG9mIENvbmZpZ3VyYXRpb24gTWFuYWdlbWVudCAoQ00pLiI7CgogICAgbGVhZiBjbUhhbmRsZSB7CiAgICAgIHR5cGUgc3RyaW5nOwogICAgICBkZXNjcmlwdGlvbiAiVW5pcXVlIGlkZW50aWZpZXIgZm9yIG5ldHdvcmsgZW50aXRpZXMgaW4gQ00uIjsKICAgIH0KCiAgICBsZWFmIHJlc291cmNlSWRlbnRpZmllciB7CiAgICAgIHR5cGUgc3RyaW5nOwogICAgICBkZXNjcmlwdGlvbiAiVGhlIHhwYXRoIGV4cHJlc3Npb24gaWRlbnRpZnlpbmcgdGhlIHJlc291cmNlIGluIHRoZSBOb2RlIG1vZGVsIHlhbmcgdHJlZS4iOwogICAgfQogIH0KCiAgdHlwZWRlZiBfM0dQUF9GRE5fVHlwZSB7CiAgICB0eXBlIHR5cGVzM2dwcDpEaXN0aW5ndWlzaGVkTmFtZTsKICB9CgogIGNvbnRhaW5lciBjb25zdW1lci1kYXRhIHsKICAgIGRlc2NyaXB0aW9uICJUaGlzIGNvbnRhaW5lciBkZWZpbmVzIHRoZSBjb25zdW1lci1kYXRhLiBDb25zdW1lci1kYXRhIG1heSBiZSBhdHRhY2hlZCB0byBUb3BvbG9neSBFbnRpdHkgb3IKICAgICAgICAgICAgICAgIFRvcG9sb2d5IFJlbGF0aW9uIGluc3RhbmNlLCBvdXRzaWRlIG9mIHRoZSBkZWNsYXJlZCBUb3BvbG9neSBFbnRpdHkgb3IgVG9wb2xvZ3kgUmVsYXRpb25zaGlwJ3MgYXR0cmlidXRlcy4KICAgICAgICAgICAgICAgIFRoaXMgY29udGFpbmVyIGNhbm5vdCBiZSBpbnN0YW50aWF0ZWQsIGFuZCBpdCBNVVNUIE5PVCBiZSBhdWdtZW50ZWQgb3IgZGV2aWF0ZWQgaW4gYW55IHdheSwgdW5sZXNzIHN0YXRlZAogICAgICAgICAgICAgICAgb3RoZXJ3aXNlLiI7CgogICAgY29udGFpbmVyIGRlY29yYXRvcnMgewogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBjb250YWluZXIgc2VydmVzIGFzIGV4dGVuc2lvbiBwb2ludCBmb3IgYXBwbGljYXRpb25zIHdpc2hpbmcgdG8gZGVmaW5lIHRoZWlyIG93biBkZWNvcmF0b3JzLgogICAgICAgICAgICAgICAgICBUaGlzIGlzIGRvbmUgdmlhIGF1Z21lbnRhdGlvbnMuIFRoZXkgY2FuIG9ubHkgYmUgZGVmaW5lZCBpbiBuYW1lIHZhbHVlIHBhaXIuIjsKICAgIH0KCiAgICBsZWFmLWxpc3QgY2xhc3NpZmllcnMgewogICAgICBkZXNjcmlwdGlvbiAiQ29uc3VtZXIgZGVmaW5lZCB0YWdzIHRvIHRvcG9sb2d5IGVudGl0aWVzIGFuZCByZWxhdGlvbnNoaXBzLiI7CiAgICAgIHR5cGUgaWRlbnRpdHlyZWYgeyBiYXNlIGNsYXNzaWZpZXI7IH0KICAgIH0KCiAgICBsZWFmLWxpc3Qgc291cmNlSWRzIHsKICAgICAgZGVzY3JpcHRpb24gIkFuIG9yZGVyZWQgbGlzdCBvZiBpZGVudGl0aWVzIHRoYXQgcmVwcmVzZW50IHRoZSBzZXQgb2YgbmF0aXZlIHNvdXJjZSBpZGVudGlmaWVycyBmb3IgcGFydGljaXBhdGluZwogICAgICAgICAgICAgICAgICBlbnRpdGllcy4iOwogICAgICB0eXBlIHN0cmluZzsKICAgICAgb3JkZXJlZC1ieSB1c2VyOwogICAgfQoKICAgIGNvbnRhaW5lciBtZXRhZGF0YSB7CiAgICAgIGRlc2NyaXB0aW9uICJUaGlzIGNvbnRhaW5lciBzZXJ2ZXMgYXMgZXh0ZW5zaW9uIHBvaW50IHRvIGRlZmluZSBtZXRhZGF0YS4gVGhleSBjYW4gb25seSBiZSBkZWZpbmVkIGluIG5hbWUgdmFsdWUKICAgICAgICAgICAgICAgICAgcGFpci4iOwogICAgfQogIH0KCiAgaWRlbnRpdHkgY2xhc3NpZmllcnsKICAgIGRlc2NyaXB0aW9uICAiVGhlIGNsYXNzaWZpZXIgaXMgdXNlZCBhcyBhIGJhc2UgdG8gcHJvdmlkZSBhbGwgY2xhc3NpZmllcnMgd2l0aCBpZGVudGl0eS4gIjsKICB9Cn0= BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-oam urn:o-ran:smo-teiv-oam OAM [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LW9hbSB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtb2FtIjsKICAgIHByZWZpeCBvci10ZWl2LW9hbTsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBvcmdhbml6YXRpb24gIkVyaWNzc29uIEFCIjsKICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOwogICAgZGVzY3JpcHRpb24KICAgICJSQU4gTyZNIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIE8mTSBkb21haW4sIHdoaWNoIGFyZSBpbnRlbmRlZCB0byByZXByZXNlbnQgbWFuYWdlbWVudCBzeXN0ZW1zCiAgICBhbmQgbWFuYWdlbWVudCBpbnRlcmZhY2VzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMDIiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIE9BTTsKCiAgICBsaXN0IE1hbmFnZWRFbGVtZW50IHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBNYW5hZ2VkIEVsZW1lbnQgKE1FKSBpcyBhIG5vZGUgaW50byBhIHRlbGVjb21tdW5pY2F0aW9uIG5ldHdvcmsKICAgICAgICAgICAgICAgICAgICBwcm92aWRpbmcgc3VwcG9ydCBhbmQvb3Igc2VydmljZSB0byBzdWJzY3JpYmVycy4gQW4gTUUgY29tbXVuaWNhdGVzCiAgICAgICAgICAgICAgICAgICAgd2l0aCBhIG1hbmFnZXIgYXBwbGljYXRpb24gKGRpcmVjdGx5IG9yIGluZGlyZWN0bHkpIG92ZXIgb25lIG9yIG1vcmUKICAgICAgICAgICAgICAgICAgICBpbnRlcmZhY2VzIGZvciB0aGUgcHVycG9zZSBvZiBiZWluZyBtb25pdG9yZWQgYW5kL29yIGNvbnRyb2xsZWQuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBmZG4gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoaXMgRnVsbCBEaXN0aW5ndWlzaGVkIE5hbWUgKEZETikgaWRlbnRpZmllcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW4gaW5zdGFuY2Ugb2YgdGhlIE1hbmFnZWRFbGVtZW50IE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFuYWdlZEVsZW1lbnQuIjsKICAgICAgICAgICAgICAgIHR5cGUgb3ItdGVpdi10eXBlczpfM0dQUF9GRE5fVHlwZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-oam-to-ran urn:o-ran:smo-teiv-oam-to-ran OAM_TO_RAN ["o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran"] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LW9hbS10by1yYW4gewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOm8tcmFuOnNtby10ZWl2LW9hbS10by1yYW4iOwogICAgcHJlZml4IG9yLXRlaXYtb2FtdG9yYW47CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggb3ItdGVpdi10eXBlczsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LW9hbSB7cHJlZml4IG9yLXRlaXYtb2FtOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LXJhbiB7cHJlZml4IG9yLXRlaXYtcmFuOyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiUkFOIE8mTSB0byBMb2dpY2FsIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSBSQU4gTyZNIHRvIExvZ2ljYWwgdG9wb2xvZ3kgcmVsYXRpb25zIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0wMiIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIG9yLXRlaXYteWV4dDpkb21haW4gT0FNX1RPX1JBTjsKCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX01BTkFHRVNfRU5PREVCRlVOQ1RJT04geyAgIC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IG1hbmFnZXMgZU5vZGVCIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBvci10ZWl2LW9hbTpNYW5hZ2VkRWxlbWVudDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBtYW5hZ2VkLWJ5LW1hbmFnZWRFbGVtZW50IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImVOb2RlQiBGdW5jdGlvbiBtYW5hZ2VkIGJ5IE1hbmFnZWQgRWxlbWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46RU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJEVUZVTkNUSU9OIHsgICAgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgbWFuYWdlZC1nbmJkdUZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1hbmFnZWQgRWxlbWVudCBtYW5hZ2VzIGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1vYW06TWFuYWdlZEVsZW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgbWFuYWdlZC1ieS1tYW5hZ2VkRWxlbWVudCB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItRFUgRnVuY3Rpb24gbWFuYWdlZCBieSBNYW5hZ2VkIEVsZW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVUNQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtQ1AgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLUNQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVUNQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVVVQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1dXBGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtVVAgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLVVQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVVVQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-ran urn:o-ran:smo-teiv-ran RAN [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJhbiB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtcmFuIjsKICAgIHByZWZpeCBvci10ZWl2LXJhbjsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgXzNncHAtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggdHlwZXMzZ3BwOyB9CgogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgICAgICBwcmVmaXggZ2VvOwogICAgICAgIHJlZmVyZW5jZSAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiBMb2dpY2FsIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIExvZ2ljYWwgZG9tYWluLCB3aGljaCByZXByZXNlbnRzIHRoZSBmdW5jdGlvbmFsIGNhcGFiaWxpdHkKICAgIG9mIHRoZSBkZXBsb3llZCBSQU4gdGhhdCBhcmUgcmVsZXZhbnQgdG8gckFwcHMgdXNlIGNhc2VzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMDIiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIFJBTjsKCiAgICBsaXN0IEdOQkRVRnVuY3Rpb24gewogICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUIgRGlzdHJpYnV0ZWQgVW5pdCAoZ05CLURVKS4KCiAgICAgICAgICAgICAgICAgICAgQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ2VudHJhbGl6ZWQgVW5pdAogICAgICAgICAgICAgICAgICAgIChnTkItQ1UpIGFuZCBhIGdOQi1EVS4gVGhlIENVIHByb2Nlc3NlcyBub24tcmVhbAogICAgICAgICAgICAgICAgICAgIHRpbWUgcHJvdG9jb2xzIGFuZCBzZXJ2aWNlcywgYW5kIHRoZSBEVSBwcm9jZXNzZXMKICAgICAgICAgICAgICAgICAgICBQSFkgbGV2ZWwgcHJvdG9jb2wgYW5kIHJlYWwgdGltZSBzZXJ2aWNlcy4gVGhlCiAgICAgICAgICAgICAgICAgICAgZ05CLUNVIGFuZCB0aGUgZ05CLURVIHVuaXRzIGFyZSBjb25uZWN0ZWQgdmlhCiAgICAgICAgICAgICAgICAgICAgRjEgbG9naWNhbCBpbnRlcmZhY2UuCgogICAgICAgICAgICAgICAgICAgIFRoZSBmb2xsb3dpbmcgaXMgdHJ1ZSBmb3IgYSBnTkItRFU6CiAgICAgICAgICAgICAgICAgICAgSXMgY29ubmVjdGVkIHRvIHRoZSBnTkItQ1UtQ1AgdGhyb3VnaCB0aGUgRjEtQwogICAgICAgICAgICAgICAgICAgIGludGVyZmFjZS5JcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1DVS1VUCB0aHJvdWdoCiAgICAgICAgICAgICAgICAgICAgdGhlIEYxLVUgaW50ZXJmYWNlLiBPbmUgZ05CLURVIGlzIGNvbm5lY3RlZCB0byBvbmx5CiAgICAgICAgICAgICAgICAgICAgb25lIGdOQi1DVS1DUC4gT25lIGdOQi1EVSBjYW4gYmUgY29ubmVjdGVkIHRvCiAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUgZ05CLUNVLVVQcyB1bmRlciB0aGUgY29udHJvbCBvZiB0aGUgc2FtZQogICAgICAgICAgICAgICAgICAgIGdOQi1DVS1DUC4KICAgICAgICAgICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUKICAgICAgICAgICAgICAgICAgICBnTkItQ1UtVVBzIGFuZCBtdWx0aXBsZSBnTkItRFVzLiBnTkItRFUgaXMgYSBjb25jcmV0ZQogICAgICAgICAgICAgICAgICAgIGNsYXNzIHRoYXQgZXh0ZW5kcyB0aGUgTkctUkFOIG5vZGUgb2JqZWN0LiBJbiBUb3BvbG9neSwgeW91CiAgICAgICAgICAgICAgICAgICAgY2FuIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlIHRoZSBnTkItRFUgb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZmRuIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIEZ1bGwgRGlzdGluZ3Vpc2hlZCBOYW1lIChGRE4pIGlkZW50aWZpZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuIGluc3RhbmNlIG9mIHRoZSBHTkJEVUZ1bmN0aW9uIE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgR05CRFVGdW5jdGlvbi4iOwogICAgICAgICAgICAgICAgdHlwZSBvci10ZWl2LXR5cGVzOl8zR1BQX0ZETl9UeXBlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBjb250YWluZXIgZFVwTE1OSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlBMTU4gaWRlbnRpZmllciB1c2VkIGFzIHBhcnQgb2YgUE0gRXZlbnRzIGRhdGEiOwogICAgICAgICAgICAgICAgdXNlcyB0eXBlczNncHA6UExNTklkOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGdOQkRVSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgRFUgd2l0aGluIGEgZ05vZGVCIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGdOQklkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJJZGVudGl0eSBvZiBnTm9kZUIgd2l0aGluIGEgUExNTiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBjbUlkIHsKICAgICAgICAgICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpDTV9JRDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEdOQkNVQ1BGdW5jdGlvbiB7CiAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQiBDZW50cmFsaXplZCBVbml0IENvbnRyb2wgUGxhbmUgKGdOQi1DVS1DUCkKCiAgICAgICAgICAgICAgICAgICAgVGhpcyBpcyBhIGxvZ2ljYWwgbm9kZSBob3N0aW5nIHRoZSBSYWRpbyBSZXNvdXJjZQogICAgICAgICAgICAgICAgICAgIENvbnRyb2wgKFJSQykgYW5kIHRoZSBjb250cm9sIHBsYW5lIHBhcnQgb2YgdGhlCiAgICAgICAgICAgICAgICAgICAgUGFja2V0IERhdGEgQ29udmVyZ2VuY2UgUHJvdG9jb2wgKFBEQ1ApIG9mIHRoZQogICAgICAgICAgICAgICAgICAgIGdOb2RlQiBDZW50cmFsaXplZCBVbml0IChnTkItQ1UpIGZvciBhbiBFLVVUUkFOIGdOb2RlQgogICAgICAgICAgICAgICAgICAgIChlbi1nTkIpIG9yIGEgZ05vZGVCIChnTkIpLiBUaGUgZ05CLUNVLUNQIHRlcm1pbmF0ZXMKICAgICAgICAgICAgICAgICAgICB0aGUgRTEgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTkItQ1UtVVAgYW5kIHRoZQogICAgICAgICAgICAgICAgICAgIEYxLUMgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTm9kZUIKICAgICAgICAgICAgICAgICAgICBEaXN0cmlidXRlZCBVbml0IChnTkItRFUpLgoKICAgICAgICAgICAgICAgICAgICBUaGUgZm9sbG93aW5nIGlzIHRydWUgZm9yIGEgZ05CLUNVLUNQOgogICAgICAgICAgICAgICAgICAgIElzIGNvbm5lY3RlZCB0byB0aGUgZ05CLURVIHRocm91Z2ggdGhlIEYxLUMgaW50ZXJmYWNlLgogICAgICAgICAgICAgICAgICAgIElzIGNvbm5lY3RlZCB0byB0aGUgZ05CLUNVLVVQIHRocm91Z2ggdGhlIEUxIGludGVyZmFjZS4KICAgICAgICAgICAgICAgICAgICBPbmx5IG9uZSBnTkItQ1UtQ1AgaXMgY29ubmVjdGVkIHRvIG9uZSBnTkItRFUuCiAgICAgICAgICAgICAgICAgICAgT25seSBvbmUgZ05CLUNVLUNQIGlzIGNvbm5lY3RlZCB0byBvbmUgZ05CLUNVLVVQLgogICAgICAgICAgICAgICAgICAgIE9uZSBnTkItRFUgY2FuIGJlIGNvbm5lY3RlZCB0byBtdWx0aXBsZSBnTkItQ1UtVVBzCiAgICAgICAgICAgICAgICAgICAgdW5kZXIgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLk9uZSBnTkItQ1UtVVAKICAgICAgICAgICAgICAgICAgICBjYW4gYmUgY29ubmVjdGVkIHRvIG11bHRpcGxlIERVcyB1bmRlciB0aGUgY29udHJvbCBvZgogICAgICAgICAgICAgICAgICAgIHRoZSBzYW1lIGdOQi1DVS1DUC4KICAgICAgICAgICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUKICAgICAgICAgICAgICAgICAgICBnTkItQ1UtVVBzIGFuZCBtdWx0aXBsZSBnTkItRFVzLiBBIGdOQi1DVS1DUCBpcyBhCiAgICAgICAgICAgICAgICAgICAgY29uY3JldGUgY2xhc3MgdGhhdCBleHRlbmRzIHRoZSBORy1SQU4gbm9kZSBvYmplY3QuCiAgICAgICAgICAgICAgICAgICAgSW4gVG9wb2xvZ3ksIHlvdSBjYW4gY3JlYXRlLCByZWFkLCB1cGRhdGUsIGFuZCBkZWxldGUKICAgICAgICAgICAgICAgICAgICB0aGUgZ05CLUNVLUNQIG9iamVjdC4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGZkbiB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBGdWxsIERpc3Rpbmd1aXNoZWQgTmFtZSAoRkROKSBpZGVudGlmaWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiB0aGUgR05CQ1VDUEZ1bmN0aW9uIE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgR05CQ1VDUEZ1bmN0aW9uLiI7CiAgICAgICAgICAgICAgICB0eXBlIG9yLXRlaXYtdHlwZXM6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZ05CQ1VOYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIGdOb2RlQi1DVSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZ05CSWRMZW5ndGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxlbmd0aCBvZiBnTkJJZCBiaXQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBjb250YWluZXIgcExNTklkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJQTE1OIGlkZW50aWZpZXIgdG8gYmUgdXNlZCBhcyBwYXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZiBnbG9iYWwgUkFOIG5vZGUgaWRlbnRpdHkiOwogICAgICAgICAgICAgICAgdXNlcyB0eXBlczNncHA6UExNTklkOwogICAgICAgICAgICB9CgogICAgICAgICAgICBjb250YWluZXIgY21JZCB7CiAgICAgICAgICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6Q01fSUQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBHTkJDVVVQRnVuY3Rpb24gewogICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUIgQ2VudHJhbGl6ZWQgVW5pdCBVc2VyIFBsYW5lIChnTkItQ1UtVVApCgogICAgICAgICAgICAgICAgICAgIEEgZ05CLUNVLVVQIGlzIGEgbG9naWNhbCBub2RlIGhvc3RpbmcgdGhlIFVzZXIKICAgICAgICAgICAgICAgICAgICBQbGFuZSBwYXJ0IG9mIHRoZSBQYWNrZXQgRGF0YSBDb252ZXJnZW5jZSwKICAgICAgICAgICAgICAgICAgICBQcm90b2NvbCAoUERDUCkgb2YgdGhlIGdOb2RlQiBDZW50cmFsaXplZCBVbml0CiAgICAgICAgICAgICAgICAgICAgKGdOQi1DVSkgZm9yIGFuIEUtVVRSQU4gZ05vZGVCIChlbi1nTkIpLCBhbmQgdGhlCiAgICAgICAgICAgICAgICAgICAgVXNlciBQbGFuZSBwYXJ0IG9mIHRoZSBQRENQIHByb3RvY29sIGFuZCB0aGUKICAgICAgICAgICAgICAgICAgICBTZXJ2aWNlIERhdGEgQWRhcHRhdGlvbiBQcm90b2NvbCAoU0RBUCkgb2YgdGhlCiAgICAgICAgICAgICAgICAgICAgZ05CLUNVIGZvciBhIGdOb2RlQiAoZ05CKS4gVGhlIGdOQi1DVS1VUCB0ZXJtaW5hdGVzCiAgICAgICAgICAgICAgICAgICAgdGhlIEUxIGludGVyZmFjZSBjb25uZWN0ZWQgd2l0aCB0aGUgZ05CLUNVLUNQIGFuZAogICAgICAgICAgICAgICAgICAgIHRoZSBGMS1VIGludGVyZmFjZSBjb25uZWN0ZWQgd2l0aCB0aGUgZ05vZGVCCiAgICAgICAgICAgICAgICAgICAgRGlzdHJpYnV0ZWQgVW5pdCAoZ05CLURVKS4KCiAgICAgICAgICAgICAgICAgICAgVGhlIGZvbGxvd2luZyBpcyB0cnVlIGZvciBhIGdOQi1DVS1VUDoKICAgICAgICAgICAgICAgICAgICBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1EVSB0aHJvdWdoIHRoZQogICAgICAgICAgICAgICAgICAgIEYxLVUgaW50ZXJmYWNlLiBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1DVS1DUCB0aHJvdWdoCiAgICAgICAgICAgICAgICAgICAgdGhlIEUxIGludGVyZmFjZS4gT25lIGdOQi1DVS1VUCBpcyBjb25uZWN0ZWQgdG8gb25seSBvbmUKICAgICAgICAgICAgICAgICAgICBnTkItQ1UtQ1AuIE9uZSBnTkItRFUgY2FuIGJlIGNvbm5lY3RlZCB0byBtdWx0aXBsZQogICAgICAgICAgICAgICAgICAgIGdOQi1DVS1VUHMgdW5kZXIgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLiBPbmUKICAgICAgICAgICAgICAgICAgICBnTkItQ1UtVVAgY2FuIGJlIGNvbm5lY3RlZCB0byBtdWx0aXBsZSBEVXMgdW5kZXIgdGhlCiAgICAgICAgICAgICAgICAgICAgY29udHJvbCBvZiB0aGUgc2FtZSBnTkItQ1UtQ1AuCiAgICAgICAgICAgICAgICAgICAgTm90ZTogQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ1UtQ1AsIG11bHRpcGxlIGdOQi1DVS1VUHMKICAgICAgICAgICAgICAgICAgICBhbmQgbXVsdGlwbGUgZ05CLURVcy4gQSBnTkItQ1UtVVAgaXMgYSBjb25jcmV0ZSBjbGFzcyB0aGF0CiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kcyB0aGUgTkctUkFOIG5vZGUgb2JqZWN0LiBJbiBUb3BvbG9neSwgeW91IGNhbgogICAgICAgICAgICAgICAgICAgIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlIHRoZSBnTkItQ1UtVVAgb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZmRuIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIEZ1bGwgRGlzdGluZ3Vpc2hlZCBOYW1lIChGRE4pIGlkZW50aWZpZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuIGluc3RhbmNlIG9mIHRoZSBHTkJDVVVQRnVuY3Rpb24gTU8uIEl0IGNvbnRhaW5zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgZnVsbCBwYXRoIGZyb20gdGhlIFN1Ym5ldHdvcmsgdG8gdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBHTkJDVVVQRnVuY3Rpb24uIjsKICAgICAgICAgICAgICAgIHR5cGUgb3ItdGVpdi10eXBlczpfM0dQUF9GRE5fVHlwZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZ05CSWRMZW5ndGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxlbmd0aCBvZiBnTkJJZCBiaXQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBjb250YWluZXIgY21JZCB7CiAgICAgICAgICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6Q01fSUQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBOUkNlbGxDVSB7CiAgICAgICAgZGVzY3JpcHRpb24gIlJlcHJlc2VudHMgYW4gTlIgQ2VsbCBpbiBnTm9kZUItQ1UuCgogICAgICAgICAgICAgICAgICAgIDVHIE5SIGlzIGEgbmV3IHJhZGlvIGFjY2VzcyB0ZWNobm9sb2d5IChSQVQpCiAgICAgICAgICAgICAgICAgICAgZGV2ZWxvcGVkIGJ5IDNHUFAgZm9yIHRoZSA1RyAoZmlmdGggZ2VuZXJhdGlvbikKICAgICAgICAgICAgICAgICAgICBtb2JpbGUgbmV0d29yay4gSXQgaXMgZGVzaWduZWQgdG8gYmUgdGhlIGdsb2JhbAogICAgICAgICAgICAgICAgICAgIHN0YW5kYXJkIGZvciB0aGUgYWlyIGludGVyZmFjZSBvZiA1RyBuZXR3b3Jrcy4KCiAgICAgICAgICAgICAgICAgICAgNUcgTlIgaGFzIHN5bmNocm9uaXphdGlvbiBzaWduYWwgdGhhdCBpcyBrbm93biBhcwogICAgICAgICAgICAgICAgICAgIFByaW1hcnkgU3luY2hyb25pemF0aW9uIHNpZ25hbCAoUFNTKSBhbmQgU2Vjb25kYXJ5CiAgICAgICAgICAgICAgICAgICAgU3luY2hyb25pemF0aW9uIHNpZ25hbCAoU1NTKS4gVGhlc2Ugc2lnbmFscyBhcmUKICAgICAgICAgICAgICAgICAgICBzcGVjaWZpYyB0byBOUiBwaHlzaWNhbCBsYXllciBhbmQgcHJvdmlkZSB0aGUKICAgICAgICAgICAgICAgICAgICBmb2xsb3dpbmcgaW5mb3JtYXRpb24gcmVxdWlyZWQgYnkgVUUgZm9yIGRvd25saW5rCiAgICAgICAgICAgICAgICAgICAgc3luY2hyb25pemF0aW9uOiBQU1MgcHJvdmlkZXMgUmFkaW8gRnJhbWUgQm91bmRhcnkKICAgICAgICAgICAgICAgICAgICAoUG9zaXRpb24gb2YgMXN0IFN5bWJvbCBpbiBhIFJhZGlvIGZyYW1lKSBTU1MgcHJvdmlkZXMKICAgICAgICAgICAgICAgICAgICBTdWJmcmFtZSBCb3VuZGFyeSAoUG9zaXRpb24gb2YgMXN0IFN5bWJvbCBpbiBhIFN1YmZyYW1lKQogICAgICAgICAgICAgICAgICAgIFBoeXNpY2FsIExheWVyIENlbGwgSUQgKFBDSSkgaW5mb3JtYXRpb24gdXNpbmcgYm90aAogICAgICAgICAgICAgICAgICAgIFBTUyBhbmQgU1NTLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZmRuIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIEZ1bGwgRGlzdGluZ3Vpc2hlZCBOYW1lIChGRE4pIGlkZW50aWZpZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuIGluc3RhbmNlIG9mIHRoZSBOUkNlbGxDVSBNTy4gSXQgY29udGFpbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBmdWxsIHBhdGggZnJvbSB0aGUgU3VibmV0d29yayB0byB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5SQ2VsbENVLiI7CiAgICAgICAgICAgICAgICB0eXBlIG9yLXRlaXYtdHlwZXM6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgY2VsbExvY2FsSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVzZWQgdG9nZXRoZXIgd2l0aCBnTm9kZUIgaWRlbnRpZmllciB0bwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnRpZnkgTlIgY2VsbCBpbiBQTE1OLiBVc2VkIHRvZ2V0aGVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoIGdOQklkIHRvIGZvcm0gTkNJLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIHBsbW5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBJRCBmb3IgTlIgQ0dJLiBJZiBlbXB0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdOQkNVQ1BGdW5jdGlvbjo6cExNTklkIGlzIHVzZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBQTE1OIElEIGluIE5SIENHSSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgbkNJIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsIElkZW50aXR5IjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG5SVEFDIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBUcmFja2luZyBBcmVhIENvZGUgKFRBQykiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBjbUlkIHsKICAgICAgICAgICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpDTV9JRDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IE5SQ2VsbERVIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyBhbiBOUiBDZWxsIGluIGdOb2RlQi1EVS4KCiAgICAgICAgICAgICAgICAgICAgNUcgTlIgaXMgYSBuZXcgcmFkaW8gYWNjZXNzIHRlY2hub2xvZ3kgKFJBVCkKICAgICAgICAgICAgICAgICAgICBkZXZlbG9wZWQgYnkgM0dQUCBmb3IgdGhlIDVHIChmaWZ0aCBnZW5lcmF0aW9uKQogICAgICAgICAgICAgICAgICAgIG1vYmlsZSBuZXR3b3JrLiBJdCBpcyBkZXNpZ25lZCB0byBiZSB0aGUgZ2xvYmFsCiAgICAgICAgICAgICAgICAgICAgc3RhbmRhcmQgZm9yIHRoZSBhaXIgaW50ZXJmYWNlIG9mIDVHIG5ldHdvcmtzLgoKICAgICAgICAgICAgICAgICAgICA1RyBOUiBoYXMgc3luY2hyb25pemF0aW9uIHNpZ25hbCB0aGF0IGlzIGtub3duIGFzCiAgICAgICAgICAgICAgICAgICAgUHJpbWFyeSBTeW5jaHJvbml6YXRpb24gc2lnbmFsIChQU1MpIGFuZCBTZWNvbmRhcnkKICAgICAgICAgICAgICAgICAgICBTeW5jaHJvbml6YXRpb24gc2lnbmFsIChTU1MpLiBUaGVzZSBzaWduYWxzIGFyZQogICAgICAgICAgICAgICAgICAgIHNwZWNpZmljIHRvIE5SIHBoeXNpY2FsIGxheWVyIGFuZCBwcm92aWRlIHRoZQogICAgICAgICAgICAgICAgICAgIGZvbGxvd2luZyBpbmZvcm1hdGlvbiByZXF1aXJlZCBieSBVRSBmb3IgZG93bmxpbmsKICAgICAgICAgICAgICAgICAgICBzeW5jaHJvbml6YXRpb246IFBTUyBwcm92aWRlcyBSYWRpbyBGcmFtZSBCb3VuZGFyeQogICAgICAgICAgICAgICAgICAgIChQb3NpdGlvbiBvZiAxc3QgU3ltYm9sIGluIGEgUmFkaW8gZnJhbWUpIFNTUyBwcm92aWRlcwogICAgICAgICAgICAgICAgICAgIFN1YmZyYW1lIEJvdW5kYXJ5IChQb3NpdGlvbiBvZiAxc3QgU3ltYm9sIGluIGEgU3ViZnJhbWUpCiAgICAgICAgICAgICAgICAgICAgUGh5c2ljYWwgTGF5ZXIgQ2VsbCBJRCAoUENJKSBpbmZvcm1hdGlvbiB1c2luZyBib3RoCiAgICAgICAgICAgICAgICAgICAgUFNTIGFuZCBTU1MuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBmZG4gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoaXMgRnVsbCBEaXN0aW5ndWlzaGVkIE5hbWUgKEZETikgaWRlbnRpZmllcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW4gaW5zdGFuY2Ugb2YgdGhlIE5SQ2VsbERVIE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgTlJDZWxsRFUuIjsKICAgICAgICAgICAgICAgIHR5cGUgb3ItdGVpdi10eXBlczpfM0dQUF9GRE5fVHlwZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBjZWxsTG9jYWxJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVXNlZCB0b2dldGhlciB3aXRoIGdOb2RlQiBpZGVudGlmaWVyIHRvIGlkZW50aWZ5IE5SCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbCBpbiBQTE1OLiBVc2VkIHRvZ2V0aGVyIHdpdGggZ05CSWQgdG8gZm9ybSBOQ0kuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG5DSSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbCBJZGVudGl0eS4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgblJQQ0kgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBQaHlzaWNhbCBDZWxsIElkZW50aXR5IChQQ0kpIG9mIHRoZSBOUiBjZWxsLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBuUlRBQyB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgVHJhY2tpbmcgQXJlYSBDb2RlIChUQUMpLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgRU5vZGVCRnVuY3Rpb24gewogICAgICAgIGRlc2NyaXB0aW9uICJBbiBFdm9sdmVkIE5vZGUgQiAoZU5vZGVCKSBpcyB0aGUgb25seSBtYW5kYXRvcnkKICAgICAgICAgICAgICAgICAgICBub2RlIGluIHRoZSByYWRpbyBhY2Nlc3MgbmV0d29yayAoUkFOKSBvZiBMb25nLVRlcm0KICAgICAgICAgICAgICAgICAgICBFdm9sdXRpb24gKExURSkuIFRoZSBlTm9kZUIgaXMgYSBjb21wbGV4IGJhc2UKICAgICAgICAgICAgICAgICAgICBzdGF0aW9uIHRoYXQgaGFuZGxlcyByYWRpbyBjb21tdW5pY2F0aW9ucwogICAgICAgICAgICAgICAgICAgIGluIHRoZSBjZWxsIGFuZCBjYXJyaWVzIG91dCByYWRpbyByZXNvdXJjZQogICAgICAgICAgICAgICAgICAgIG1hbmFnZW1lbnQgYW5kIGhhbmRvdmVyIGRlY2lzaW9ucy4gVW5saWtlIDIvM0cKICAgICAgICAgICAgICAgICAgICB3aXJlbGVzcyBSQU4sIHRoZXJlIGlzIG5vIGNlbnRyYWxpemVkIHJhZGlvIG5ldHdvcmsKICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyIGluIExURS4gSXQgaXMgdGhlIGhhcmR3YXJlIHRoYXQgaXMgY29ubmVjdGVkCiAgICAgICAgICAgICAgICAgICAgdG8gdGhlIG1vYmlsZSBwaG9uZSBuZXR3b3JrIHRoYXQgY29tbXVuaWNhdGVzCiAgICAgICAgICAgICAgICAgICAgZGlyZWN0bHkgd2l0aCBtb2JpbGUgaGFuZHNldHMgKFVzZXIgRXF1aXBtZW50KSwgbGlrZSBhIGJhc2UKICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlciBzdGF0aW9uIChCVFMpIGluIEdTTSBuZXR3b3Jrcy4gVGhpcyBzaW1wbGlmaWVzCiAgICAgICAgICAgICAgICAgICAgdGhlIGFyY2hpdGVjdHVyZSBhbmQgYWxsb3dzIGxvd2VyIHJlc3BvbnNlIHRpbWVzLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZmRuIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIEZ1bGwgRGlzdGluZ3Vpc2hlZCBOYW1lIChGRE4pIGlkZW50aWZpZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuIGluc3RhbmNlIG9mIHRoZSBFTm9kZUJGdW5jdGlvbiBNTy4gSXQgY29udGFpbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBmdWxsIHBhdGggZnJvbSB0aGUgU3VibmV0d29yayB0byB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVOb2RlQkZ1bmN0aW9uLiI7CiAgICAgICAgICAgICAgICB0eXBlIG9yLXRlaXYtdHlwZXM6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZU5CSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgSUQgdGhhdCBmb3JtcyBwYXJ0IG9mCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgQ2VsbCBHbG9iYWwgSWRlbnRpdHksIGFuZCBpcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxzbyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBub2RlIG92ZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBTMSBpbnRlcmZhY2UiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBlTm9kZUJQbG1uSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgUHVibGljIExhbmQgTW9iaWxlIE5ldHdvcmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChQTE1OKSBJRCB0aGF0IGZvcm1zIHBhcnQgb2YgdGhlIEVOb2RlQgogICAgICAgICAgICAgICAgICAgICAgICAgICAgR2xvYmFsIElEIHVzZWQgdG8gaWRlbnRpZnkgdGhlIG5vZGUgb3ZlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIFMxIGludGVyZmFjZS4gTm90ZTogVGhlIHZhbHVlIChNQ0M9MDAxLCBNTkM9MDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2F0ZXMgdGhhdCB0aGUgUExNTiBpcyBub3QgaW5pdGlhdGVkLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIGNhbiBub3QgYmUgdXNlZCBhcyBhIHZhbGlkIFBMTU4gSWRlbnRpdHkuIjsKCiAgICAgICAgICAgICAgICBsZWFmIG1jYyB7CiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBNQ0MgcGFydCBvZiBhIFBMTU4gaWRlbnRpdHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VkIGluIHRoZSByYWRpbyBuZXR3b3JrLiI7CiAgICAgICAgICAgICAgICAgICAgdHlwZSBpbnQzMiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlIDAuLjk5OTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZWFmIG1uYyB7CiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBNTkMgcGFydCBvZiBhIFBMTU4gaWRlbnRpdHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VkIGluIHRoZSByYWRpbyBuZXR3b3JrLiI7CiAgICAgICAgICAgICAgICAgICAgdHlwZSBpbnQzMiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlIDAuLjk5OTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZWFmIG1uY0xlbmd0aCB7CiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBsZW5ndGggb2YgdGhlIE1OQyBwYXJ0IG9mIGEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQTE1OIGlkZW50aXR5IHVzZWQgaW4gdGhlIHJhZGlvIG5ldHdvcmsuIjsKICAgICAgICAgICAgICAgICAgICB0eXBlIGludDMyIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgMi4uMzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBjbUlkIHsKICAgICAgICAgICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpDTV9JRDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEVVdHJhbkNlbGwgewogICAgICAgIGRlc2NyaXB0aW9uICJSZXByZXNlbnRzIGFuIEZERCBvciBUREQgRVV0cmFuQ2VsbCBhbmQKICAgICAgICAgICAgICAgICAgICBjb250YWlucyBwYXJhbWV0ZXJzIG5lZWRlZCBieSB0aGUgY2VsbC4KICAgICAgICAgICAgICAgICAgICBJdCBhbHNvIGNvbnRhaW5zIHBhcmFtZXRlcnMgZm9yIHRoZQogICAgICAgICAgICAgICAgICAgIG1hbmRhdG9yeSBjb21tb24gY2hhbm5lbHMuIEFuIEVVVFJBTiBzdGFuZHMKICAgICAgICAgICAgICAgICAgICBmb3IgRXZvbHZlZCBVbml2ZXJzYWwgTW9iaWxlIFRlbGVjb21tdW5pY2F0aW9ucwogICAgICAgICAgICAgICAgICAgIFN5c3RlbSAoVU1UUykgVGVycmVzdHJpYWwgUmFkaW8gQWNjZXNzIE5ldHdvcmsKICAgICAgICAgICAgICAgICAgICB3aGljaCBjb250YWlucyBhbiBlTm9kZUIuIFRoZSBlTm9kZUIgY29uY3JldGUKICAgICAgICAgICAgICAgICAgICBjbGFzcyBpcyBleHRlbmRlZCBmcm9tIHRoZSBFVVRSQU4gTm9kZSBhYnN0cmFjdCBjbGFzcy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGZkbiB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBGdWxsIERpc3Rpbmd1aXNoZWQgTmFtZSAoRkROKSBpZGVudGlmaWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiBlaXRoZXIgdGhlIEVVdHJhbkNlbGxGREQgTU8gb3IKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBFVXRyYW5DZWxsVEREIE1PLiBJdCBjb250YWlucyB0aGUgZnVsbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZSBFVXRyYW5DZWxsRkREIG9yCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFVXRyYW5DZWxsVERELiI7CiAgICAgICAgICAgICAgICB0eXBlIG9yLXRlaXYtdHlwZXM6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgY2VsbElkewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlJCUyBpbnRlcm5hbCBJRCBhdHRyaWJ1dGUgZm9yIEVVdHJhbkNlbGwuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBNdXN0IGJlIHVuaXF1ZSBpbiB0aGUgUkJTLiBUb2dldGhlciB3aXRoIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgTm9kZSBJRCBhbmQgUHVibGljIExhbmQgTW9iaWxlIE5ldHdvcmsgKFBMTU4pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzIGlzIGEgdW5pdmVyc2FsbHkgdW5pcXVlIGNlbGwgSUQiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZWFyZmNuZGwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjaGFubmVsIG51bWJlciBmb3IgdGhlIGNlbnRyYWwgZG93bmxpbmsgZnJlcXVlbmN5LiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBlYXJmY251bCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiQ2hhbm5lbCBudW1iZXIgZm9yIHRoZSBjZW50cmFsIHVwbGluayBmcmVxdWVuY3kiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZGxDaGFubmVsQmFuZHdpZHRoIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgZG93bmxpbmsgY2hhbm5lbCBiYW5kd2lkdGggaW4gdGhlIEZERCBjZWxsLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBlYXJmY24gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFLVVUUkEgQWJzb2x1dGUgUmFkaW8gRnJlcXVlbmN5IENoYW5uZWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE51bWJlciAoRUFSRkNOKSBmb3IgdGhlIFRERCBjZWxsIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGNoYW5uZWxCYW5kd2lkdGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjaGFubmVsIGJhbmR3aWR0aCBpbiB0aGUgVEREIGNlbGwuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIHRhYyB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVHJhY2tpbmcgQXJlYSBDb2RlIGZvciB0aGUgRVV0cmFuIENlbGwiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZHVwbGV4VHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdG9yIG9mIEVVdHJhbkNlbGwgdHlwZSwgRkREIG9yIFRERCI7CiAgICAgICAgICAgICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICAgICAgICAgICAgICBlbnVtIGZkZCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJGREQiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbnVtIHRkZCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUREQiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTlJTZWN0b3JDYXJyaWVyIHsKICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIE5SIFNlY3RvciBDYXJyaWVyIG9iamVjdCBwcm92aWRlcwogICAgICAgICAgICAgICAgICAgIHRoZSBhdHRyaWJ1dGVzIGZvciBkZWZpbmluZyB0aGUgbG9naWNhbAogICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcmlzdGljcyBvZiBhIGNhcnJpZXIgKGNlbGwpIGluIGEKICAgICAgICAgICAgICAgICAgICBzZWN0b3IuIEEgc2VjdG9yIGlzIGEgY292ZXJhZ2UgYXJlYSBhc3NvY2lhdGVkCiAgICAgICAgICAgICAgICAgICAgd2l0aCBhIGJhc2Ugc3RhdGlvbiBoYXZpbmcgaXRzIG93biBhbnRlbm5hcywKICAgICAgICAgICAgICAgICAgICByYWRpbyBwb3J0cywgYW5kIGNvbnRyb2wgY2hhbm5lbHMuIFRoZSBjb25jZXB0CiAgICAgICAgICAgICAgICAgICAgb2Ygc2VjdG9ycyB3YXMgZGV2ZWxvcGVkIHRvIGltcHJvdmUgY28tY2hhbm5lbAogICAgICAgICAgICAgICAgICAgIGludGVyZmVyZW5jZSBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcwogICAgICAgICAgICAgICAgICAgIHN5c3RlbXMgdXNlIHRocmVlIHNlY3RvciBjZWxscy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGZkbiB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBGdWxsIERpc3Rpbmd1aXNoZWQgTmFtZSAoRkROKSBpZGVudGlmaWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiB0aGUgTlJTZWN0b3JDYXJyaWVyIE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgTlJTZWN0b3JDYXJyaWVyLiI7CiAgICAgICAgICAgICAgICB0eXBlIG9yLXRlaXYtdHlwZXM6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgYXJmY25ETCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQWJzb2x1dGUgUmFkaW8gRnJlcXVlbmN5IENoYW5uZWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE51bWJlciAoTlItQVJGQ04pIGZvciBkb3dubGluayI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBhcmZjblVMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBBYnNvbHV0ZSBSYWRpbyBmcmVxdWVuY3kgQ2hhbm5lbCBOdW1iZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChOUi1BUkZDTikgZm9yIHVwbGluay4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZnJlcXVlbmN5REwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlJGIFJlZmVyZW5jZSBGcmVxdWVuY3kgb2YgZG93bmxpbmsgY2hhbm5lbCI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBmcmVxdWVuY3lVTCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUkYgUmVmZXJlbmNlIEZyZXF1ZW5jeSBvZiB1cGxpbmsgY2hhbm5lbCI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBiU0NoYW5uZWxCd0RMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJCUyBDaGFubmVsIGJhbmR3aWR0aCBpbiBNSHogZm9yIGRvd25saW5rLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTFRFU2VjdG9yQ2FycmllciB7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBMVEUgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZQogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMgZm9yIGRlZmluaW5nIHRoZSBsb2dpY2FsIGNoYXJhY3RlcmlzdGljcwogICAgICAgICAgICAgICAgICAgIG9mIGEgY2FycmllciAoY2VsbCkgaW4gYSBzZWN0b3IuIEEgc2VjdG9yIGlzIGEgY292ZXJhZ2UKICAgICAgICAgICAgICAgICAgICBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbiBoYXZpbmcKICAgICAgICAgICAgICAgICAgICBpdHMgb3duIGFudGVubmFzLCByYWRpbyBwb3J0cywgYW5kIGNvbnRyb2wgY2hhbm5lbHMuCiAgICAgICAgICAgICAgICAgICAgVGhlIGNvbmNlcHQgb2Ygc2VjdG9ycyB3YXMgZGV2ZWxvcGVkIHRvIGltcHJvdmUgY28tY2hhbm5lbAogICAgICAgICAgICAgICAgICAgIGludGVyZmVyZW5jZSBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zCiAgICAgICAgICAgICAgICAgICAgdXNlIHRocmVlIHNlY3RvciBjZWxscy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGZkbiB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBGdWxsIERpc3Rpbmd1aXNoZWQgTmFtZSAoRkROKSBpZGVudGlmaWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiB0aGUgU2VjdG9yQ2FycmllciBNTy4gSXQgY29udGFpbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBmdWxsIHBhdGggZnJvbSB0aGUgU3VibmV0d29yayB0byB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlY3RvckNhcnJpZXIuIjsKICAgICAgICAgICAgICAgIHR5cGUgb3ItdGVpdi10eXBlczpfM0dQUF9GRE5fVHlwZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBzZWN0b3JDYXJyaWVyVHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoZSBzZWN0b3IgY2FycmllcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxsZWQgYnkgTU8gU2VjdG9yQ2FycmllciBpcyBhIGRpZ2l0YWwgc2VjdG9yLiI7CiAgICAgICAgICAgICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICAgICAgICAgICAgICBlbnVtIG5vcm1hbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAwOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTm90IGEgZGlnaXRhbCBzZWN0b3IiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbnVtIGxlZnRfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAxOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVmdCBkaWdpdGFsIHNlY3RvciBmb3IgMkRTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSByaWdodF9kaWdpdGFsX3NlY3RvciB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSaWdodCBkaWdpdGFsIHNlY3RvciBmb3IgMkRTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBsZWZ0X2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDM7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMZWZ0IGRpZ2l0YWwgc2VjdG9yIGZvciAzRFMiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbnVtIHJpZ2h0X2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSaWdodCBkaWdpdGFsIHNlY3RvciBmb3IgM0RTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBtaWRkbGVfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA1OwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWlkZGxlIGRpZ2l0YWwgc2VjdG9yIGZvciAzRFMiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgQW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIE1PIHNlcnZlcyBhcyBhIG1hcHBpbmcgYmV0d2VlbiB0aGUgY2VsbAogICAgICAgICAgICAgICAgICAgIGFuZCB0aGUgUkJTIGVxdWlwbWVudCB1c2VkIHRvIHByb3ZpZGUgY292ZXJhZ2UKICAgICAgICAgICAgICAgICAgICBpbiBhIGNlcnRhaW4gZ2VvZ3JhcGhpY2FsIGFyZWEuIFRoZSBNTyBhbHNvCiAgICAgICAgICAgICAgICAgICAgY29udHJvbHMgdGhlIG1heGltdW0gb3V0cHV0IHBvd2VyIG9mIHRoZSBzZWN0b3IuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBmZG4gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoaXMgRnVsbCBEaXN0aW5ndWlzaGVkIE5hbWUgKEZETikgaWRlbnRpZmllcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW4gaW5zdGFuY2Ugb2YgdGhlIFNlY3RvckVxdWlwbWVudEZ1bmN0aW9uIE1PLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgSXQgY29udGFpbnMgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byB0aGUgU2VjdG9yRXF1aXBtZW50RnVuY3Rpb24uIjsKICAgICAgICAgICAgICAgIHR5cGUgb3ItdGVpdi10eXBlczpfM0dQUF9GRE5fVHlwZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZi1saXN0IGVVdHJhbkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgTFRFIGZyZXF1ZW5jeSBiYW5kcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCBhc3NvY2lhdGVkIGhhcmR3YXJlIHN1cHBvcnRzIjsKICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgZ2VyYW5GcUJhbmRzIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMaXN0IG9mIEdFUkFOIGZyZXF1ZW5jeSBiYW5kcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCBhc3NvY2lhdGVkIGhhcmR3YXJlIHN1cHBvcnRzIjsKICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgblJGcUJhbmRzIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMaXN0IG9mIE5SIGZyZXF1ZW5jeSBiYW5kcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzb2NpYXRlZCBoYXJkd2FyZSBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgU2VjdG9yIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBncm91cCBvZiBjby1sb2NhdGVkIENlbGxzIHRoYXQKICAgICAgICAgICAgICAgICAgICBoYXZlIGEgc2hhcmVkIGNvdmVyYWdlIGFyZWEuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBzZWN0b3JJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVW5pdmVyc2FsbHkgdW5pcXVlIElEIGdlbmVyYXRlZCBieSB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlY3RvcidzIGRpc2NvdmVyeSBtZWNoYW5pc20uIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDY0OwogICAgICAgICAgICB9CgogICAgICAgICAgICB1c2VzIGdlbzpnZW8tbG9jYXRpb247CgogICAgICAgICAgICBsZWFmIGF6aW11dGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkF2ZXJhZ2UgdmFsdWUgb2YgdGhlIGF6aW11dGhzIG9mIHRoZSBjZWxscwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJpc2luZyB0aGUgc2VjdG9yLCBkZXRlcm1pbmVkIGR1cmluZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VjdG9yIGRpc2NvdmVyeS4iOwogICAgICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjR7CiAgICAgICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB1bml0cyAiZGVncmVlcyI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfRVVUUkFOQ0VMTCB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIEVVVFJBTiBDZWxsLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBFTm9kZUJGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBwcm92aWRlZC1ieS1lbm9kZWJGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCBwcm92aWRlZCBieSBlTm9kZUIgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEVVdHJhbkNlbGw7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHByb3ZpZGVkIGJ5IGVOb2RlQiBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTFRFU2VjdG9yQ2FycmllcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBHTkJEVUZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTERVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIENlbGwtRFUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIEdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZ25iZHVGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLURVIHByb3ZpZGVkIGJ5IGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CRFVGVU5DVElPTl9QUk9WSURFU19OUlNFQ1RPUkNBUlJJRVIgeyAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBwcm92aWRlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBHTkJEVUZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmR1RnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgU2VjdG9yIENhcnJpZXIgcHJvdmlkZWQgYnkgZ05vZGVCLURVIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUlNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CQ1VDUEZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTENVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsQ3UgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVQ1AgRnVuY3Rpb24gcHJvdmlkZXMgTlIgQ2VsbC1DVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgR05CQ1VDUEZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLUNVIHByb3ZpZGVkIGJ5IGdOb2RlQi1DVUNQIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUkNlbGxDVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBFVVRSQU5DRUxMX1VTRVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHVzZWQtbHRlU2VjdG9yQ2FycmllciB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCB1c2VzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRVV0cmFuQ2VsbDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgRVVUUkFOIENlbGwuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBMVEVTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMVEUgU2VjdG9yIENhcnJpZXIgdXNlcyBBbnRlbm5hIENhcGFiaWxpdHkuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYtbGlzdCB1c2VkLWJ5LWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTFRFIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBBbnRlbm5hQ2FwYWJpbGl0eTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5SQ0VMTERVX1VTRVNfTlJTRUNUT1JDQVJSSUVSIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSB1c2VzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBOUkNlbGxEVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LW5yQ2VsbER1IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgTlIgQ2VsbC1EVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTlJTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBTZWN0b3IgQ2FycmllciB1c2VzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1ieS1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTlIgU2VjdG9yIENhcnJpZXIuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgU0VDVE9SX0dST1VQU19OUkNFTExEVSB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IGdyb3VwZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBOUiBDZWxsLURVLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBTZWN0b3I7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgZ3JvdXBlZC1ieS1zZWN0b3IgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSBncm91cGVkIGJ5IFNlY3Rvci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBTRUNUT1JfR1JPVVBTX0VVVFJBTkNFTEwgeyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBFVVRSQU4gQ2VsbC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgU2VjdG9yOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGdyb3VwZWQtYnktc2VjdG9yIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkVVVFJBTiBDZWxsIGdyb3VwZWQgYnkgU2VjdG9yLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBFVXRyYW5DZWxsOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-equipment urn:o-ran:smo-teiv-equipment EQUIPMENT [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWVxdWlwbWVudCB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtZXF1aXBtZW50IjsKICAgIHByZWZpeCBvci10ZWl2LWVxdWlwOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7cHJlZml4IG9yLXRlaXYtdHlwZXM7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IG9yLXRlaXYteWV4dDsgfQoKICAgIGltcG9ydCBpZXRmLWdlby1sb2NhdGlvbiB7CiAgICAgICAgcHJlZml4IGdlbzsKICAgICAgICByZWZlcmVuY2UgIlJGQyA5MTc5OiBBIFlBTkcgR3JvdXBpbmcgZm9yIEdlb2dyYXBoaWMgTG9jYXRpb25zIjsKICAgIH0KCiAgICBvcmdhbml6YXRpb24gIkVyaWNzc29uIEFCIjsKICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOwogICAgZGVzY3JpcHRpb24KICAgICJSQU4gRXF1aXBtZW50IHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIEVxdWlwbWVudCBkb21haW4sIHdoaWNoIGlzIG1vZGVsbGVkIHRvIHVuZGVyc3RhbmQgdGhlIHBoeXNpY2FsCiAgICBsb2NhdGlvbiBvZiBlcXVpcG1lbnQgc3VjaCBhcyBhbnRlbm5hcyBhc3NvY2lhdGVkIHdpdGggYSBjZWxsL2NhcnJpZXIKICAgIGFuZCB0aGVpciByZWxldmFudCBwcm9wZXJ0aWVzIGUuZy4gdGlsdCwgbWF4IHBvd2VyIGV0Yy4iOwoKICAgIHJldmlzaW9uICIyMDI0LTA1LTAyIiB7CiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmRvbWFpbiBFUVVJUE1FTlQ7CgogICAgbGlzdCBBbnRlbm5hTW9kdWxlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gQW50ZW5uYSBNb2R1bGUgcmVwcmVzZW50cyB0aGUKICAgICAgICAgICAgICAgICAgICBwaHlzaWNhbCBhc3BlY3Qgb2YgYW4gYW50ZW5uYS4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGZkbiB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBGdWxsIERpc3Rpbmd1aXNoZWQgTmFtZSAoRkROKSBpZGVudGlmaWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiB0aGUgQW50ZW5uYVN1YlVuaXQgTU8uIEl0IGNvbnRhaW5zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgZnVsbCBwYXRoIGZyb20gdGhlIFN1Ym5ldHdvcmsgdG8gdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBbnRlbm5hU3ViVW5pdC4iOwogICAgICAgICAgICAgICAgdHlwZSBvci10ZWl2LXR5cGVzOl8zR1BQX0ZETl9UeXBlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGFudGVubmFNb2RlbE51bWJlciB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVmVuZG9yLXNwZWNpZmljIGFudGVubmEgbW9kZWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50aWZpZXIuIFRoaXMgYXR0cmlidXRlIGlzIHBhcnQgb2YKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFJU0cgdjMgQURCIFN0YW5kYXJkIGFuZCBoYXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vIG9wZXJhdGlvbmFsIGltcGFjdC4iOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgbWVjaGFuaWNhbEFudGVubmFCZWFyaW5nIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIGJlYXJpbmcgb24gYW50ZW5uYSBzdWJ1bml0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGVyZSBhbnRlbm5hIHVuaXQgaXMgaW5zdGFsbGVkLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBtZWNoYW5pY2FsQW50ZW5uYVRpbHQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBmaXhlZCBhbnRlbm5hIHRpbHQgb2YgdGhlIGluc3RhbGxhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZWQgYXMgdGhlIGluY2xpbmF0aW9uIG9mIHRoZSBhbnRlbm5hCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50IHJlc3BlY3QgdG8gdGhlIHZlcnRpY2FsIHBsYW5lLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgSXQgaXMgYSBzaWduZWQgdmFsdWUuIFBvc2l0aXZlIGluZGljYXRlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bnRpbHQsIGFuZCBuZWdhdGl2ZSBpbmRpY2F0ZXMgdXB0aWx0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBwb3NpdGlvbldpdGhpblNlY3RvciB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSB1bml0IHBvc2l0aW9uIHdpdGhpbiBzZWN0b3IuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaGlzIGF0dHJpYnV0ZSBpcyBwYXJ0IG9mIEFJU0cgdjMgQURCCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFuZGFyZCBhbmQgaGFzIG5vIG9wZXJhdGlvbmFsIGltcGFjdC4iOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgdG90YWxUaWx0IHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUb3RhbCBhbnRlbm5hIGVsZXZhdGlvbiBpbmNsdWRpbmcgdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YWxsZWQgdGlsdCBhbmQgdGhlIHRpbHQgYXBwbGllZCBieQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIFJlbW90ZSBFbGVjdHJpY2FsIFRpbHQgKFJFVCkuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVsZWN0cmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiRWxlY3RyaWNhbGx5LWNvbnRyb2xsZWQgdGlsdCBvZiBtYWluIGJlYW0gbWF4aW11bQogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2l0aCByZXNwZWN0IHRvIGRpcmVjdGlvbiBvcnRob2dvbmFsIHRvIGFudGVubmEKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgYXhpcyAoc2VlIDNHUFAgVFMgMjUuNDY2KS4gVmFsdWUgaXMgc2lnbmVkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsdCBkb3duIGlzIHBvc2l0aXZlLCB0aWx0IHVwIGlzIG5lZ2F0aXZlLiI7CiAgICAgICAgICAgICAgICB0eXBlIHVpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZi1saXN0IGFudGVubmFCZWFtV2lkdGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBhbmd1bGFyIHNwYW4gb2YgdGhlIG1haW4gbG9iZSBvZiB0aGUgYW50ZW5uYSByYWRpYXRpb24KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiBpbiB0aGUgaG9yaXpvbnRhbCBwbGFuZS4gTWVhc3VyZWQgaW4gZGVncmVlcy4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHVzZXMgZ2VvOmdlby1sb2NhdGlvbjsKCiAgICAgICAgICAgIGNvbnRhaW5lciBjbUlkIHsKICAgICAgICAgICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpDTV9JRDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IFNpdGUgewogICAgICAgIGRlc2NyaXB0aW9uICJBIHNpdGUgaXMgYSBwaHlzaWNhbCBsb2NhdGlvbiB3aGVyZSBhbiBBbnRlbm5hIG9yCiAgICAgICAgICAgICAgICAgICAgUGh5c2ljYWwgTkYgY2FuIGJlIGluc3RhbGxlZC4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIG5hbWUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5hbWUgb2YgU2l0ZSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdXNlcyBnZW86Z2VvLWxvY2F0aW9uOwoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgUGh5c2ljYWxORiB7CiAgICAgICAgZGVzY3JpcHRpb24gIlJlcHJlc2VudHMgYSBQaHlzaWNhbCBORiwKICAgICAgICAgICAgICAgICAgICB3aGljaCBpcyB1c2VkIHRvIHJlYWxpc2UgTmV0d29yayBGdW5jdGlvbnMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBuYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIFBoeXNpY2FsIE5GLiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiB0eXBlIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUeXBlIG9mIFBoeXNpY2FsIE5GLiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdXNlcyBnZW86Z2VvLWxvY2F0aW9uOwoKICAgICAgICAgICAgY29udGFpbmVyIGNtSWQgewogICAgICAgICAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOkNNX0lEOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgQU5URU5OQU1PRFVMRV9JTlNUQUxMRURfQVRfU0lURSB7IC8vIDAuLm4gdG8gMC4uMQoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZiBpbnN0YWxsZWQtYXQtc2l0ZSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIE1vZHVsZSBpbnN0YWxsZWQgYXQgU2l0ZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgQW50ZW5uYU1vZHVsZTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IGluc3RhbGxlZC1hbnRlbm5hTW9kdWxlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIlNpdGUgd2hlcmUgQW50ZW5uYSBNb2R1bGUgaXMgaW5zdGFsbGVkLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBTaXRlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgUEhZU0lDQUxORl9JTlNUQUxMRURfQVRfU0lURSB7IC8vIDEuLm4gdG8gMC4uMQoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZiBpbnN0YWxsZWQtYXQtc2l0ZSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJQaHlzaWNhbCBORiBpbnN0YWxsZWQgYXQgU2l0ZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgUGh5c2ljYWxORjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IGluc3RhbGxlZC1waHlzaWNhbE5GIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIlNpdGUgd2hlcmUgUGh5c2ljYWwgTkYgaXMgaW5zdGFsbGVkLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBTaXRlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgICAgIG1pbi1lbGVtZW50cyAxOwogICAgICAgIH0KICAgIH0KfQ== BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-cloud-to-ran urn:o-ran:smo-teiv-cloud-to-ran CLOUD_TO_RAN ["o-ran-smo-teiv-cloud", "o-ran-smo-teiv-ran"] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNsb3VkLXRvLXJhbiB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtY2xvdWQtdG8tcmFuIjsKICAgIHByZWZpeCBvci10ZWl2LWNsb3VkdG9yYW47CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggb3ItdGVpdi10eXBlczsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNsb3VkIHtwcmVmaXggb3ItdGVpdi1jbG91ZDsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1yYW4ge3ByZWZpeCBvci10ZWl2LXJhbjsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiBDbG91ZCB0byBSQU4gTG9naWNhbCB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjMgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIENsb3VkIHRvIFJBTiBMb2dpY2FsIHRvcG9sb2d5IHJlbGF0aW9ucyI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMDIiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIENMT1VEX1RPX1JBTjsKCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5GREVQTE9ZTUVOVF9TRVJWRVNfR05CRFVGVU5DVElPTiB7IC8vIDAuLm4gdG8gMC4ubQoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHNlcnZpY2VkLWduYmR1RnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCRFUgRnVuY3Rpb24gc2VydmljZWQgYnkgdGhpcyBORiBEZXBsb3ltZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBvci10ZWl2LWNsb3VkOk5GRGVwbG95bWVudDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IHNlcnZpbmctbkZEZXBsb3ltZW50IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5GIERlcGxveW1lbnQgdGhhdCBzZXJ2ZXMgdGhpcyBnTm9kZUJEVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46R05CRFVGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5GREVQTE9ZTUVOVF9TRVJWRVNfR05CQ1VDUEZVTkNUSU9OIHsgLy8gMC4ubiB0byAwLi5tCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtZ25iY3VjcEZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQi1DVS1DUCBGdW5jdGlvbiBzZXJ2aWNlZCBieSB0aGlzIE5GIERlcGxveW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtY2xvdWQ6TkZEZXBsb3ltZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1uRkRlcGxveW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTkYgRGVwbG95bWVudCB0aGF0IHNlcnZlcyB0aGlzIGdOb2RlQkNVQ1AgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkNVQ1BGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5GREVQTE9ZTUVOVF9TRVJWRVNfR05CQ1VVUEZVTkNUSU9OIHsgLy8gMC4ubiB0byAwLi5tCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtZ25iY3V1cEZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQi1DVS1VUCBGdW5jdGlvbiBzZXJ2aWNlZCBieSB0aGlzIE5GIERlcGxveW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtY2xvdWQ6TkZEZXBsb3ltZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1uRkRlcGxveW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTkYgRGVwbG95bWVudCB0aGF0IHNlcnZlcyB0aGlzIGdOb2RlQkNVVVAgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkNVVVBGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KfQ== BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-cloud urn:o-ran:smo-teiv-cloud CLOUD [] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNsb3VkIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1jbG91ZCI7CiAgICBwcmVmaXggb3ItdGVpdi1jbG91ZDsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgaWV0Zi1nZW8tbG9jYXRpb24gewogICAgICAgIHByZWZpeCBnZW87CiAgICAgICAgcmVmZXJlbmNlICJSRkMgOTE3OTogQSBZQU5HIEdyb3VwaW5nIGZvciBHZW9ncmFwaGljIExvY2F0aW9ucyI7CiAgICB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiUkFOIENsb3VkIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIENMT1VEIGRvbWFpbiwgd2hpY2ggY29tcHJpc2VzIGNsb3VkIGluZnJhc3RydWN0dXJlIGFuZAogICAgZGVwbG95bWVudCBhc3BlY3RzIHRoYXQgY2FuIGJlIHVzZWQgaW4gdGhlIHRvcG9sb2d5IG1vZGVsLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMDIiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIENMT1VEOwoKICAgIGxpc3QgQ2xvdWRpZmllZE5GIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBSQU4gTmV0d29yayBGdW5jdGlvbiBzb2Z0d2FyZSB0aGF0IGlzIGRlcGxveWVkIGluIHRoZSBPLUNsb3VkIHZpYSBvbmUgb3IgbW9yZSBORiBEZXBsb3ltZW50cy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIG5hbWUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5hbWUgb2YgQ2xvdWRpZmllZCBORiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IE5GRGVwbG95bWVudCB7CiAgICAgICAgZGVzY3JpcHRpb24gIkEgc29mdHdhcmUgZGVwbG95bWVudCBvbiBPLUNsb3VkIHJlc291cmNlcyB0aGF0IHJlYWxpemVzLCBhbGwgb3IgcGFydCBvZiwgYSBDbG91ZGlmaWVkIE5GLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgbmFtZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTmFtZSBvZiBORiBEZXBsb3ltZW50IjsKICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgQ2xvdWROYW1lc3BhY2UgewogICAgICAgIGRlc2NyaXB0aW9uICJDbG91ZE5hbWVzcGFjZSBwcm92aWRlIGEgbWVjaGFuaXNtIGZvciBpc29sYXRpbmcKICAgICAgICAgICAgICAgICAgICBncm91cHMgb2YgcmVzb3VyY2VzIHdpdGhpbiBhIHNpbmdsZSBjbHVzdGVyLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgbmFtZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTmFtZSBvZiBDbG91ZCBOYW1lc3BhY2UiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBOb2RlQ2x1c3RlciB7CiAgICAgICAgZGVzY3JpcHRpb24gIkEgTm9kZUNsdXN0ZXIgbWFuYWdlcyBhIGNvbGxlY3Rpb24gb2YgTm9kZXMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBuYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIE5vZGUgQ2x1c3RlciI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IENsb3VkU2l0ZSB7CiAgICAgICAgZGVzY3JpcHRpb24gIlJlcHJlc2VudHMgdGhlIGluZnJhc3RydWN0dXJlIHRoYXQKICAgICAgICAgICAgICAgICAgICBob3N0cyB0aGUgTkYgRGVwbG95bWVudC4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIG5hbWUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5hbWUgb2YgQ2xvdWQgU2l0ZSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdXNlcyBnZW86Z2VvLWxvY2F0aW9uOwogICAgICAgIH0KICAgIH0KCgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBDTE9VRElGSUVETkZfQ09NUFJJU0VTX05GREVQTE9ZTUVOVCB7IC8vIDEgdG8gMS4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IGNvbXByaXNlZC1uRkRlcGxveW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQ2xvdWRpZmllZCBORiBjb21wcmlzZXMgb2YgdGhlc2UgTkYgRGVwbG95bWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgQ2xvdWRpZmllZE5GOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgICAgIG1pbi1lbGVtZW50cyAxOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBjb21wcmlzZWQtYnktY2xvdWRpZmllZE5GIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5GIERlcGxveW1lbnQgcGFydCBvZiBDbG91ZGlmaWVkIE5GLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBORkRlcGxveW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTkZERVBMT1lNRU5UX0RFUExPWUVEX09OX0NMT1VETkFNRVNQQUNFIHsgLy8gMS4ubiB0byAxLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgZGVwbG95ZWQtb24tY2xvdWROYW1lc3BhY2UgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTkYgRGVwbG95bWVudCBkZXBsb3llZCBvbiBDbG91ZCBOYW1lc3BhY2UuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIE5GRGVwbG95bWVudDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtaW4tZWxlbWVudHMgMTsKICAgICAgICB9CgogICAgICAgIGxlYWYtbGlzdCBkZXBsb3llZC1uRkRlcGxveW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQ2xvdWQgTmFtZXNwYWNlIGRlcGxveXMgTkYgRGVwbG95bWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgQ2xvdWROYW1lc3BhY2U7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgQ0xPVUROQU1FU1BBQ0VfREVQTE9ZRURfT05fTk9ERUNMVVNURVIgeyAvLyAxLi5uIHRvIDEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgZGVwbG95ZWQtb24tbm9kZUNsdXN0ZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQ2xvdWQgTmFtZXNwYWNlIGRlcGxveWVkIG9uIE5vZGUgQ2x1c3Rlci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgQ2xvdWROYW1lc3BhY2U7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgZGVwbG95ZWQtY2xvdWROYW1lc3BhY2UgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTm9kZSBDbHVzdGVyIGRlcGxveXMgQ2xvdWQgTmFtZXNwYWNlLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOb2RlQ2x1c3RlcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtaW4tZWxlbWVudHMgMTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBOT0RFQ0xVU1RFUl9MT0NBVEVEX0FUX0NMT1VEU0lURSB7IC8vIDEuLm4gdG8gMS4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IGxvY2F0ZWQtYXQtY2xvdWRTaXRlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5vZGUgQ2x1c3RlciBsb2NhdGVkIGF0IENsb3VkIFNpdGUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIE5vZGVDbHVzdGVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgICAgIG1pbi1lbGVtZW50cyAxOwogICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IGxvY2F0aW9uLW9mLW5vZGVDbHVzdGVyIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkIFNpdGUgaXMgbG9jYXRpb24gb2YgTm9kZSBDbHVzdGVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBDbG91ZFNpdGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE -o-ran-smo-teiv-equipment-to-ran urn:o-ran:smo-teiv-equipment-to-ran EQUIPMENT_TO_RAN ["o-ran-smo-teiv-equipment", "o-ran-smo-teiv-ran"] 2024-05-02 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWVxdWlwbWVudC10by1yYW4gewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOm8tcmFuOnNtby10ZWl2LWVxdWlwbWVudC10by1yYW4iOwogICAgcHJlZml4IG9yLXRlaXYtZXF1aXB0b3JhbjsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtZXF1aXBtZW50IHtwcmVmaXggb3ItdGVpdi1lcXVpcDsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1yYW4ge3ByZWZpeCBvci10ZWl2LXJhbjsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiBFcXVpcG1lbnQgdG8gTG9naWNhbCB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjMgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIEVxdWlwbWVudCB0byBMb2dpY2FsIHRvcG9sb2d5CiAgICBlbnRpdGllcyBhbmQgcmVsYXRpb25zLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMDIiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIEVRVUlQTUVOVF9UT19SQU47CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBQSFlTSUNBTE5GX1NFUlZFU19HTkJEVUZVTkNUSU9OIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtZ25iZHVGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItRFUgRnVuY3Rpb24gc2VydmljZWQgYnkgdGhpcyBQaHlzaWNhbCBORi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1lcXVpcDpQaHlzaWNhbE5GOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHNlcnZpbmctcGh5c2ljYWxORiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJQaHlzaWNhbCBORiBzZXJ2ZXMgdGhpcyBnTm9kZUItRFUgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBQSFlTSUNBTE5GX1NFUlZFU19HTkJDVUNQRlVOQ1RJT04geyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBzZXJ2aWNlZC1nbmJjdWNwRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVQ1AgRnVuY3Rpb24gc2VydmljZWQgYnkgdGhpcyBQaHlzaWNhbCBORi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1lcXVpcDpQaHlzaWNhbE5GOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHNlcnZpbmctcGh5c2ljYWxORiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJQaHlzaWNhbCBORiBzZXJ2ZXMgdGhpcyBnTm9kZUItQ1VDUCBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46R05CQ1VDUEZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgUEhZU0lDQUxORl9TRVJWRVNfR05CQ1VVUEZVTkNUSU9OIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtZ25iY3V1cEZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQi1DVVVQIEZ1bmN0aW9uIHNlcnZpY2VkIGJ5IHRoaXMgUGh5c2ljYWwgTkYuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtZXF1aXA6UGh5c2ljYWxORjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBzZXJ2aW5nLXBoeXNpY2FsTkYgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiUGh5c2ljYWwgTkYgc2VydmVzIHRoaXMgZ05vZGVCLUNVVVAgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkNVVVBGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIFBIWVNJQ0FMTkZfU0VSVkVTX0VOT0RFQkZVTkNUSU9OIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHNlcnZpY2VkIGJ5IHRoaXMgUGh5c2ljYWwgTkYuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtZXF1aXA6UGh5c2ljYWxORjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBzZXJ2aW5nLXBoeXNpY2FsTkYgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiUGh5c2ljYWwgTkYgc2VydmVzIHRoaXMgZU5vZGVCIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpFTm9kZUJGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIEFOVEVOTkFNT0RVTEVfU0VSVkVTX0FOVEVOTkFDQVBBQklMSVRZIHsgLy8gMC4ubiB0byAwLi5tCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtYW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHNlcnZpY2VkIGJ5IHRoaXMgQW50ZW5uYSBNb2R1bGUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtZXF1aXA6QW50ZW5uYU1vZHVsZTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IHNlcnZpbmctYW50ZW5uYU1vZHVsZSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIE1vZHVsZSBzZXJ2ZXMgdGhpcyBBbnRlbm5hIENhcGFiaWxpdHkuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgU0VDVE9SX0dST1VQU19BTlRFTk5BTU9EVUxFIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgZ3JvdXBlZC1hbnRlbm5hTW9kdWxlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIlNlY3RvciBncm91cHMgQW50ZW5uYSBNb2R1bGUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtcmFuOlNlY3RvcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBncm91cGVkLWJ5LXNlY3RvciB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIE1vZHVsZSBncm91cGVkIGJ5IFNlY3Rvci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1lcXVpcDpBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQp9 BUILT_IN_MODULE IN_USAGE +COPY ties_model.module_reference("name","revision", "namespace", "domain", "includedModules", "content") FROM stdin; +o-ran-smo-teiv-ran-logical-to-cloud 2023-10-24 urn:rdns:o-ran:-ran-logical-to-cloud RAN_LOGICAL_TO_CLOUD ["o-ran-smo-teiv-ran-logical", "o-ran-smo-teiv-ran-cloud"] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbC10by1jbG91ZCB7DQogICAgeWFuZy12ZXJzaW9uIDEuMTsNCiAgICBuYW1lc3BhY2UgInVybjpyZG5zOmNvbTplcmljc3Nvbjp0b3BpbnZtb2RlbDplcmljc3Nvbi10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbC10by1jbG91ZCI7DQogICAgcHJlZml4IHJhbmxvZ3RvY2xvdWRlcml0b3BpbnY7DQoNCiAgICBpbXBvcnQgZXJpY3Nzb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggeWV4dGU7IH0NCg0KICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCB0eXBlc2VyaXRvcGludjsgfQ0KDQogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggeWV4dGVyaXRvcGludjsgfQ0KDQogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbCB7cHJlZml4IHJhbmxvZ2VyaXRvcGludjsgfQ0KDQogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tY2xvdWQge3ByZWZpeCByYW5jbG91ZGVyaXRvcGludjsgfQ0KDQogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7DQogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7DQogICAgZGVzY3JpcHRpb24NCiAgICAiUkFOIExvZ2ljYWwgdG8gUkFOIENsb3VkIHRvcG9sb2d5IG1vZGVsLg0KDQogICAgQ29weXJpZ2h0IChjKSAyMDIzIEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KDQogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIExvZ2ljYWwgdG8gUkFOIENsb3VkIHRvcG9sb2d5IHJlbGF0aW9ucyI7DQoNCiAgICByZXZpc2lvbiAiMjAyMy0xMC0yNCIgew0KICAgICAgICBkZXNjcmlwdGlvbg0KICAgICAgICAiSW5pdGlhbCByZXZpc2lvbi4iOw0KICAgICAgICB5ZXh0ZTp2ZXJzaW9uICIwIjsNCiAgICAgICAgeWV4dGU6cmVsZWFzZSAiMSI7DQogICAgICAgIHlleHRlOmNvcnJlY3Rpb24gIjEiOw0KICAgIH0NCg0KICAgIHlleHRlcml0b3BpbnY6ZG9tYWluIFJBTl9MT0dJQ0FMX1RPX0NMT1VEOw0KDQogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CRFVGVU5DVElPTl9SRUFMSVNFRF9CWV9DTE9VRE5BVElWRUFQUExJQ0FUSU9OIHsgLy8gMC4ubiB0byAwLi5tDQoNCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7DQogICAgICAgIGtleSBpZDsNCg0KICAgICAgICBsZWFmLWxpc3QgcmVhbGlzZWQtYnktY2xvdWROYXRpdmVBcHBsaWNhdGlvbiB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHJlYWxpc2VkIGJ5DQogICAgICAgICAgICAgICAgICAgICAgICAgQ2xvdWQgTmF0aXZlIEFwcGxpY2F0aW9uLiI7DQogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmFTaWRlIHJhbmxvZ2VyaXRvcGludjpHTkJEVUZ1bmN0aW9uOw0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICB9DQoNCiAgICAgICAgbGVhZi1saXN0IHJlYWxpc2VkLWduYmR1RnVuY3Rpb24gew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkIE5hdGl2ZSBBcHBsaWNhdGlvbiByZWFsaXNlcyBnTm9kZUJEVSBGdW5jdGlvbi4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjpiU2lkZSByYW5jbG91ZGVyaXRvcGludjpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOw0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICB9DQogICAgfQ0KDQogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CQ1VDUEZVTkNUSU9OX1JFQUxJU0VEX0JZX0NMT1VETkFUSVZFQVBQTElDQVRJT04geyAvLyAwLi5uIHRvIDAuLm0NCg0KICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsNCiAgICAgICAga2V5IGlkOw0KDQogICAgICAgIGxlYWYtbGlzdCByZWFsaXNlZC1ieS1jbG91ZE5hdGl2ZUFwcGxpY2F0aW9uIHsNCiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItQ1UtQ1AgRnVuY3Rpb24gcmVhbGlzZWQgYnkNCiAgICAgICAgICAgICAgICAgICAgICAgIENsb3VkIE5hdGl2ZSBBcHBsaWNhdGlvbi4uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YVNpZGUgcmFubG9nZXJpdG9waW52OkdOQkNVQ1BGdW5jdGlvbjsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KDQogICAgICAgIGxlYWYtbGlzdCByZWFsaXNlZC1nbmJjdWNwRnVuY3Rpb24gew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkIE5hdGl2ZSBBcHBsaWNhdGlvbiByZWFsaXNlcw0KICAgICAgICAgICAgICAgICAgICAgICAgZ05vZGVCQ1VDUCBGdW5jdGlvbi4uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgcmFuY2xvdWRlcml0b3BpbnY6Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIHlleHRlcml0b3BpbnY6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIEdOQkNVVVBGVU5DVElPTl9SRUFMSVNFRF9CWV9DTE9VRE5BVElWRUFQUExJQ0FUSU9OIHsgLy8gMC4ubiB0byAwLi5tDQoNCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7DQogICAgICAgIGtleSBpZDsNCg0KICAgICAgICBsZWFmLWxpc3QgcmVhbGlzZWQtYnktY2xvdWROYXRpdmVBcHBsaWNhdGlvbiB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLVVQIEZ1bmN0aW9uIHJlYWxpc2VkIGJ5DQogICAgICAgICAgICAgICAgICAgICAgICBDbG91ZCBOYXRpdmUgQXBwbGljYXRpb24uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YVNpZGUgcmFubG9nZXJpdG9waW52OkdOQkNVVVBGdW5jdGlvbjsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KDQogICAgICAgIGxlYWYtbGlzdCByZWFsaXNlZC1nbmJjdXVwRnVuY3Rpb24gew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkIE5hdGl2ZSBBcHBsaWNhdGlvbiByZWFsaXNlcw0KICAgICAgICAgICAgICAgICAgICAgICAgZ05vZGVCQ1VVUCBGdW5jdGlvbi4uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgcmFuY2xvdWRlcml0b3BpbnY6Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KICAgIH0NCn0= +o-ran-smo-teiv-ran-equipment 2023-06-26 urn:rdns:o-ran:o-ran-smo-teiv-ran-equipment RAN_EQUIPMENT [] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tZXF1aXBtZW50IHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpyZG5zOmNvbTplcmljc3Nvbjp0b3BpbnZtb2RlbDplcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktcmFuLWVxdWlwbWVudCI7CiAgICBwcmVmaXggcmFuZXF1aXBlcml0b3BpbnY7CgogICAgaW1wb3J0IGVyaWNzc29uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlOyB9CgogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy10eXBlcyB7cHJlZml4IHR5cGVzZXJpdG9waW52OyB9CgogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggeWV4dGVyaXRvcGludjsgfQoKCiAgICBpbXBvcnQgaWV0Zi1nZW8tbG9jYXRpb24gewogICAgICAgIHByZWZpeCBnZW87CiAgICAgICAgcmVmZXJlbmNlICJSRkMgOTE3OTogQSBZQU5HIEdyb3VwaW5nIGZvciBHZW9ncmFwaGljIExvY2F0aW9ucyI7CiAgICB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiUkFOIEVxdWlwbWVudCB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjMgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUKICAgIFJBTiBMb2dpY2FsIGRvbWFpbiwgd2hpY2ggcmVwcmVzZW50cyB0aGUgZnVuY3Rpb25hbCBjYXBhYmlsaXR5CiAgICBvZiB0aGUgZGVwbG95ZWQgUkFOIHRoYXQgYXJlIHJlbGV2YW50IHRvIHJBcHBzIHVzZSBjYXNlcy4iOwoKICAgIHJldmlzaW9uICIyMDIzLTEyLTEyIiB7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIHlleHRlOnZlcnNpb24gIjAiOwogICAgICAgIHlleHRlOnJlbGVhc2UgIjIiOwogICAgICAgIHlleHRlOmNvcnJlY3Rpb24gIjAiOwogICAgfQoKICAgIHlleHRlcml0b3BpbnY6ZG9tYWluIFJBTl9FUVVJUE1FTlQ7CgogICAgbGlzdCBBbnRlbm5hTW9kdWxlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gQW50ZW5uYSBNb2R1bGUgcmVwcmVzZW50cyB0aGUKICAgICAgICAgICAgICAgICAgICBwaHlzaWNhbCBhc3BlY3Qgb2YgYW4gYW50ZW5uYS4iOwoKICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBmZG4gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoaXMgRnVsbCBEaXN0aW5ndWlzaGVkIE5hbWUgKEZETikgaWRlbnRpZmllcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW4gaW5zdGFuY2Ugb2YgdGhlIEFudGVubmFTdWJVbml0IE1PLiBJdCBjb250YWlucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQW50ZW5uYVN1YlVuaXQuIjsKICAgICAgICAgICAgICAgIHR5cGUgdHlwZXNlcml0b3BpbnY6XzNHUFBfRkROX1R5cGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgYW50ZW5uYU1vZGVsTnVtYmVyIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJWZW5kb3Itc3BlY2lmaWMgYW50ZW5uYSBtb2RlbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnRpZmllci4gVGhpcyBhdHRyaWJ1dGUgaXMgcGFydCBvZgogICAgICAgICAgICAgICAgICAgICAgICAgICAgQUlTRyB2MyBBREIgU3RhbmRhcmQgYW5kIGhhcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbm8gb3BlcmF0aW9uYWwgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBtZWNoYW5pY2FsQW50ZW5uYUJlYXJpbmcgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgYmVhcmluZyBvbiBhbnRlbm5hIHN1YnVuaXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoZXJlIGFudGVubmEgdW5pdCBpcyBpbnN0YWxsZWQuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG1lY2hhbmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGZpeGVkIGFudGVubmEgdGlsdCBvZiB0aGUgaW5zdGFsbGF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lZCBhcyB0aGUgaW5jbGluYXRpb24gb2YgdGhlIGFudGVubmEKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgcmVzcGVjdCB0byB0aGUgdmVydGljYWwgcGxhbmUuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJdCBpcyBhIHNpZ25lZCB2YWx1ZS4gUG9zaXRpdmUgaW5kaWNhdGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3dudGlsdCwgYW5kIG5lZ2F0aXZlIGluZGljYXRlcyB1cHRpbHQuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIHBvc2l0aW9uV2l0aGluU2VjdG9yIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIHVuaXQgcG9zaXRpb24gd2l0aGluIHNlY3Rvci4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRoaXMgYXR0cmlidXRlIGlzIHBhcnQgb2YgQUlTRyB2MyBBREIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YW5kYXJkIGFuZCBoYXMgbm8gb3BlcmF0aW9uYWwgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiB0b3RhbFRpbHQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRvdGFsIGFudGVubmEgZWxldmF0aW9uIGluY2x1ZGluZyB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbGxlZCB0aWx0IGFuZCB0aGUgdGlsdCBhcHBsaWVkIGJ5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgUmVtb3RlIEVsZWN0cmljYWwgVGlsdCAoUkVUKS4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZWxlY3RyaWNhbEFudGVubmFUaWx0IHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFbGVjdHJpY2FsbHktY29udHJvbGxlZCB0aWx0IG9mIG1haW4gYmVhbSBtYXhpbXVtCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoIHJlc3BlY3QgdG8gZGlyZWN0aW9uIG9ydGhvZ29uYWwgdG8gYW50ZW5uYQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCBheGlzIChzZWUgM0dQUCBUUyAyNS40NjYpLiBWYWx1ZSBpcyBzaWduZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWx0IGRvd24gaXMgcG9zaXRpdmUsIHRpbHQgdXAgaXMgbmVnYXRpdmUuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgQW50ZW5uYUJlYW1XaWR0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGFuZ3VsYXIgc3BhbiBvZiB0aGUgbWFpbiBsb2JlIG9mIHRoZSBhbnRlbm5hIHJhZGlhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiBpbiB0aGUgaG9yaXpvbnRhbCBwbGFuZS4gTWVhc3VyZWQgaW4gZGVncmVlcy4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZHVwbGV4VHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdG9yIG9mIEVVdHJhbkNlbGwgdHlwZSwgRkREIG9yIFRERCI7CiAgICAgICAgICAgICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICAgICAgICAgICAgICBlbnVtIHR5cGUxIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgMDsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gInR5cGUxIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpTT1VSQ0VfSURTOwogICAgICAgIH0KICAgIH0KCiAgICB5ZXh0ZXJpdG9waW52OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBBTlRFTk5BTU9EVUxFX1VTRVNfQU5URU5OQU1PRFVMRSB7IC8vIFNhbWUgZW50aXR5ICgwLi4xIHRvIDAuLjEpCgogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHVzZWQtYnktYW50ZW5uYU1vZHVsZSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIE1vZHVsZSByZWFsaXNlZCBieSBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmFTaWRlIHJhbmVxdWlwZXJpdG9waW52OkFudGVubmFNb2R1bGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgIH0KCiAgICAgICAgbGVhZi1saXN0IHVzZWQtYW50ZW5uYU1vZHVsZSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIE1vZHVsZSByZWFsaXNlcyBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmJTaWRlIHJhbmVxdWlwZXJpdG9waW52OkFudGVubmFNb2R1bGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgIH0KICAgIH0KfQ== +o-ran-smo-teiv-ran-oam-to-cloud 2023-10-24 urn:rdns:o-ran:o-ran-smo-teiv-ran-oam-to-cloud RAN_OAM_TO_CLOUD ["o-ran-smo-teiv-ran-oam", "o-ran-smo-teiv-ran-cloud"] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tb2FtLXRvLWNsb3VkIHsNCiAgICB5YW5nLXZlcnNpb24gMS4xOw0KICAgIG5hbWVzcGFjZSAidXJuOnJkbnM6Y29tOmVyaWNzc29uOnRvcGludm1vZGVsOmVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tb2FtLXRvLWNsb3VkIjsNCiAgICBwcmVmaXggcmFub2FtdG9jbG91ZGVyaXRvcGludjsNCg0KICAgIGltcG9ydCBlcmljc3Nvbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCB5ZXh0ZTsgfQ0KDQogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy10eXBlcyB7cHJlZml4IHR5cGVzZXJpdG9waW52OyB9DQoNCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCB5ZXh0ZXJpdG9waW52OyB9DQoNCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LXJhbi1vYW0ge3ByZWZpeCByYW5vYW1lcml0b3BpbnY7IH0NCg0KICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktcmFuLWNsb3VkIHtwcmVmaXggcmFuY2xvdWRlcml0b3BpbnY7IH0NCg0KICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOw0KICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOw0KICAgIGRlc2NyaXB0aW9uIA0KICAgICJSQU4gTyZNIHRvIENsb3VkIHRvcG9sb2d5IG1vZGVsLg0KDQogICAgQ29weXJpZ2h0IChjKSAyMDIzIEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KICAgIA0KICAgIFRoaXMgbW9kZWwgY29udGFpbnMgdGhlIFJBTiBPJk0gdG8gQ2xvdWQgdG9wb2xvZ3kgcmVsYXRpb25zIjsNCg0KICAgIHJldmlzaW9uICIyMDIzLTEwLTI0IiB7DQogICAgICAgIGRlc2NyaXB0aW9uDQogICAgICAgICJJbml0aWFsIHJldmlzaW9uLiI7DQogICAgICAgIHlleHRlOnZlcnNpb24gIjAiOw0KICAgICAgICB5ZXh0ZTpyZWxlYXNlICIxIjsNCiAgICAgICAgeWV4dGU6Y29ycmVjdGlvbiAiMSI7DQogICAgfQ0KDQogICAgeWV4dGVyaXRvcGludjpkb21haW4gUkFOX09BTV9UT19DTE9VRDsNCg0KICAgIHlleHRlcml0b3BpbnY6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX0RFUExPWUVEX0FTX0NMT1VETkFUSVZFU1lTVEVNIHsgIC8vIDAuLjEgdG8gMQ0KDQogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZiBkZXBsb3llZC1hcy1jbG91ZE5hdGl2ZVN5c3RlbSB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IGRlcGxveWVkIGFzIENsb3VkIE5hdGl2ZSBTeXN0ZW0uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YVNpZGUgcmFub2FtZXJpdG9waW52Ok1hbmFnZWRFbGVtZW50Ow0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICB9DQoNCiAgICAgICAgbGVhZiBkZXBsb3llZC1tYW5hZ2VkRWxlbWVudCB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQ2xvdWQgTmF0aXZlIFN5c3RlbSBkZXBsb3lzIE1hbmFnZWQgRWxlbWVudC4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjpiU2lkZSByYW5jbG91ZGVyaXRvcGludjpDbG91ZE5hdGl2ZVN5c3RlbTsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgICAgIG1hbmRhdG9yeSB0cnVlOw0KICAgICAgICB9DQogICAgfQ0KDQogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfUkVBTElTRURfQllfQ0xPVUROQVRJVkVBUFBMSUNBVElPTiB7IC8vIDEgdG8gMS4ubg0KDQogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IHJlYWxpc2VkLWJ5LWNsb3VkTmF0aXZlQXBwbGljYXRpb24gew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1hbmFnZWQgRWxlbWVudCByZWFsaXNlZCBieSBDbG91ZCANCiAgICAgICAgICAgICAgICAgICAgICAgIE5hdGl2ZSBBcHBsaWNhdGlvbi4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSByYW5vYW1lcml0b3BpbnY6TWFuYWdlZEVsZW1lbnQ7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgICAgICBtaW4tZWxlbWVudHMgMTsNCiAgICAgICAgfQ0KDQogICAgICAgIGxlYWYgcmVhbGlzZWQtbWFuYWdlZEVsZW1lbnQgew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIkNsb3VkIE5hdGl2ZSBBcHBsaWNhdGlvbiByZWFsaXNlcyANCiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmFnZWQgRWxlbWVudC4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjpiU2lkZSByYW5jbG91ZGVyaXRvcGludjpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOw0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7DQogICAgICAgIH0JDQogICAgfQ0KfQ== +o-ran-smo-teiv-ran-oam-to-logical 2023-10-24 urn:rdns:o-ran:o-ran-smo-teiv-ran-oam-to-logical RAN_OAM_TO_LOGICAL ["o-ran-smo-teiv-ran-oam", "o-ran-smo-teiv-ran-logical"] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tb2FtLXRvLWxvZ2ljYWwgew0KICAgIHlhbmctdmVyc2lvbiAxLjE7DQogICAgbmFtZXNwYWNlICJ1cm46cmRuczpjb206ZXJpY3Nzb246dG9waW52bW9kZWw6ZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LXJhbi1vYW0tdG8tbG9naWNhbCI7DQogICAgcHJlZml4IHJhbm9hbXRvbG9nZXJpdG9waW52Ow0KDQogICAgaW1wb3J0IGVyaWNzc29uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlOyB9DQoNCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggdHlwZXNlcml0b3BpbnY7IH0NCg0KICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlcml0b3BpbnY7IH0NCg0KICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktcmFuLW9hbSB7cHJlZml4IHJhbm9hbWVyaXRvcGludjsgfQ0KDQogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbCB7cHJlZml4IHJhbmxvZ2VyaXRvcGludjsgfQ0KDQoNCiAgICBvcmdhbml6YXRpb24gIkVyaWNzc29uIEFCIjsNCiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsNCiAgICBkZXNjcmlwdGlvbg0KICAgICJSQU4gTyZNIHRvIExvZ2ljYWwgdG9wb2xvZ3kgbW9kZWwuDQoNCiAgICBDb3B5cmlnaHQgKGMpIDIwMjMgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQogICAgDQogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIE8mTSB0byBMb2dpY2FsIHRvcG9sb2d5IHJlbGF0aW9ucyI7DQoNCiAgICByZXZpc2lvbiAiMjAyMy0xMC0yNCIgew0KICAgICAgICBkZXNjcmlwdGlvbg0KICAgICAgICAiSW5pdGlhbCByZXZpc2lvbi4iOw0KICAgICAgICB5ZXh0ZTp2ZXJzaW9uICIwIjsNCiAgICAgICAgeWV4dGU6cmVsZWFzZSAiMSI7DQogICAgICAgIHlleHRlOmNvcnJlY3Rpb24gIjEiOw0KICAgIH0NCg0KICAgIHlleHRlcml0b3BpbnY6ZG9tYWluIFJBTl9PQU1fVE9fTE9HSUNBTDsNCg0KICAgIHlleHRlcml0b3BpbnY6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX01BTkFHRVNfRU5PREVCRlVOQ1RJT04geyAgIC8vIDEgdG8gMC4ubg0KDQogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZW5vZGViRnVuY3Rpb24gew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1hbmFnZWQgRWxlbWVudCBtYW5hZ2VzIGVOb2RlQiBGdW5jdGlvbi4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSByYW5vYW1lcml0b3BpbnY6TWFuYWdlZEVsZW1lbnQ7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgIH0NCg0KICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgew0KICAgICAgICAgICAgZGVzY3JpcHRpb24gImVOb2RlQiBGdW5jdGlvbiBtYW5hZ2VkIGJ5IE1hbmFnZWQgRWxlbWVudC4iOw0KICAgICAgICAgICAgeWV4dGVyaXRvcGludjpiU2lkZSByYW5sb2dlcml0b3BpbnY6RU5vZGVCRnVuY3Rpb247DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsNCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIHlleHRlcml0b3BpbnY6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX01BTkFHRVNfR05CRFVGVU5DVElPTiB7ICAgIC8vIDEgdG8gMC4ubg0KDQogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZ25iZHVGdW5jdGlvbiB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IG1hbmFnZXMgZ05vZGVCLURVIEZ1bmN0aW9uLiI7DQogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmFTaWRlIHJhbm9hbWVyaXRvcGludjpNYW5hZ2VkRWxlbWVudDsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KDQogICAgICAgIGxlYWYgbWFuYWdlZC1ieS1tYW5hZ2VkRWxlbWVudCB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7DQogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmJTaWRlIHJhbmxvZ2VyaXRvcGludjpHTkJEVUZ1bmN0aW9uOw0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7DQogICAgICAgIH0NCiAgICB9DQogICAgDQogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVUNQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4NCg0KICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsNCiAgICAgICAga2V5IGlkOw0KDQogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1Y3BGdW5jdGlvbiB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IG1hbmFnZXMgZ05vZGVCLUNVLUNQIEZ1bmN0aW9uLiI7DQogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmFTaWRlIHJhbm9hbWVyaXRvcGludjpNYW5hZ2VkRWxlbWVudDsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgfQ0KDQogICAgICAgIGxlYWYgbWFuYWdlZC1ieS1tYW5hZ2VkRWxlbWVudCB7DQogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLUNQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7DQogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmJTaWRlIHJhbmxvZ2VyaXRvcGludjpHTkJDVUNQRnVuY3Rpb247DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsNCiAgICAgICAgfQkNCiAgICB9DQoNCiAgICB5ZXh0ZXJpdG9waW52OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBNQU5BR0VERUxFTUVOVF9NQU5BR0VTX0dOQkNVVVBGVU5DVElPTiB7ICAgIC8vIDEgdG8gMC4ubg0KDQogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZ25iY3V1cEZ1bmN0aW9uIHsNCiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtVVAgRnVuY3Rpb24uIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YVNpZGUgcmFub2FtZXJpdG9waW52Ok1hbmFnZWRFbGVtZW50Ow0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgICB9DQoNCiAgICAgICAgbGVhZiBtYW5hZ2VkLWJ5LW1hbmFnZWRFbGVtZW50IHsNCiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItQ1UtVVAgRnVuY3Rpb24gbWFuYWdlZCBieSBNYW5hZ2VkIEVsZW1lbnQuIjsNCiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgcmFubG9nZXJpdG9waW52OkdOQkNVVVBGdW5jdGlvbjsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICAgICAgIG1hbmRhdG9yeSB0cnVlOw0KICAgICAgICB9DQogICAgfQ0KfQ== +o-ran-smo-teiv-ran-cloud 2023-06-26 urn:rdns:o-ran:o-ran-smo-teiv-ran-cloud RAN_CLOUD [] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tY2xvdWQgewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOnJkbnM6Y29tOmVyaWNzc29uOnRvcGludm1vZGVsOmVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tY2xvdWQiOwogICAgcHJlZml4IHJhbmNsb3VkZXJpdG9waW52OwoKICAgIGltcG9ydCBlcmljc3Nvbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCB5ZXh0ZTsgfQoKICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCB0eXBlc2VyaXRvcGludjsgfQoKICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlcml0b3BpbnY7IH0KCiAgICBpbXBvcnQgaWV0Zi1nZW8tbG9jYXRpb24gewogICAgICAgIHByZWZpeCBnZW87CiAgICAgICAgcmVmZXJlbmNlICJSRkMgOTE3OTogQSBZQU5HIEdyb3VwaW5nIGZvciBHZW9ncmFwaGljIExvY2F0aW9ucyI7CiAgICB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiUkFOIENsb3VkIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIENMT1VEIGRvbWFpbiwgd2hpY2ggY29tcHJpc2VzIGNsb3VkIGluZnJhc3RydWNlIGFuZAogICAgZGVwbG95bWVudCBhc3BlY3RzIHRoYXQgY2FuIGJlIHVzZWQgaW4gdGhlIHRvcG9sb2d5IG1vZGVsLiI7CgogICAgcmV2aXNpb24gIjIwMjMtMDYtMjYiIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgeWV4dGU6dmVyc2lvbiAiMCI7CiAgICAgICAgeWV4dGU6cmVsZWFzZSAiMSI7CiAgICAgICAgeWV4dGU6Y29ycmVjdGlvbiAiMCI7CiAgICB9CgogICAgeWV4dGVyaXRvcGludjpkb21haW4gUkFOX0NMT1VEOwoKICAgIGxpc3QgQ2xvdWRTaXRlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyB0aGUgaW5mcmFzdHJ1Y3R1cmUgdGhhdAogICAgICAgICAgICAgICAgICAgIGhvc3RzIHRoZSBDbG91ZCBOYXRpdmUgQXBwbGljYXRpb25zLiI7CgogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIG5hbWUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5hbWUgb2YgQ2xvdWQgU2l0ZSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdXNlcyBnZW86Z2VvLWxvY2F0aW9uOwogICAgICAgIH0KICAgIH0KfQ== +o-ran-smo-teiv-ran-logical-to-equipment 2023-10-24 urn:rdns:o-ran:-ran-logical-to-equipment RAN_LOGICAL_TO_EQUIPMENT ["o-ran-smo-teiv-ran-logical", "o-ran-smo-teiv-ran-equipment"] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tZXF1aXBtZW50LXRvLWxvZ2ljYWwgewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOnJkbnM6Y29tOmVyaWNzc29uOnRvcGludm1vZGVsOmVyaWNzc29uLXRvcG9sb2d5YW5kaW52ZW50b3J5LXJhbi1lcXVpcG1lbnQtdG8tbG9naWNhbCI7CiAgICBwcmVmaXggcmFubG9ndG9lcXVpcGVyaXRvcGludjsKCiAgICBpbXBvcnQgZXJpY3Nzb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggeWV4dGU7IH0KCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggdHlwZXNlcml0b3BpbnY7IH0KCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCB5ZXh0ZXJpdG9waW52OyB9CgogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbCB7cHJlZml4IHJhbmxvZ2VyaXRvcGludjsgfQoKICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktcmFuLWVxdWlwbWVudCB7cHJlZml4IHJhbmVxdWlwZXJpdG9waW52OyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiUkFOIExvZ2ljYWwgdG8gRXF1aXBtZW50IHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSBSQU4gTG9naWNhbCB0byBFcXVpcG1lbnQgdG9wb2xvZ3kKICAgIGVudGl0aWVzIGFuZCByZWxhdGlvbnMuIjsKCiAgICByZXZpc2lvbiAiMjAyMy0xMi0xMiIgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICB5ZXh0ZTp2ZXJzaW9uICIwIjsKICAgICAgICB5ZXh0ZTpyZWxlYXNlICIyIjsKICAgICAgICB5ZXh0ZTpjb3JyZWN0aW9uICIwIjsKICAgIH0KCiAgICB5ZXh0ZXJpdG9waW52OmRvbWFpbiBFUVVJUE1FTlRfVE9fUkFOX0xPR0lDQUw7CgogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgQU5URU5OQU1PRFVMRV9TRVJWRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLm0KCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3Qgc2VydmljZWQtYW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHNlcnZpY2VkIGJ5IHRoaXMgQW50ZW5uYSBNb2R1bGUuIjsKICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSByYW5lcXVpcGVyaXRvcGludjpBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1hbnRlbm5hTW9kdWxlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIHNlcnZlcyB0aGlzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmJTaWRlIHJhbmxvZ2VyaXRvcGludjpBbnRlbm5hQ2FwYWJpbGl0eTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KfQo= +o-ran-smo-teiv-ran-logical 2023-11-03 urn:rdns:o-ran:o-ran-smo-teiv-ran-logical RAN_LOGICAL [] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tbG9naWNhbCB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46cmRuczpjb206ZXJpY3Nzb246dG9waW52bW9kZWw6ZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LXJhbi1sb2dpY2FsIjsKICAgIHByZWZpeCByYW5sb2dlcml0b3BpbnY7CgogICAgaW1wb3J0IGVyaWNzc29uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlOyB9CgogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy10eXBlcyB7cHJlZml4IHR5cGVzZXJpdG9waW52OyB9CgogICAgaW1wb3J0IGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1jb21tb24teWFuZy1leHRlbnNpb25zIHtwcmVmaXggeWV4dGVyaXRvcGludjsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiBMb2dpY2FsIHRvcG9sb2d5IG1vZGVsLgoKICAgIENvcHlyaWdodCAoYykgMjAyMyBFcmljc3NvbiBBQi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBUaGlzIG1vZGVsIGNvbnRhaW5zIHRoZSB0b3BvbG9neSBlbnRpdGllcyBhbmQgcmVsYXRpb25zIGluIHRoZQogICAgUkFOIExvZ2ljYWwgZG9tYWluLCB3aGljaCByZXByZXNlbnRzIHRoZSBmdW5jdGlvbmFsIGNhcGFiaWxpdHkKICAgIG9mIHRoZSBkZXBsb3llZCBSQU4gdGhhdCBhcmUgcmVsZXZhbnQgdG8gckFwcHMgdXNlIGNhc2VzLiI7CgogICAgcmV2aXNpb24gIjIwMjMtMTItMTIiIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgeWV4dGU6dmVyc2lvbiAiMCI7CiAgICAgICAgeWV4dGU6cmVsZWFzZSAiMyI7CiAgICAgICAgeWV4dGU6Y29ycmVjdGlvbiAiMCI7CiAgICB9CgogICAgeWV4dGVyaXRvcGludjpkb21haW4gUkFOX0xPR0lDQUw7CgogICAgZ3JvdXBpbmcgUExNTklkIHsKICAgICAgICBsZWFmIG1jYyB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTW9iaWxlIENvdW50cnkgQ29kZSAoTUNDKSBpZGVudGlmaWVzIHVuaXF1ZWx5CiAgICAgICAgICAgICAgICAgICAgICAgIGRvbWljaWxlIGNvdW50cnkgb2YgbW9iaWxlIHN1YnNjcmliZXIuCgogICAgICAgICAgICAgICAgICAgICAgICBNQ0MgY29uc2lzdHMgb2YgdGhyZWUgZGVjaW1hbCBkaWdpdHMuIFRoZSBmaXJzdCBkaWdpdAogICAgICAgICAgICAgICAgICAgICAgICBvZiBNQ0MgaWRlbnRpZmllcyBnZW9ncmFwaGljIHJlZ2lvbi4gKFZhbHVlcyAxIGFuZCA4CiAgICAgICAgICAgICAgICAgICAgICAgIGluIHRoZSBmaXJzdCBkaWdpdCBhcmUgbm90IGFsbG93ZWQuKQogICAgICAgICAgICAgICAgICAgICAgICBBcyBkZWZhdWx0IHZhbHVlLCB1c2UgMDAxLgogICAgICAgICAgICAgICAgICAgICAgICBBbGxvd2VkIHZhbHVlczogWzAyMzQ1Njc5XVswLTldWzAtOV0KCiAgICAgICAgICAgICAgICAgICAgICAgIFNwZWNpZmljYXRpb246IDNHUFAgVFMgMjguNTQxCiAgICAgICAgICAgICAgICAgICAgICAgIFZhbGlkIHZhbHVlczogXlswMjM0NTY3OV1bMC05XVswLTldJCI7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBtbmMgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIE1vYmlsZSBOZXR3b3JrIENvZGUgKE1OQykgaWRlbnRpZmllcyBob21lIFBMTU4KICAgICAgICAgICAgICAgICAgICAgICAgb2YgbW9iaWxlIHN1YnNjcmlwdGlvbi4KCiAgICAgICAgICAgICAgICAgICAgICAgIE1OQyBjb25zaXN0cyBvZiB0d28gb3IgdGhyZWUgZGVjaW1hbCBkaWdpdHMuIEZvcgogICAgICAgICAgICAgICAgICAgICAgICBleGFtcGxlLCBNTkMgb2YgMDAxIGlzIG5vdCBzYW1lIGFzIE1OQyBvZiAwMS4KICAgICAgICAgICAgICAgICAgICAgICAgQXMgZGVmYXVsdCB2YWx1ZSwgdXNlIDAxLgogICAgICAgICAgICAgICAgICAgICAgICBBbGxvd2VkIHZhbHVlczogWzAtOV1bMC05XVswLTldfFswLTldWzAtOV0KCiAgICAgICAgICAgICAgICAgICAgICAgIFNwZWNpZmljYXRpb246IDNHUFAgVFMgMjguNTQxCiAgICAgICAgICAgICAgICAgICAgICAgIFZhbGlkIHZhbHVlczogXigoWzAtOV1bMC05XVswLTldKXwoWzAtOV1bMC05XSkpJCI7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEVOb2RlQkZ1bmN0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gRXZvbHZlZCBOb2RlIEIgKGVOb2RlQikgaXMgdGhlIG9ubHkgbWFuZGF0b3J5CiAgICAgICAgICAgICAgICAgICAgbm9kZSBpbiB0aGUgcmFkaW8gYWNjZXNzIG5ldHdvcmsgKFJBTikgb2YgTG9uZy1UZXJtCiAgICAgICAgICAgICAgICAgICAgRXZvbHV0aW9uIChMVEUpLiBUaGUgZU5vZGVCIGlzIGEgY29tcGxleCBiYXNlCiAgICAgICAgICAgICAgICAgICAgc3RhdGlvbiB0aGF0IGhhbmRsZXMgcmFkaW8gY29tbXVuaWNhdGlvbnMKICAgICAgICAgICAgICAgICAgICBpbiB0aGUgY2VsbCBhbmQgY2FycmllcyBvdXQgcmFkaW8gcmVzb3VyY2UKICAgICAgICAgICAgICAgICAgICBtYW5hZ2VtZW50IGFuZCBoYW5kb3ZlciBkZWNpc2lvbnMuIFVubGlrZSAyLzNHCiAgICAgICAgICAgICAgICAgICAgd2lyZWxlc3MgUkFOLCB0aGVyZSBpcyBubyBjZW50cmFsaXplZCByYWRpbyBuZXR3b3JrCiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlciBpbiBMVEUuIEl0IGlzIHRoZSBoYXJkd2FyZSB0aGF0IGlzIGNvbm5lY3RlZAogICAgICAgICAgICAgICAgICAgIHRvIHRoZSBtb2JpbGUgcGhvbmUgbmV0d29yayB0aGF0IGNvbW11bmljYXRlcwogICAgICAgICAgICAgICAgICAgIGRpcmVjdGx5IHdpdGggbW9iaWxlIGhhbmRzZXRzIChVc2VyIEVxdWlwbWVudCksIGxpa2UgYSBiYXNlCiAgICAgICAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIgc3RhdGlvbiAoQlRTKSBpbiBHU00gbmV0d29ya3MuIFRoaXMgc2ltcGxpZmllcwogICAgICAgICAgICAgICAgICAgIHRoZSBhcmNoaXRlY3R1cmUgYW5kIGFsbG93cyBsb3dlciByZXNwb25zZSB0aW1lcy4iOwoKICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKCiAgICAgICAgICAgIGxlYWYgZU5CSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgSUQgdGhhdCBmb3JtcyBwYXJ0IG9mCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgQ2VsbCBHbG9iYWwgSWRlbnRpdHksIGFuZCBpcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxzbyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBub2RlIG92ZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBTMSBpbnRlcmZhY2UiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgICAgICBkZWZhdWx0IDExOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGR1cGxleFR5cGUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkluZGljYXRvciBvZiBFVXRyYW5DZWxsIHR5cGUsIEZERCBvciBUREQiOwogICAgICAgICAgICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgZW51bSB0ZGQgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAxOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVEREIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBlTm9kZUJQbG1uSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgRU5vZGVCIFB1YmxpYyBMYW5kIE1vYmlsZSBOZXR3b3JrCiAgICAgICAgICAgICAgICAoUExNTikgSUQgdGhhdCBmb3JtcyBwYXJ0IG9mIHRoZSBFTm9kZUIKICAgICAgICAgICAgICAgIEdsb2JhbCBJRCB1c2VkIHRvIGlkZW50aWZ5IHRoZSBub2RlIG92ZXIKICAgICAgICAgICAgICAgIHRoZSBTMSBpbnRlcmZhY2UuIE5vdGU6IFRoZSB2YWx1ZSAoTUNDPTAwMSwgTU5DPTAxKQogICAgICAgICAgICAgICAgaW5kaWNhdGVzIHRoYXQgdGhlIFBMTU4gaXMgbm90IGluaXRpYXRlZC4KICAgICAgICAgICAgICAgIFRoZSB2YWx1ZSBjYW4gbm90IGJlIHVzZWQgYXMgYSB2YWxpZCBQTE1OIElkZW50aXR5LiI7CgogICAgICAgICAgICAgICAgbGVhZiBtY2MgewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTUNDIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlZCBpbiB0aGUgcmFkaW8gbmV0d29yay4iOwogICAgICAgICAgICAgICAgICAgIHR5cGUgaW50MzIgewogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSAwLi45OTk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGVhZiBtbmMgewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTU5DIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlZCBpbiB0aGUgcmFkaW8gbmV0d29yay4iOwogICAgICAgICAgICAgICAgICAgIHR5cGUgaW50MzIgewogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSAwLi45OTk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGVhZiBtbmNMZW5ndGggewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgbGVuZ3RoIG9mIHRoZSBNTkMgcGFydCBvZiBhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUExNTiBpZGVudGl0eSB1c2VkIGluIHRoZSByYWRpbyBuZXR3b3JrLiI7CiAgICAgICAgICAgICAgICAgICAgdHlwZSBpbnQzMiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlIDIuLjM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6U09VUkNFX0lEUzsKICAgICAgICB9CiAgICB9CiAgICBsaXN0IEFudGVubmFDYXBhYmlsaXR5IHsKICAgICAgICBkZXNjcmlwdGlvbiAiVGhpcyBNTyBzZXJ2ZXMgYXMgYSBtYXBwaW5nIGJldHdlZW4gdGhlIGNlbGwKICAgICAgICAgICAgICAgICAgICBhbmQgdGhlIFJCUyBlcXVpcG1lbnQgdXNlZCB0byBwcm92aWRlIGNvdmVyYWdlCiAgICAgICAgICAgICAgICAgICAgaW4gYSBjZXJ0YWluIGdlb2dyYXBoaWNhbCBhcmVhLiBUaGUgTU8gYWxzbwogICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzIHRoZSBtYXhpbXVtIG91dHB1dCBwb3dlciBvZiB0aGUgc2VjdG9yLiI7CgogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmLWxpc3QgZVV0cmFuRnFCYW5kcyB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGlzdCBvZiBMVEUgZnJlcXVlbmN5IGJhbmRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0IGFzc29jaWF0ZWQgaGFyZHdhcmUgc3VwcG9ydHMiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYtbGlzdCBnZXJhbkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgR0VSQU4gZnJlcXVlbmN5IGJhbmRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCBhc3NvY2lhdGVkIGhhcmR3YXJlIHN1cHBvcnRzIjsKICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgblJGcUJhbmRzIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMaXN0IG9mIE5SIGZyZXF1ZW5jeSBiYW5kcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzb2NpYXRlZCBoYXJkd2FyZSBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQogICAgICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlNPVVJDRV9JRFM7CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTFRFU2VjdG9yQ2FycmllciB7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBMVEUgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZQogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMgZm9yIGRlZmluaW5nIHRoZSBsb2dpY2FsIGNoYXJhY3RlcmlzdGljcwogICAgICAgICAgICAgICAgICAgIG9mIGEgY2FycmllciAoY2VsbCkgaW4gYSBzZWN0b3IuIEEgc2VjdG9yIGlzIGEgY292ZXJhZ2UKICAgICAgICAgICAgICAgICAgICBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbiBoYXZpbmcKICAgICAgICAgICAgICAgICAgICBpdHMgb3duIGFudGVubmFzLCByYWRpbyBwb3J0cywgYW5kIGNvbnRyb2wgY2hhbm5lbHMuCiAgICAgICAgICAgICAgICAgICAgVGhlIGNvbmNlcHQgb2Ygc2VjdG9ycyB3YXMgZGV2ZWxvcGVkIHRvIGltcHJvdmUgY28tY2hhbm5lbAogICAgICAgICAgICAgICAgICAgIGludGVyZmVyZW5jZSBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zCiAgICAgICAgICAgICAgICAgICAgdXNlIHRocmVlIHNlY3RvciBjZWxscy4iOwoKICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBzZWN0b3JDYXJyaWVyVHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoZSBzZWN0b3IgY2FycmllcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxsZWQgYnkgTU8gU2VjdG9yQ2FycmllciBpcyBhIGRpZ2l0YWwgc2VjdG9yLiI7CiAgICAgICAgICAgICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICAgICAgICAgICAgICBlbnVtIG5vcm1hbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAwOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTm90IGEgZGlnaXRhbCBzZWN0b3IiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbnVtIGxlZnRfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAxOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVmdCBkaWdpdGFsIHNlY3RvciBmb3IgMkRTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSByaWdodF9kaWdpdGFsX3NlY3RvciB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSaWdodCBkaWdpdGFsIHNlY3RvciBmb3IgMkRTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBsZWZ0X2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDM7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMZWZ0IGRpZ2l0YWwgc2VjdG9yIGZvciAzRFMiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbnVtIHJpZ2h0X2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSaWdodCBkaWdpdGFsIHNlY3RvciBmb3IgM0RTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBtaWRkbGVfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA1OwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWlkZGxlIGRpZ2l0YWwgc2VjdG9yIGZvciAzRFMiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlNvdXJjZUlkZW50aWZpZXJzR3JwOwoKICAgICAgICB9CiAgICB9CgogICAgbGlzdCBOUlNlY3RvckNhcnJpZXIgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTlIgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzCiAgICAgICAgICAgICAgICAgICAgdGhlIGF0dHJpYnV0ZXMgZm9yIGRlZmluaW5nIHRoZSBsb2dpY2FsCiAgICAgICAgICAgICAgICAgICAgY2hhcmFjdGVyaXN0aWNzIG9mIGEgY2FycmllciAoY2VsbCkgaW4gYQogICAgICAgICAgICAgICAgICAgIHNlY3Rvci4gQSBzZWN0b3IgaXMgYSBjb3ZlcmFnZSBhcmVhIGFzc29jaWF0ZWQKICAgICAgICAgICAgICAgICAgICB3aXRoIGEgYmFzZSBzdGF0aW9uIGhhdmluZyBpdHMgb3duIGFudGVubmFzLAogICAgICAgICAgICAgICAgICAgIHJhZGlvIHBvcnRzLCBhbmQgY29udHJvbCBjaGFubmVscy4gVGhlIGNvbmNlcHQKICAgICAgICAgICAgICAgICAgICBvZiBzZWN0b3JzIHdhcyBkZXZlbG9wZWQgdG8gaW1wcm92ZSBjby1jaGFubmVsCiAgICAgICAgICAgICAgICAgICAgaW50ZXJmZXJlbmNlIGluIGNlbGx1bGFyIHN5c3RlbXMsIGFuZCBtb3N0IHdpcmVsZXNzCiAgICAgICAgICAgICAgICAgICAgc3lzdGVtcyB1c2UgdGhyZWUgc2VjdG9yIGNlbGxzLiI7CgogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGFyZmNuREwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIEFic29sdXRlIFJhZGlvIEZyZXF1ZW5jeSBDaGFubmVsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOdW1iZXIgKE5SLUFSRkNOKSBmb3IgZG93bmxpbmsiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgYXJmY25VTCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQWJzb2x1dGUgUmFkaW8gZnJlcXVlbmN5IENoYW5uZWwgTnVtYmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoTlItQVJGQ04pIGZvciB1cGxpbmsuIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGZyZXF1ZW5jeURMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSRiBSZWZlcmVuY2UgRnJlcXVlbmN5IG9mIGRvd25saW5rIGNoYW5uZWwiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZnJlcXVlbmN5VUwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlJGIFJlZmVyZW5jZSBGcmVxdWVuY3kgb2YgdXBsaW5rIGNoYW5uZWwiOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpTb3VyY2VJZGVudGlmaWVyc0dycDsKICAgICAgICB9CiAgICB9CgogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTFRFU0VDVE9SQ0FSUklFUl9VU0VTX0FOVEVOTkFDQVBBQklMSVRZIHsgLy8gMC4uMSB0byAwLi4xCgogICAgICAgIHVzZXMgdHlwZXNlcml0b3BpbnY6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZiB1c2VkLWFudGVubmFDYXBhYmlsaXR5IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxURSBTZWN0b3IgQ2FycmllciB1c2VzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmFTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgdXNlZC1ieS1sdGVTZWN0b3JDYXJyaWVyIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgQ3BhYmlsaXR5IHVzZWQgYnkgTFRFIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgQW50ZW5uYUNhcGFiaWxpdHk7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBwcm92aWRlZC1sdGVTZWN0b3JDYXJyaWVyIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImVOb2RlQiBGdW5jdGlvbiBwcm92aWRlcyBMVEUgU2VjdG9yIENhcnJpZXIuIjsKICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSBFTm9kZUJGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBwcm92aWRlZC1ieS1lbm9kZWJGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMVEUgU2VjdG9yIENhcnJpZXIgcHJvdmlkZWQgYnkgZU5vZGVCIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgTFRFU2VjdG9yQ2FycmllcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgeWV4dGVyaXRvcGludjpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTlJTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmIHVzZWQtYW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgU2VjdG9yIENhcnJpZXIgdXNlcyBBbnRlbm5hIENhcGFiaWxpdHkuIjsKICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSBOUlNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYtbGlzdCB1c2VkLWJ5LW5yU2VjdG9yQ2FycmllciB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIENhcGFiaWxpdHkgdXNlZCBieSBOUiBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICB5ZXh0ZXJpdG9waW52OmJTaWRlIEFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIHlleHRlcml0b3BpbnY6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIEFOVEVOTkFDQVBBQklMSVRZX1JFQUxJU0VEX0JZX0FOVEVOTkFDQVBBQklMSVRZIHsgLy8gU2FtZSBlbnRpdHkgKDAuLm4gdG8gMC4ubSkKCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcmVhbGlzZWQtYnktYW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIENhcGFiaWxpdHkgcmVhbGlzZWQgYnkgQW50ZW5uYSBDYXBhYmlsaXR5LiI7CiAgICAgICAgICAgICAgICAgICAgeWV4dGVyaXRvcGludjphU2lkZSByYW5sb2dlcml0b3BpbnY6QW50ZW5uYUNhcGFiaWxpdHk7CiAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgcmVhbGlzZWQtYW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHJlYWxpc2VzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgIHlleHRlcml0b3BpbnY6YlNpZGUgcmFubG9nZXJpdG9waW52OkFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICB9CiAgICB9Cn0= +o-ran-smo-teiv-ran-oam 2023-06-26 urn:rdns:o-ran:o-ran-smo-teiv-ran-oam RAN_OAM [] bW9kdWxlIGVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tb2FtIHsNCiAgICB5YW5nLXZlcnNpb24gMS4xOw0KICAgIG5hbWVzcGFjZSAidXJuOnJkbnM6Y29tOmVyaWNzc29uOnRvcGludm1vZGVsOmVyaWNzc29uLXByZS1yMS10b3BvbG9neWFuZGludmVudG9yeS1yYW4tb2FtIjsNCiAgICBwcmVmaXggcmFub2FtZXJpdG9waW52Ow0KDQogICAgaW1wb3J0IGVyaWNzc29uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlOyB9DQoNCiAgICBpbXBvcnQgZXJpY3Nzb24tcHJlLXIxLXRvcG9sb2d5YW5kaW52ZW50b3J5LWNvbW1vbi15YW5nLXR5cGVzIHtwcmVmaXggdHlwZXNlcml0b3BpbnY7IH0NCg0KICAgIGltcG9ydCBlcmljc3Nvbi1wcmUtcjEtdG9wb2xvZ3lhbmRpbnZlbnRvcnktY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IHlleHRlcml0b3BpbnY7IH0NCg0KICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOw0KICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOw0KICAgIGRlc2NyaXB0aW9uIA0KICAgICJSQU4gTyZNIHRvcG9sb2d5IG1vZGVsLg0KDQogICAgQ29weXJpZ2h0IChjKSAyMDIzIEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KICAgIA0KICAgIFRoaXMgbW9kZWwgY29udGFpbnMgdGhlIHRvcG9sb2d5IGVudGl0aWVzIGFuZCByZWxhdGlvbnMgaW4gdGhlIA0KICAgIFJBTiBPJk0gZG9tYWluLCB3aGljaCBhcmUgaW50ZW5kZWQgdG8gcmVwcmVzZW50IG1hbmFnZW1lbnQgc3lzdGVtcyANCiAgICBhbmQgbWFuYWdlbWVudCBpbnRlcmZhY2VzLiI7DQoNCiAgICByZXZpc2lvbiAiMjAyMy0wNi0yNiIgew0KICAgICAgICBkZXNjcmlwdGlvbg0KICAgICAgICAiSW5pdGlhbCByZXZpc2lvbi4iOw0KICAgICAgICB5ZXh0ZTp2ZXJzaW9uICIwIjsNCiAgICAgICAgeWV4dGU6cmVsZWFzZSAiMSI7DQogICAgICAgIHlleHRlOmNvcnJlY3Rpb24gIjAiOw0KICAgIH0NCg0KICAgIHlleHRlcml0b3BpbnY6ZG9tYWluIFJBTl9PQU07DQogICAgICAgIA0KICAgIGxpc3QgTWFuYWdlZEVsZW1lbnQgew0KICAgICAgICBkZXNjcmlwdGlvbiANCiAgICAgICAgIkEgTWFuYWdlZCBFbGVtZW50IChNRSkgaXMgYSBub2RlIGludG8gYSB0ZWxlY29tbXVuaWNhdGlvbiBuZXR3b3JrIA0KICAgICAgICBwcm92aWRpbmcgc3VwcG9ydCBhbmQvb3Igc2VydmljZSB0byBzdWJzY3JpYmVycy4gQW4gTUUgY29tbXVuaWNhdGVzIA0KICAgICAgICB3aXRoIGEgbWFuYWdlciBhcHBsaWNhdGlvbiAoZGlyZWN0bHkgb3IgaW5kaXJlY3RseSkgb3ZlciBvbmUgb3IgbW9yZSANCiAgICAgICAgaW50ZXJmYWNlcyBmb3IgdGhlIHB1cnBvc2Ugb2YgYmVpbmcgbW9uaXRvcmVkIGFuZC9vciBjb250cm9sbGVkLiI7DQoNCiAgICAgICAgdXNlcyB0eXBlc2VyaXRvcGludjpUb3BfR3JwX1R5cGU7DQogICAgICAgIGtleSBpZDsNCg0KICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7DQogICAgICAgICAgICBsZWFmIGZkbiB7DQogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoaXMgRnVsbCBEaXN0aW5ndWlzaGVkIE5hbWUgKEZETikgaWRlbnRpZmllcyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBpbnN0YW5jZSBvZiB0aGUgTWFuYWdlZEVsZW1lbnQgTU8uIEl0IGNvbnRhaW5zDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGZ1bGwgcGF0aCBmcm9tIHRoZSBTdWJuZXR3b3JrIHRvIHRoZSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYW5hZ2VkRWxlbWVudC4iOw0KICAgICAgICAgICAgICAgIHR5cGUgdHlwZXNlcml0b3BpbnY6XzNHUFBfRkROX1R5cGU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGNvbnRhaW5lciBjbUlkIHsNCiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzZXJpdG9waW52OkNNX0lEOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KfQ== \. -COPY ties_model.entity_info("name", "moduleReferenceName") FROM stdin; -ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt o-ran-smo-teiv-oam -ManagedElement o-ran-smo-teiv-oam -NodeCluster o-ran-smo-teiv-cloud -CloudNativeSystem o-ran-smo-teiv-cloud -CloudNativeApplication o-ran-smo-teiv-cloud -CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm o-ran-smo-teiv-cloud -CloudSite o-ran-smo-teiv-cloud -Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-cloud -CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-cloud -Namespace o-ran-smo-teiv-cloud -Sector o-ran-smo-teiv-ran -GNBCUUPFunction o-ran-smo-teiv-ran -ENodeBFunction o-ran-smo-teiv-ran -NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU o-ran-smo-teiv-ran -NRCellDU o-ran-smo-teiv-ran -LTESectorCarrier o-ran-smo-teiv-ran -GNBDUFunction o-ran-smo-teiv-ran -NRCellCU o-ran-smo-teiv-ran -GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran -AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-equipment -ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE o-ran-smo-teiv-equipment -EUtranCell o-ran-smo-teiv-ran -GNBCUCPFunction o-ran-smo-teiv-ran -NRSectorCarrier o-ran-smo-teiv-ran -AntennaCapability o-ran-smo-teiv-ran -TestEntityB o-ran-smo-teiv-ran -TestEntityA o-ran-smo-teiv-ran -Site o-ran-smo-teiv-equipment -AntennaModule o-ran-smo-teiv-equipment -PhysicalNetworkAppliance o-ran-smo-teiv-equipment +COPY ties_model.module_reference("name", "namespace", "domain", "includedModules", "revision", "content") FROM stdin; +_3gpp-common-yang-extensions urn:3gpp:sa5:_3gpp-common-yang-extensions \N [] 2019-06-23 bW9kdWxlIF8zZ3BwLWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgewogIHlhbmctdmVyc2lvbiAxLjE7CiAgbmFtZXNwYWNlIHVybjozZ3BwOnNhNTpfM2dwcC1jb21tb24teWFuZy1leHRlbnNpb25zIDsKICBwcmVmaXggeWV4dDNncHAgOwoKICBvcmdhbml6YXRpb24gIjNHUFAgU0E1IjsKICBkZXNjcmlwdGlvbiAiVGhlIG1vZHVsZSBkZWZpbmVzIFlBTkcgZXh0ZW5zaW9ucyBuZWVkZWQKICAgIDNHUFAgWUFORyBtb2RlbGluZy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTkgM0dQUC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCiAgICBFeHRlbnNpb25zIE1VU1QgYmUgZGVmaW5lZCB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGluIHRoZQogICAgZGVzY3JpcHRpb24gc3RhdGVtZW50OgogICAgICAgIC0gV2hhdCBpcyB0aGlzIHN0YXRlbWVudC4KICAgICAgICAtIE5ld2xpbmUsCiAgICAgICAgLSBUaGlzIHN0YXRlbWVudCBjYW4gYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlIHh4eCBzdGF0ZW1lbnRzIHdpdGgKICAgICAgICBjYXJkaW5hbGl0eSB4Li55LgogICAgICAgIC0gVGhpcyBzdGF0ZW1lbnQgY2FuIGhhdmUgdGhlIGZvbGxvd2luZyBzdWJzdGF0ZW1lbnRzIHdpdGgKICAgICAgICBjYXJkaW5hbGl0eSB4Li55LgogICAgICAgIC0gTmV3bGluZQogICAgICAgIC0gSXMgY2hhbmdpbmcgdGhpcyBzdGF0ZW1lbnQgYW4gZWRpdG9yaWFsLCBCQyhiYWNrd2FyZHMgY29tcGF0aWJsZSkKICAgICAgICBvciBOQkMobm9uLUJDKSBjaGFuZ2U/CiAgICAgICAgLSBOZXdsaW5lLgogICAgICAgIC0gVGhlIGFyZ3VtZW50IGl0cyBtZWFuaW5nIGFuZCB0eXBlLiBQcmVmZXJhYmx5IHVzZSBZQU5HIHR5cGVzIGFuZAogICAgICAgICAgY29uc3RyYWludHMgdG8gZGVmaW5lIHRoZSBhcmd1bWVudCdzIHR5cGUuCgogICAgQW55IGV4dGVuc2lvbiBzdGF0ZW1lbnQgY2FuIGJlIGFkZGVkIHdpdGggYQogICAgZGV2aWF0aW9uL2RldmlhdGUgYWRkIHN0YXRlbWVudC4gSW4gdGhpcyBjYXNlIHRoZSByZXN0cmljdGlvbiBhYm91dAogICAgdGhlIHBhcmVudCBzdGF0ZW1lbnQgb2YgdGhlIGV4dGVuc2lvbiBTSEFMTCBiZSBldmFsdWF0ZWQgYmFzZWQgb24gdGhlCiAgICB0YXJnZXQgb2YgdGhlIGRldmlhdGlvbiBzdGF0ZW1lbnQuCgogICAgU3VwcG9ydCBmb3IgdGhpcyBtb2R1bGUgZG9lcyBub3QgbWVhbiB0aGF0IGEgWUFORyBzZXJ2ZXIgaW1wbGVtZW50cwogICAgc3VwcG9ydCBmb3IgZWFjaCBvZiB0aGVzZSBleHRlbnNpb25zLgogICAgSW1wbGVtZW50ZXJzIG9mIGVhY2ggc3BlY2lmaWMgbW9kdWxlIHVzaW5nIGFuIGV4dGVuc2lvbnMgTVVTVCBjaGVjawogICAgaWYgdGhlIHNlcnZlciBpbXBsZW1lbnRzIHN1cHBvcnQgZm9yIHRoZSB1c2VkIGV4dGVuc2lvbi4KICAgIE5vdGU6IG1vZHVsZXMgdXNlIG1hbnkgZXh0ZW5zaW9ucyB3aGljaCBpbmRpdmlkdWFsCiAgICBpbXBsZW1lbnRhdGlvbnMgTUFZIG9yIE1BWSBOT1Qgc3VwcG9ydC4KICAgIElmIHN1cHBvcnQgZm9yIGFuIGV4dGVuc2lvbiBpcyBtaXNzaW5nIHRoZSBleHRlbnNpb24gc3RhdGVtZW50IG5lZWRzCiAgICBpbmRpdmlkdWFsIGhhbmRsaW5nIG9yIGl0IFNIT1VMRCBiZSByZW1vdmVkIGZyb20gdGhlIG1vZHVsZSB1c2luZwogICAgdGhlIGV4dGVuc2lvbiBlLmcuIHdpdGggYSBkZXZpYXRpb24uCiAgICAgICAgICAiOwoKICByZXZpc2lvbiAiMjAxOS0wNi0yMyIgewogICAgZGVzY3JpcHRpb24gIkluaXRpYWwgdmVyc2lvbiI7CiAgfQoKICBleHRlbnNpb24gaW5WYXJpYW50IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgICJJbmRpY2F0ZXMgdGhhdCB0aGUgdmFsdWUgZm9yIHRoZSBkYXRhIG5vZGUgY2FuIG9ubHkgYmUgc2V0IHdoZW4gaXRzCiAgICAgIHBhcmVudCBkYXRhIG5vZGUgaXMgYmVpbmcgY3JlYXRlZC4gVG8gY2hhbmdlIHRoZSB2YWx1ZSBhZnRlciB0aGF0LCB0aGUKICAgICAgcGFyZW50IGRhdGEgbm9kZSBtdXN0IGJlIGRlbGV0ZWQgYW5kIHJlY3JlYXRlZCB3aXRoIHRoZSBkYXRhIG5vZGUKICAgICAgaGF2aW5nIHRoZSBuZXcgdmFsdWUuCgogICAgICBJdCBpcyB1bm5lY2Vzc2FyeSB0byB1c2UgYW5kIE1VU1QgTk9UIGJlIHVzZWQgZm9yIGtleSBsZWFmcy4KCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgbGVhZiwgbGVhZi1saXN0LCBsaXN0CiAgICAgIHN0YXRlbWVudHMgdGhhdCBpcyBjb25maWc9dHJ1ZS4KICAgICAgWmVybyBvciBvbmUgaW5WYXJpYW50IHN0YXRlbWVudCBpcyBhbGxvd2VkIHBlciBwYXJlbnQgc3RhdGVtZW50LgogICAgICBOTyBzdWJzdGF0ZW1lbnRzIGFyZSBhbGxvd2VkLgoKICAgICAgQWRkaW5nIHRoaXMgc3RhdGVtZW50IGlzIGFuIE5CQyBjaGFuZ2UsIHJlbW92aW5nIGl0IGlzIEJDLiI7CiAgfQoKICBleHRlbnNpb24gaW5pdGlhbC12YWx1ZSB7CiAgICBkZXNjcmlwdGlvbiAiU3BlY2lmaWVzIGEgdmFsdWUgdGhhdCB0aGUgc3lzdGVtIHdpbGwgc2V0IGZvciBhIGxlYWYKICAgICAgbGVhZi1saXN0IGlmIGEgdmFsdWUgaXMgbm90IHNwZWNpZmllZCBmb3IgaXQgd2hlbiBpdHMgcGFyZW50IGxpc3QKICAgICAgb3IgY29udGFpbmVyIGlzIGNyZWF0ZWQuIFRoZSB2YWx1ZSBoYXMgbm8gZWZmZWN0IGluIGFueSBvdGhlcgogICAgICBtb2RpZmljYXRpb24gZS5nLiBjaGFuZ2luZyBvciByZW1vdmluZyB0aGUgdmFsdWUuCgogICAgICBUaGUgZGVzY3JpcHRpb24gc3RhdGVtZW50IG9mIHRoZSBwYXJlbnQgc3RhdGVtZW50IFNIT1VMRCBjb250YWluCiAgICAgIHRoZSBsYWJlbCAnSW5pdGlhbC12YWx1ZTogJyBmb2xsb3dlZCBieSB0aGUgdGV4dCBmcm9tIHRoZSBhcmd1bWVudC4KCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgbGVhZiBvciBsZWFmLWxpc3QuCiAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBOT1QgYmUgcHJlc2VudCBpZiB0aGUgbGVhZiBvciB0aGUgbGVhZi1saXN0CiAgICAgIGhhcyBhIGRlZmF1bHQgc3RhdGVtZW50IG9yIHRoZSB0eXBlIHVzZWQgZm9yIHRoZSBkYXRhIG5vZGUKICAgICAgaGFzIGEgZGVmYXVsdCB2YWx1ZS4KICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIE5PVCBiZSB1c2VkIGZvciBjb25maWc9ZmFsc2UgZGF0YSBvciBpbiBhbgogICAgICBhY3Rpb24sIHJwYyBvciBub3RpZmljYXRpb24uCiAgICAgIFplcm8gb3Igb25lIGluaXRpYWwtdmFsdWUgc3RhdGVtZW50cyBhcmUgYWxsb3dlZCBmb3IgYSBsZWFmIHBhcmVudAogICAgICBzdGF0ZW1lbnQuIFplcm8gb3IgbW9yZSBpbml0aWFsLXZhbHVlIHN0YXRlbWVudHMgYXJlIGFsbG93ZWQgZm9yIGEKICAgICAgbGVhZi1saXN0IHBhcmVudCBzdGF0ZW1lbnQuIElmIHRoZSBsZWFmLWxpc3QgaXMgb3JkZXJlZC1ieSB1c2VyLCB0aGUKICAgICAgaW5pdGlhbCB2YWx1ZXMgYXJlIHN0b3JlZCBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW4gdGhlIFlBTkcgZGVmaW5pdGlvbi4KICAgICAgTk8gc3Vic3RhdGVtZW50cyBhcmUgYWxsb3dlZC4KCiAgICAgIEFsd2F5cyBjb25zaWRlciB1c2luZyBhIFlBTkctZGVmYXVsdCBzdGF0ZW1lbnQgaW5zdGVhZC4KCiAgICAgIE1vZGlmaWNhdGlvbiBvZiB0aGUgaW5pdGlhbC12YWx1ZSBpcyBhIG5vbi1iYWNrd2FyZHMtY29tcGF0aWJsZSBjaGFuZ2UuCgogICAgICBUaGUgYXJndW1lbnQgc3BlY2lmaWVzIGEgc2luZ2xlIGluaXRpYWwgdmFsdWUgZm9yIGEgbGVhZiBvciBsZWFmLWxpc3QuCiAgICAgIFRoZSB2YWx1ZSBNVVNUIGJlIHBhcnQgb2YgdGhlIHZhbHVlc3BhY2Ugb2YgdGhlIGxlYWYvbGVhZi1saXN0LgogICAgICBJdCBmb2xsb3dzIHRoZSBzYW1lIHJ1bGVzIGFzIHRoZSBhcmd1bWVudCBvZiB0aGUgZGVmYXVsdCBzdGF0ZW1lbnQuIjsKCiAgICBhcmd1bWVudCAiaW5pdGlhbC12YWx1ZSI7CiAgfQp9Cg== +_3gpp-common-yang-types urn:3gpp:sa5:_3gpp-common-yang-types \N [] 2023-11-06 bW9kdWxlIF8zZ3BwLWNvbW1vbi15YW5nLXR5cGVzIHsKICB5YW5nLXZlcnNpb24gMS4xOwogIG5hbWVzcGFjZSAidXJuOjNncHA6c2E1Ol8zZ3BwLWNvbW1vbi15YW5nLXR5cGVzIjsKICBwcmVmaXggInR5cGVzM2dwcCI7CgogIGltcG9ydCBpZXRmLWluZXQtdHlwZXMgeyBwcmVmaXggaW5ldDsgfQogIGltcG9ydCBpZXRmLXlhbmctdHlwZXMgeyBwcmVmaXggeWFuZzsgfQogIGltcG9ydCBfM2dwcC1jb21tb24teWFuZy1leHRlbnNpb25zIHsgcHJlZml4IHlleHQzZ3BwOyB9CgogIG9yZ2FuaXphdGlvbiAiM0dQUCBTQTUiOwogIGNvbnRhY3QgImh0dHBzOi8vd3d3LjNncHAub3JnL0R5bmFSZXBvcnQvVFNHLVdHLS1TNS0tb2ZmaWNpYWxzLmh0bT9JdGVtaWQ9NDY0IjsKICBkZXNjcmlwdGlvbiAiVGhlIG1vZGVsIGRlZmluZXMgYSBZQU5HIG1hcHBpbmcgb2YgdGhlIHRvcCBsZXZlbAogICAgaW5mb3JtYXRpb24gY2xhc3NlcyB1c2VkIGZvciBtYW5hZ2VtZW50IG9mIDVHIG5ldHdvcmtzIGFuZAogICAgbmV0d29yayBzbGljaW5nLgogICAgQ29weXJpZ2h0IDIwMjMsIDNHUFAgT3JnYW5pemF0aW9uYWwgUGFydG5lcnMgKEFSSUIsIEFUSVMsIENDU0EsIEVUU0ksIFRTRFNJLAogICAgVFRBLCBUVEMpLiBBbGwgcmlnaHRzIHJlc2VydmVkLiI7CiAgcmVmZXJlbmNlICIzR1BQIFRTIDI4LjYyMyI7CgogIHJldmlzaW9uIDIwMjMtMTEtMDYgeyByZWZlcmVuY2UgQ1ItMDMwNTsgfQogIHJldmlzaW9uIDIwMjMtMDktMTggeyByZWZlcmVuY2UgQ1ItMDI3MSA7IH0KICByZXZpc2lvbiAyMDIzLTA4LTA5IHsgcmVmZXJlbmNlIENSLTAyNjY7IH0KICByZXZpc2lvbiAyMDIzLTA1LTEwIHsgcmVmZXJlbmNlIENSLTAyNTA7IH0KICByZXZpc2lvbiAyMDIzLTAyLTE0IHsgcmVmZXJlbmNlIENSLTAyMzQ7IH0KICByZXZpc2lvbiAyMDIyLTExLTA0IHsgcmVmZXJlbmNlICJDUi0wMTk0IjsgfQogIHJldmlzaW9uIDIwMjItMTAtMjQgeyByZWZlcmVuY2UgQ1ItMDE5NjsgIH0KICByZXZpc2lvbiAyMDIyLTA3LTI2IHsgcmVmZXJlbmNlICJDUi0wMTgwIiA7IH0KICByZXZpc2lvbiAyMDIyLTAyLTA5IHsgcmVmZXJlbmNlICJDUi0wMTQ0IjsgfQogIHJldmlzaW9uIDIwMjEtMTEtMDEgeyByZWZlcmVuY2UgIkNSLTAxNDEiOyB9CgogIHJldmlzaW9uIDIwMjEtMDktMzAgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIExvbmdpdHVkZSwgTGF0aXR1ZGUsIFRlbnRoT2ZEZWdyZWVzLCBPbk9mZi4iOwogICAgcmVmZXJlbmNlICJDUi0wMTM4IjsKICB9CgogIHJldmlzaW9uIDIwMjAtMTEtMDYgewogICAgZGVzY3JpcHRpb24gIlJlbW92ZWQgaW5jb3JyZWN0IFMtTlNTQUkgZGVmaW5pdGlvbnMuIjsKICAgIHJlZmVyZW5jZSAiQ1ItMDExOCI7CiAgfQoKICByZXZpc2lvbiAyMDIwLTAzLTEwIHsKICAgIGRlc2NyaXB0aW9uICJSZW1vdmVkIGZhdWx0eSB3aGVuIHN0YXRlbWVudHMuIjsKICAgIHJlZmVyZW5jZSAiU1AtMjAwMjI5IjsKICB9CgogIHJldmlzaW9uIDIwMTktMTAtMjUgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIE1hbmFnZWRORlByb2ZpbGUuIjsKICAgIHJlZmVyZW5jZSAiUzUtMTk0NDU3IjsKICB9CgogIHJldmlzaW9uIDIwMTktMTAtMTYgewogICAgZGVzY3JpcHRpb24gIkFkZGVkIFNBUCBhbmQgdXNhZ2VTdGF0ZS4iOwogICAgcmVmZXJlbmNlICJTNS0xOTM1MTgiOwogIH0KCiAgcmV2aXNpb24gMjAxOS0wNi0yMyB7CiAgICByZWZlcmVuY2UgICJJbml0aWFsIHZlcnNpb24uIjsKICB9CgogIHR5cGVkZWYgRW5hYmxlZERpc2FibGVkIHsKICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICBlbnVtIERJU0FCTEVEIDsKICAgICAgZW51bSBFTkFCTEVEIDsKICAgIH0KICB9CgogIGdyb3VwaW5nIG5hbWVWYWx1ZVBhaXIgewogICAgbGVhZiBuYW1lIHsgdHlwZSBzdHJpbmc7IH0KICAgIGxlYWYgdmFsdWUgeyB0eXBlIHN0cmluZzsgfQogIH0KCiAgZ3JvdXBpbmcgUHJvY2Vzc01vbml0b3JHcnAgewogICAgZGVzY3JpcHRpb24gIlByb3ZpZGVzIGF0dHJpYnV0ZXMgdG8gbW9uaXRvciB0aGUgcHJvZ3Jlc3Mgb2YgcHJvY2Vzc2VzCiAgICAgIHdpdGggc3BlY2lmaWMgcHVycG9zZSBhbmQgbGltaXRlZCBsaWZldGltZSBydW5uaW5nIG9uIE1uUyBwcm9kdWNlcnMuCiAgICAgIEl0IG1heSBiZSB1c2VkIGFzIGRhdGEgdHlwZSBmb3IgZGVkaWNhdGVkIHByb2dyZXNzIG1vbml0b3IgYXR0cmlidXRlcwogICAgICB3aGVuIHNwZWNpZnlpbmcgdGhlIG1hbmFnZW1lbnQgcmVwcmVzZW50YXRpb24gb2YgdGhlc2UgcHJvY2Vzc2VzLgogICAgICBUaGUgYXR0cmlidXRlcyBpbiB0aGlzIGNsYXVzZSBhcmUgZGVmaW5lZCBpbiBhIGdlbmVyaWMgd2F5LgogICAgICBGb3Igc29tZSBhdHRyaWJ1dGVzIHNwZWNpYWxpc2F0aW9ucyBtYXkgYmUgcHJvdmlkZWQgd2hlbiBzcGVjaWZ5aW5nIGEKICAgICAgY29uY3JldGUgcHJvY2VzcyByZXByZXNlbnRhdGlvbi4KCiAgICAgIElmIGEgbWFuYWdlbWVudCBvcGVyYXRpb24gb24gc29tZSBJT0NzIHRyaWdnZXJzIGFuIGFzc29jaWF0ZWQKICAgICAgYXN5bmNocm9ub3VzIHByb2Nlc3MgKHdob3NlIHByb2dyZXNzIHNoYWxsIGJlIG1vbml0b3JlZCksIHRoaXMgc2hvdWxkCiAgICAgIGFsc28gcmVzdWx0IGluIGNyZWF0aW5nIGFuIGF0dHJpYnV0ZSBuYW1lZCAncHJvY2Vzc01vbml0b3InIChvZiB0eXBlCiAgICAgICdQcm9jZXNzTW9uaXRvcicpIGluIHRoZXNlIElPQyhzKS4gVGhlIHByb2Nlc3NNb25pdG9yIGF0dHJpYnV0ZSBtYXkgYmUKICAgICAgYWNjb21wYW5pZWQgYnkgdXNlLWNhc2Ugc3BlY2lmaWMgYWRkaXRpb25hbCBkYXRhIGl0ZW1zLgoKICAgICAgVGhlIHByb2dyZXNzIG9mIHRoZSBwcm9jZXNzIGlzIGRlc2NyaWJlZCBieSB0aGUgJ3N0YXR1cycgYW5kCiAgICAgICdwcm9ncmVzc1BlcmNlbnRhZ2UnIGF0dHJpYnV0ZXMuIEFkZGl0aW9uYWwgdGV4dHVhbCBxdWFsaWZpY2F0aW9ucyBmb3IKICAgICAgdGhlICdzdGF0dXMnIGF0dHJpYnV0ZSBtYXkgYmUgcHJvdmlkZWQgYnkgdGhlICdwcm9ncmVzc1N0YXRlSW5mbycgYW5kCiAgICAgICdyZXN1bHRTdGF0ZUluZm8nIGF0dHJpYnV0ZXMuCgogICAgICBXaGVuIHRoZSBwcm9jZXNzIGlzIGluc3RhbnRpYXRlZCwgdGhlICdzdGF0dXMnIGlzIHNldCB0byAnTk9UX1JVTk5JTkcnCiAgICAgIGFuZCB0aGUgJ3Byb2dyZXNzUGVyY2VudGFnZScgdG8gJzAnLiBUaGUgTW5TIHByb2R1Y2VyIGRlY2lkZXMgd2hlbiB0bwogICAgICBzdGFydCBleGVjdXRpbmcgdGhlIHByb2Nlc3MgYW5kIHRvIHRyYW5zaXRpb24gaW50byB0aGUgJ1JVTk5JTkcnIHN0YXRlLgogICAgICBUaGlzIHRpbWUgaXMgY2FwdHVyZWQgaW4gdGhlICdzdGFydFRpbWUnIGF0dHJpYnV0ZS4gQWx0ZXJuYXRpdmVseSwgdGhlCiAgICAgIHByb2Nlc3MgbWF5IHN0YXJ0IHRvIGV4ZWN1dGUgZGlyZWN0bHkgdXBvbiBpdHMgaW5zdGFudGlhdGlvbi4gT25lCiAgICAgIGFsdGVybmF0aXZlIG11c3QgYmUgc2VsZWN0ZWQgd2hlbiB1c2luZyB0aGlzIGRhdGEgdHlwZS4KCiAgICAgIER1cmluZyB0aGUgJ1JVTk5JTkcnIHN0YXRlIHRoZSAncHJvZ3Jlc3NQZXJjZW50YWdlJyBhdHRyaWJ1dGUgbWF5IGJlCiAgICAgIHJlcGVhdGVkbHkgdXBkYXRlZC4gVGhlIGV4YWN0IHNlbWFudGljIG9mIHRoaXMgYXR0cmlidXRlIGlzIHN1YmplY3QgdG8KICAgICAgZnVydGhlciBzcGVjaWFsaXNhdGlvbi4gVGhlICdwcm9ncmVzc0luZm8nIGF0dHJpYnV0ZSBtYXkgYmUgdXNlZCB0bwogICAgICBwcm92aWRlIGFkZGl0aW9uYWwgdGV4dHVhbCBpbmZvcm1hdGlvbiBpbiB0aGUgJ05PVF9SVU5OSU5HJywgJ0NBTkNFTExJTkcnCiAgICAgIGFuZCAnUlVOTklORycgc3RhdGVzLiBGdXJ0aGVyIHNwZWNpYWxpc2F0aW9uIG9mCiAgICAgICdwcm9ncmVzc1N0YXRlSW5mbycgbWF5IGJlIHByb3ZpZGVkIHdoZXJlIHRoaXMgZGF0YSB0eXBlIGlzCiAgICAgIHVzZWQuCgogICAgICBVcG9uIHN1Y2Nlc3NmdWwgY29tcGxldGlvbiBvZiB0aGUgcHJvY2VzcywgdGhlICdzdGF0dXMnIGF0dHJpYnV0ZSBpcyBzZXQKICAgICAgdG8gJ0ZJTklTSEVEJywgdGhlICdwcm9ncmVzc1BlcmNlbnRhZ2UnIHRvIDEwMCUuIFRoZSB0aW1lIGlzIGNhcHR1cmVkIGluCiAgICAgIHRoZSAnZW5kVGltZScgYXR0cmlidXRlLiBBZGRpdGlvbmFsIHRleHR1YWwgaW5mb3JtYXRpb24gbWF5IGJlIHByb3ZpZGVkCiAgICAgIGluIHRoZSAncmVzdWx0U3RhdGVJbmZvJyBhdHRyaWJ1dGUuIFRoZSB0eXBlIG9mCiAgICAgICdyZXN1bHRTdGF0ZUluZm8nIGluIHRoaXMgZGF0YSB0eXBlIGRlZmluaXRpb24gaXMgJ1N0cmluZycuCiAgICAgIEZ1cnRoZXIgc3BlY2lhbGlzYXRpb24gb2YgJ3Jlc3VsdFN0YXRlSW5mbycgbWF5IGJlIHByb3ZpZGVkCiAgICAgIHdoZXJlIHRoaXMgZGF0YSB0eXBlIGlzIHVzZWQuCgogICAgICBJbiBjYXNlIHRoZSBwcm9jZXNzIGZhaWxzIHRvIGNvbXBsZXRlIHN1Y2Nlc3NmdWxseSwgdGhlICdzdGF0dXMnCiAgICAgIGF0dHJpYnV0ZSBpcyBzZXQgdG8gJ0ZBSUxFRCcgb3IgJ1BBUlRJQUxMWV9GQUlMRUQnLCB0aGUgY3VycmVudCB2YWx1ZSBvZgogICAgICAncHJvZ3Jlc3NQZXJjZW50YWdlJyBpcyBmcm96ZW4sIGFuZCB0aGUgdGltZSBjYXB0dXJlZCBpbiAnZW5kVGltZScuIFRoZQogICAgICAncmVzdWx0U3RhdGVJbmZvJyBzcGVjaWZpZXMgdGhlIHJlYXNvbiBmb3IgdGhlIGZhaWx1cmUuCiAgICAgIFNwZWNpZmljIGZhaWx1cmUgcmVhc29ucyBtYXkgYmUgc3BlY2lmaWVkIHdoZXJlIHRoZSBkYXRhIHR5cGUgZGVmaW5lZCBpbgogICAgICB0aGlzIGNsYXVzZSBpcyB1c2VkLiBUaGUgZXhhY3Qgc2VtYW50aWMgb2YgZmFpbHVyZSBtYXkgYmUgc3ViamVjdCBmb3IKICAgICAgZnVydGhlciBzcGVjaWFsaXNhdGlvbiBhcyB3ZWxsLgoKICAgICAgSW4gY2FzZSB0aGUgcHJvY2VzcyBpcyBjYW5jZWxsZWQsIHRoZSAnc3RhdHVzJyBhdHRyaWJ1dGUgaXMgZmlyc3Qgc2V0IHRvCiAgICAgICdDQU5DRUxMSU5HJyBhbmQgd2hlbiB0aGUgcHJvY2VzcyBpcyByZWFsbHkgY2FuY2VsbGVkIHRoZW4gdG8gJ0NBTkNFTExFRCcuCiAgICAgIFRoZSB0cmFuc2l0aW9uIHRvICdDQU5DRUxMRUQnIGlzIGNhcHR1cmVkIGluIHRoZSAnZW5kVGltZScgYXR0cmlidXRlLgogICAgICBUaGUgdmFsdWUgb2YgJ3Byb2dyZXNzUGVyY2VudGFnZScgaXMgZnJvemVuLiBBZGRpdGlvbmFsIHRleHR1YWwKICAgICAgaW5mb3JtYXRpb24gbWF5IGJlIHByb3ZpZGVkIGluIHRoZSAncmVzdWx0U3RhdGVJbmZvJyBhdHRyaWJ1dGUuCgogICAgICBUaGUgJ3Jlc3VsdFN0YXRlSW5mbycgYXR0cmlidXRlIGlzIHByb3ZpZGVkIG9ubHkgZm9yIGFkZGl0aW9uYWwgdGV4dHVhbAogICAgICBxdWFsaWZpY2F0aW9uIG9mIHRoZSBzdGF0ZXMgJ0ZJTklTSEVEJywgJ0ZBSUxFRCcsICdQQVJUSUFMTFlfRkFJTEVEJyBvcgogICAgICAnQ0FOQ0VMTEVEJy4gSXQgc2hhbGwgbm90IGJlIHVzZWQgZm9yIG1ha2luZyB0aGUgb3V0Y29tZSwgdGhhdCB0aGUKICAgICAgcHJvY2VzcyBtYXkgcHJvZHVjZSBpbiBjYXNlIG9mIHN1Y2Nlc3MsIGF2YWlsYWJsZS4KCiAgICAgIFRoZSBwcm9jZXNzIG1heSBoYXZlIHRvIGJlIGNvbXBsZXRlZCB3aXRoaW4gYSBjZXJ0YWluIHRpbWUgYWZ0ZXIgaXRzCiAgICAgIGNyZWF0aW9uLCBmb3IgZXhhbXBsZSBiZWNhdXNlIHJlcXVpcmVkIGRhdGEgbWF5IG5vdCBiZSBhdmFpbGFibGUgYW55CiAgICAgIG1vcmUgYWZ0ZXIgYSBjZXJ0YWluIHRpbWUsIG9yIHRoZSBwcm9jZXNzIG91dGNvbWUgaXMgbmVlZGVkIHVudGlsIGEKICAgICAgY2VydGFpbiB0aW1lIGFuZCB3aGVuIG5vdCBwcm92aWRlZCBieSB0aGlzIHRpbWUgaXMgbm90IG5lZWRlZCBhbnkgbW9yZS4KICAgICAgVGhlIHRpbWUgdW50aWwgdGhlIE1uUyBwcm9kdWNlciBhdXRvbWF0aWNhbGx5IGNhbmNlbHMgdGhlIHByb2Nlc3MgaXMKICAgICAgaW5kaWNhdGVkIGJ5IHRoZSAndGltZXInIGF0dHJpYnV0ZS4iOwoKICAgIGxlYWYgaWQgewogICAgICB0eXBlIHN0cmluZzsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIGRlc2NyaXB0aW9uICJJZCBvZiB0aGUgcHJvY2Vzcy4gSXQgaXMgdW5pcXVlIHdpdGhpbiBhIHNpbmdsZQogICAgICAgIG11bHRpdmFsdWUgYXR0cmlidXRlIG9mIHR5cGUgUHJvY2Vzc01vbml0b3IuIjsKICAgIH0KCiAgICBsZWFmIHN0YXR1cyB7CiAgICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICAgIGVudW0gTk9UX1NUQVJURUQgOwogICAgICAgIGVudW0gUlVOTklORyA7CiAgICAgICAgZW51bSBDQU5DRUxMSU5HIDsKICAgICAgICBlbnVtIEZJTklTSEVEIDsKICAgICAgICBlbnVtIEZBSUxFRCA7CiAgICAgICAgZW51bSBQQVJUSUFMTFlfRkFJTEVEIDsKICAgICAgICBlbnVtIENBTkNFTExFRCA7CiAgICAgIH0KICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZWZhdWx0ICBSVU5OSU5HOwogICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyB0aGUgc3RhdHVzIG9mIHRoZSBhc3NvY2lhdGVkIHByb2Nlc3MsCiAgICAgICAgd2hldGhlciBpdCBmYWlscywgc3VjY2VlZHMgZXRjLgogICAgICAgIEl0IGRvZXMgbm90IHJlcHJlc2VudCB0aGUgcmV0dXJuZWQgdmFsdWVzIG9mIGEgc3VjY2Vzc2Z1bGx5IGZpbmlzaGVkCiAgICAgICAgcHJvY2Vzcy4gIjsKICAgIH0KCiAgICBsZWFmIHByb2dyZXNzUGVyY2VudGFnZSB7CiAgICAgIHR5cGUgdWludDggewogICAgICAgIHJhbmdlIDAuLjEwMDsKICAgICAgfQogICAgICBjb25maWcgZmFsc2U7CiAgICAgIGRlc2NyaXB0aW9uICJQcm9ncmVzcyBvZiB0aGUgYXNzb2NpYXRlZCBwcm9jZXNzIGFzIHBlcmNlbnRhZ2UiOwogICAgfQoKICAgIGxlYWYtbGlzdCBwcm9ncmVzc1N0YXRlSW5mbyB7CiAgICAgIHR5cGUgc3RyaW5nOwogICAgICBjb25maWcgZmFsc2U7CiAgICAgIGRlc2NyaXB0aW9uICJBZGRpdGlvbmFsIHRleHR1YWwgcXVhbGlmaWNhdGlvbiBvZiB0aGUgc3RhdGVzCiAgICAgICAgJ05PVF9TVEFSVEVEJywgJ0NBTkNFTExJTkcnIGFuZCAnUlVOTklORycuCgogICAgICAgIEZvciBzcGVjaWZpYyBwcm9jZXNzZXMsIHNwZWNpZmljIHdlbGwtZGVmaW5lZCBzdHJpbmdzIChlLmcuIHN0cmluZwogICAgICAgIHBhdHRlcm5zIG9yIGVudW1zKSBtYXkgYmUgZGVmaW5lZCBhcyBhIHNwZWNpYWxpc2F0aW9uLiI7CiAgICB9CgogICAgbGVhZiByZXN1bHRTdGF0ZUluZm8gewogICAgICB0eXBlIHN0cmluZzsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZXNjcmlwdGlvbiAiQWRkaXRpb25hbCB0ZXh0dWFsIHF1YWxpZmljYXRpb24gb2YgdGhlIHN0YXRlcwogICAgICAgICdGSU5JU0hFRCcsICdGQUlMRUQnLCAnUEFSVElBTExZX0ZBSUxFRCBhbmQgJ0NBTkNFTExFRCcuCiAgICAgICAgRm9yIGV4YW1wbGUsIGluIHRoZSAnRkFJTEVEJyBvciAnUEFSVElBTExZX0ZBSUxFRCcgc3RhdGUgdGhpcwogICAgICAgIGF0dHJpYnV0ZSBtYXkgYmUgdXNlZCB0byBwcm92aWRlIGVycm9yIHJlYXNvbnMuCgogICAgICAgIFRoaXMgYXR0cmlidXRlIHNoYWxsIG5vdCBiZSB1c2VkIHRvIG1ha2UgdGhlIG91dGNvbWUgb2YgdGhlIHByb2Nlc3MKICAgICAgICBhdmFpbGFibGUgZm9yIHJldHJpZXZhbCwgaWYgYW55LiBGb3IgdGhpcyBwdXJwb3NlLCBkZWRpY2F0ZWQKICAgICAgICBhdHRyaWJ1dGVzIHNoYWxsIGJlIHNwZWNpZmllZCB3aGVuIHNwZWNpZnlpbmcgdGhlIHJlcHJlc2VudGF0aW9uIG9mCiAgICAgICAgYSBzcGVjaWZpYyBwcm9jZXNzLgoKICAgICAgICBGb3Igc3BlY2lmaWMgcHJvY2Vzc2VzLCBzcGVjaWZpYyB3ZWxsLWRlZmluZWQgc3RyaW5ncyAoZS5nLiBzdHJpbmcKICAgICAgICBwYXR0ZXJucyBvciBlbnVtcykgbWF5IGJlIGRlZmluZWQgYXMgYSBzcGVjaWFsaXNhdGlvbi4iOwogICAgfQoKICAgIGxlYWYgc3RhcnRUaW1lIHsKICAgICAgdHlwZSB5YW5nOmRhdGUtYW5kLXRpbWU7CiAgICAgIGNvbmZpZyBmYWxzZTsKICAgICAgZGVzY3JpcHRpb24gIlN0YXJ0IHRpbWUgb2YgdGhlIGFzc29jaWF0ZWQgcHJvY2VzcywgaS5lLiB0aGUgdGltZSB3aGVuIHRoZQogICAgICAgIHN0YXR1cyBjaGFuZ2VkIGZyb20gJ05PVF9TVEFSVEVEJyB0byAnUlVOTklORycuIjsKICAgIH0KCiAgICBsZWFmIGVuZFRpbWUgewogICAgICB0eXBlIHlhbmc6ZGF0ZS1hbmQtdGltZTsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBkZXNjcmlwdGlvbiAiRGF0ZSBhbmQgdGltZSB3aGVuIHN0YXR1cyBjaGFuZ2VkIHRvICdTVUNDRVNTJywgJ0NBTkNFTExFRCcsCiAgICAgICAgJ0ZBSUxFRCcgb3IgJ1BBUlRJQUxMWV9GQUlMRUQnLgoKICAgICAgICBJZiB0aGUgdGltZSBpcyBpbiB0aGUgZnV0dXJlLCBpdCBpcyB0aGUgZXN0aW1hdGVkIHRpbWUKICAgICAgICB0aGUgcHJvY2VzcyB3aWxsIGVuZC4iOwogICAgfQoKICAgIGxlYWYgdGltZXIgewogICAgICB0eXBlIHVpbnQzMjsKICAgICAgdW5pdHMgbWludXRlczsKICAgICAgZGVzY3JpcHRpb24gIlRpbWUgdW50aWwgdGhlIGFzc29jaWF0ZWQgcHJvY2VzcyBpcyBhdXRvbWF0aWNhbGx5IGNhbmNlbGxlZC4KICAgICAgICBJZiBzZXQsIHRoZSBzeXN0ZW0gZGVjcmVhc2VzIHRoZSB0aW1lciB3aXRoIHRpbWUuIFdoZW4gaXQgcmVhY2hlcyB6ZXJvCiAgICAgICAgdGhlIGNhbmNlbGxhdGlvbiBvZiB0aGUgYXNzb2NpYXRlZCBwcm9jZXNzIGlzIGluaXRpYXRlZCBieSB0aGUKICAgICAgICBNblNfUHJvZHVjZXIuCiAgICAgICAgSWYgbm90IHNldCwgdGhlcmUgaXMgbm8gdGltZSBsaW1pdCBmb3IgdGhlIHByb2Nlc3MuCgogICAgICAgIE9uY2UgdGhlIHRpbWVyIGlzIHNldCwgdGhlIGNvbnN1bWVyIGNhbiBub3QgY2hhbmdlIGl0IGFueW1vcmUuCiAgICAgICAgSWYgdGhlIGNvbnN1bWVyIGhhcyBub3Qgc2V0IHRoZSB0aW1lciB0aGUgTW5TIFByb2R1Y2VyIG1heSBzZXQgaXQuIjsKICAgICAgeWV4dDNncHA6bm90Tm90aWZ5YWJsZTsKICAgIH0KICB9CgogIHR5cGVkZWYgVGVudGhPZkRlZ3JlZXMgewogICAgdHlwZSB1aW50MTYgewogICAgICByYW5nZSAwLi4zNjAwOwogICAgfQogICAgdW5pdHMgIjAuMSBkZWdyZWVzIjsKICAgIGRlc2NyaXB0aW9uICJBIHNpbmdsZSBpbnRlZ3JhbCB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIGFuIGFuZ2xlIGluIGRlZ3JlZXMKICAgICAgYmV0d2VlbiAwIGFuZCAzNjAgd2l0aCBhIHJlc29sdXRpb24gb2YgMC4xIGRlZ3JlZXMuIjsKICB9CgogIHR5cGVkZWYgTGF0aXR1ZGUgewogICAgdHlwZSBkZWNpbWFsNjQgewogICAgICBmcmFjdGlvbi1kaWdpdHMgNDsKICAgICAgcmFuZ2UgIi05MC4wMDAwLi4rOTAuMDAwMCI7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiTGF0aXR1ZGUgdmFsdWVzIjsKICB9CgogIHR5cGVkZWYgTG9uZ2l0dWRlIHsKICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgZnJhY3Rpb24tZGlnaXRzIDQ7CiAgICAgIHJhbmdlICItMTgwLjAwMDAuLisxODAuMDAwMCI7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiTG9uZ2l0dWRlIHZhbHVlcyI7CiAgfQoKICB0eXBlZGVmIEFsdGl0dWRlICB7CiAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgIGZyYWN0aW9uLWRpZ2l0cyA2OwogICAgfQogICAgdW5pdHMgIm1ldGVycyI7CiAgICBkZXNjcmlwdGlvbgogICAgICAiSGVpZ2h0IGZyb20gYSByZWZlcmVuY2UgMCB2YWx1ZS4iOwogIH0KCiAgZ3JvdXBpbmcgR2VvZ3JhcGhpY2FsQ29vcmRpbmF0ZXMgewogICAgZGVzY3JpcHRpb24gIlRoaXMgZGF0YXR5cGUgcmVwcmVzZW50cyB0aGUgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIjsKICAgIHJlZmVyZW5jZSAiI0dQUCBUUyAyOC41NTggY2xhdXNlIDYuMy44IjsKCiAgICBsZWFmIGxhdGl0dWRlIHsKICAgICAgdHlwZSBMYXRpdHVkZTsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CgogICAgbGVhZiBsb25naXR1ZGUgewogICAgICB0eXBlIExvbmdpdHVkZTsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CgogICAgbGVhZiBhbHRpdHVkZSB7CiAgICAgIHR5cGUgQWx0aXR1ZGU7CiAgICB9CgogIH0KCiAgdHlwZWRlZiBPbk9mZiB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBPTjsKICAgICAgZW51bSBPRkY7CiAgICB9CiAgfQoKICAvLyBncm91cGluZyBNYW5hZ2VkTkZQcm9maWxlIHdpbGwgYmUgcmVtb3ZlZCBhcyBpdCBpcwogIC8vICBiZWluZyBtb3ZlZCB0byBfM2dwcC01Z2MtbnJtLW5mcHJvZmlsZQogIGdyb3VwaW5nIE1hbmFnZWRORlByb2ZpbGUgewogICAgZGVzY3JpcHRpb24gIkRlZmluZXMgcHJvZmlsZSBmb3IgbWFuYWdlZCBORiI7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuNTAxIjsKCiAgICBsZWFmIGlkeCB7IHR5cGUgdWludDMyIDsgfQoKICAgIGxlYWYgbmZJbnN0YW5jZUlEIHsKICAgICAgY29uZmlnIGZhbHNlOwogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSB5YW5nOnV1aWQgOwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBwcm9maWxlIGZvciBtYW5hZ2VkIE5GLgogICAgICAgIFRoZSBmb3JtYXQgb2YgdGhlIE5GIEluc3RhbmNlIElEIHNoYWxsIGJlIGEKICAgICAgICBVbml2ZXJzYWxseSBVbmlxdWUgSWRlbnRpZmllciAoVVVJRCkgdmVyc2lvbiA0LAogICAgICAgIGFzIGRlc2NyaWJlZCBpbiBJRVRGIFJGQyA0MTIyICIgOwogICAgICB5ZXh0M2dwcDppblZhcmlhbnQ7CiAgICB9CgogICAgbGVhZi1saXN0IG5mVHlwZSB7CiAgICAgIGNvbmZpZyBmYWxzZTsKICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgIHR5cGUgTmZUeXBlOwogICAgICBkZXNjcmlwdGlvbiAiVHlwZSBvZiB0aGUgTmV0d29yayBGdW5jdGlvbiIgOwogICAgfQoKICAgIGxlYWYgaG9zdEFkZHIgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSBpbmV0Omhvc3QgOwogICAgICBkZXNjcmlwdGlvbiAiSG9zdCBhZGRyZXNzIG9mIGEgTkYiOwogICAgfQoKICAgIGxlYWYgYXV0aHpJbmZvIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBORiBTcGVjaWZpYyBTZXJ2aWNlIGF1dGhvcml6YXRpb24KICAgICAgICBpbmZvcm1hdGlvbi4gSXQgc2hhbGwgaW5jbHVkZSB0aGUgTkYgdHlwZSAocykgYW5kIE5GIHJlYWxtcy9vcmlnaW5zCiAgICAgICAgYWxsb3dlZCB0byBjb25zdW1lIE5GIFNlcnZpY2Uocykgb2YgTkYgU2VydmljZSBQcm9kdWNlci4iOwogICAgICByZWZlcmVuY2UgIlNlZSBUUyAyMy41MDEiIDsKICAgIH0KCiAgICBsZWFmIGxvY2F0aW9uIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiSW5mb3JtYXRpb24gYWJvdXQgdGhlIGxvY2F0aW9uIG9mIHRoZSBORiBpbnN0YW5jZQogICAgICAgIChlLmcuIGdlb2dyYXBoaWMgbG9jYXRpb24sIGRhdGEgY2VudGVyKSBkZWZpbmVkIGJ5IG9wZXJhdG9yIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmIGNhcGFjaXR5IHsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIHR5cGUgdWludDE2IDsKICAgICAgZGVzY3JpcHRpb24gIlRoaXMgcGFyYW1ldGVyIGRlZmluZXMgc3RhdGljIGNhcGFjaXR5IGluZm9ybWF0aW9uCiAgICAgICAgaW4gdGhlIHJhbmdlIG9mIDAtNjU1MzUsIGV4cHJlc3NlZCBhcyBhIHdlaWdodCByZWxhdGl2ZSB0byBvdGhlcgogICAgICAgIE5GIGluc3RhbmNlcyBvZiB0aGUgc2FtZSB0eXBlOyBpZiBjYXBhY2l0eSBpcyBhbHNvIHByZXNlbnQgaW4gdGhlCiAgICAgICAgbmZTZXJ2aWNlTGlzdCBwYXJhbWV0ZXJzLCB0aG9zZSB3aWxsIGhhdmUgcHJlY2VkZW5jZSBvdmVyIHRoaXMgdmFsdWUuIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmIG5GU3J2R3JvdXBJZCB7CiAgICAgIHR5cGUgc3RyaW5nIDsKICAgICAgZGVzY3JpcHRpb24gIlRoaXMgcGFyYW1ldGVyIGRlZmluZXMgaWRlbnRpdHkgb2YgdGhlIGdyb3VwIHRoYXQgaXMKICAgICAgICBzZXJ2ZWQgYnkgdGhlIE5GIGluc3RhbmNlLgogICAgICAgIE1heSBiZSBjb25maWcgZmFsc2Ugb3IgdHJ1ZSBkZXBlbmRpbmcgb24gdGhlIE1hbmFnZWRGdW5jdGlvbi4KICAgICAgICBDb25maWc9dHJ1ZSBmb3IgVWRyaW5mby4gQ29uZmlnPWZhbHNlIGZvciBVZG1JbmZvIGFuZCBBdXNmSW5mby4KICAgICAgICBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IFVETSBvciBBVVNGIG9yIFVEUi4gIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmLWxpc3Qgc3VwcG9ydGVkRGF0YVNldElkcyB7CiAgICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICAgIGVudW0gU1VCU0NSSVBUSU9OOwogICAgICAgIGVudW0gUE9MSUNZOwogICAgICAgIGVudW0gRVhQT1NVUkU7CiAgICAgICAgZW51bSBBUFBMSUNBVElPTjsKICAgICAgfQogICAgICBkZXNjcmlwdGlvbiAiTGlzdCBvZiBzdXBwb3J0ZWQgZGF0YSBzZXRzIGluIHRoZSBVRFIgaW5zdGFuY2UuCiAgICAgICAgTWF5IGJlIHByZXNlbnQgaWYgLi4vbmZUeXBlID0gVURSIjsKICAgICAgcmVmZXJlbmNlICJUUyAyOS41MTAiIDsKICAgIH0KCiAgICBsZWFmLWxpc3Qgc21mU2VydmluZ0FyZWFzIHsKICAgICAgdHlwZSBzdHJpbmcgOwogICAgICBkZXNjcmlwdGlvbiAiRGVmaW5lcyB0aGUgU01GIHNlcnZpY2UgYXJlYShzKSB0aGUgVVBGIGNhbiBzZXJ2ZS4KICAgICAgICBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IFVQRiI7CiAgICAgIHJlZmVyZW5jZSAiVFMgMjkuNTEwIiA7CiAgICB9CgogICAgbGVhZiBwcmlvcml0eSB7CiAgICAgIHR5cGUgdWludDE2OwogICAgICBkZXNjcmlwdGlvbiAiVGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyBQcmlvcml0eSAocmVsYXRpdmUgdG8gb3RoZXIgTkZzCiAgICAgICAgb2YgdGhlIHNhbWUgdHlwZSkgaW4gdGhlIHJhbmdlIG9mIDAtNjU1MzUsIHRvIGJlIHVzZWQgZm9yIE5GIHNlbGVjdGlvbjsKICAgICAgICBsb3dlciB2YWx1ZXMgaW5kaWNhdGUgYSBoaWdoZXIgcHJpb3JpdHkuIElmIHByaW9yaXR5IGlzIGFsc28gcHJlc2VudAogICAgICAgIGluIHRoZSBuZlNlcnZpY2VMaXN0IHBhcmFtZXRlcnMsIHRob3NlIHdpbGwgaGF2ZSBwcmVjZWRlbmNlIG92ZXIKICAgICAgICB0aGlzIHZhbHVlLiBTaGFsbCBiZSBwcmVzZW50IGlmIC4uL25mVHlwZSA9IEFNRiAiOwogICAgICByZWZlcmVuY2UgIlRTIDI5LjUxMCIgOwogICAgfQogIH0KCiAgdHlwZWRlZiB1c2FnZVN0YXRlIHsKICAgIHR5cGUgZW51bWVyYXRpb24gewogICAgICBlbnVtIElETEU7CiAgICAgIGVudW0gQUNUSVZFOwogICAgICBlbnVtIEJVU1k7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiSXQgZGVzY3JpYmVzIHdoZXRoZXIgb3Igbm90IHRoZSByZXNvdXJjZSBpcyBhY3RpdmVseSBpbgogICAgICB1c2UgYXQgYSBzcGVjaWZpYyBpbnN0YW50LCBhbmQgaWYgc28sIHdoZXRoZXIgb3Igbm90IGl0IGhhcyBzcGFyZQogICAgICBjYXBhY2l0eSBmb3IgYWRkaXRpb25hbCB1c2VycyBhdCB0aGF0IGluc3RhbnQuIFRoZSB2YWx1ZSBpcyBSRUFELU9OTFkuIjsKICAgIHJlZmVyZW5jZSAiSVRVIFQgUmVjb21tZW5kYXRpb24gWC43MzEiOwogIH0KCiAgZ3JvdXBpbmcgU0FQR3JwIHsKICAgIGxlYWYgaG9zdCB7CiAgICAgIHR5cGUgaW5ldDpob3N0OwogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgIH0KICAgIGxlYWYgcG9ydCB7CiAgICAgIHR5cGUgaW5ldDpwb3J0LW51bWJlcjsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICB9CiAgICBkZXNjcmlwdGlvbiAiU2VydmljZSBhY2Nlc3MgcG9pbnQuIjsKICAgIHJlZmVyZW5jZSAiVFMgMjguNjIyIjsKICB9CgogIHR5cGVkZWYgTWNjIHsKICAgIGRlc2NyaXB0aW9uICJUaGUgbW9iaWxlIGNvdW50cnkgY29kZSBjb25zaXN0cyBvZiB0aHJlZSBkZWNpbWFsIGRpZ2l0cywKICAgICAgVGhlIGZpcnN0IGRpZ2l0IG9mIHRoZSBtb2JpbGUgY291bnRyeSBjb2RlIGlkZW50aWZpZXMgdGhlIGdlb2dyYXBoaWMKICAgICAgcmVnaW9uICh0aGUgZGlnaXRzIDEgYW5kIDggYXJlIG5vdCB1c2VkKToiOwogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMDItNzldWzAtOV1bMC05XSc7CiAgICB9CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuMDAzIHN1YmNsYXVzZSAyLjIgYW5kIDEyLjEiOwogIH0KCiAgdHlwZWRlZiBNbmMgewogICAgZGVzY3JpcHRpb24gIlRoZSBtb2JpbGUgbmV0d29yayBjb2RlIGNvbnNpc3RzIG9mIHR3byBvciB0aHJlZQogICAgICBkZWNpbWFsIGRpZ2l0cyAoZm9yIGV4YW1wbGU6IE1OQyBvZiAwMDEgaXMgbm90IHRoZSBzYW1lIGFzIE1OQyBvZiAwMSkiOwogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMC05XVswLTldWzAtOV18WzAtOV1bMC05XSc7CiAgICB9CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjMuMDAzIHN1YmNsYXVzZSAyLjIgYW5kIDEyLjEiOwogIH0KCiAgZ3JvdXBpbmcgUExNTklkIHsKICAgIGxlYWYgbWNjIHsKICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIHR5cGUgTWNjOwogICAgfQogICAgbGVhZiBtbmMgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgdHlwZSBNbmM7CiAgICB9CiAgICByZWZlcmVuY2UgIlRTIDM4LjQxMyBjbGF1c2UgOS4zLjMuNSI7CiAgfQoKICB0eXBlZGVmIE5jaSB7CiAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbCBJZGVudGl0eS4gVGhlIE5DSSBzaGFsbCBiZSBvZiBmaXhlZCBsZW5ndGggb2YgMzYgYml0cwogICAgICBhbmQgc2hhbGwgYmUgY29kZWQgdXNpbmcgZnVsbCBoZXhhZGVjaW1hbCByZXByZXNlbnRhdGlvbi4KICAgICAgVGhlIGV4YWN0IGNvZGluZyBvZiB0aGUgTkNJIGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiBlYWNoIFBMTU4gb3BlcmF0b3IiOwogICAgcmVmZXJlbmNlICJUUyAyMy4wMDMiOwogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggMzY7CiAgICAgICAgcGF0dGVybiAnWzAxXSsnOwogICAgICB9CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggOTsKICAgICAgICBwYXR0ZXJuICdbYS1mQS1GMC05XSonOwogICAgICB9CiAgICB9CiAgfQoKICB0eXBlZGVmIE9wZXJhdGlvbmFsU3RhdGUgewogICAgcmVmZXJlbmNlICIzR1BQIFRTIDI4LjYyNSBhbmQgSVRVLVQgWC43MzEiOwogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gRElTQUJMRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyB0b3RhbGx5IGlub3BlcmFibGUuIjsKICAgICAgfQoKICAgICAgZW51bSBFTkFCTEVEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgcGFydGlhbGx5IG9yIGZ1bGx5IG9wZXJhYmxlLiI7CiAgICAgIH0KCiAgICB9CiAgfQoKICB0eXBlZGVmIEJhc2ljQWRtaW5pc3RyYXRpdmVTdGF0ZSB7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjguNjI1IGFuZCBJVFUtVCBYLjczMSI7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBMT0NLRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyBhZG1pbmlzdHJhdGl2ZWx5IHByb2hpYml0ZWQgZnJvbSBwZXJmb3JtaW5nCiAgICAgICAgICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4iOwogICAgICB9CgogICAgICBlbnVtIFVOTE9DS0VEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgYWRtaW5pc3RyYXRpdmVseSBwZXJtaXR0ZWQgdG8gcGVyZm9ybQogICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4gVGhpcyBpcyBpbmRlcGVuZGVudCBvZiBpdHMgaW5oZXJlbnQKICAgICAgICAgIG9wZXJhYmlsaXR5LiI7CiAgICAgIH0KICAgIH0KICB9CgogIHR5cGVkZWYgQWRtaW5pc3RyYXRpdmVTdGF0ZSB7CiAgICByZWZlcmVuY2UgIjNHUFAgVFMgMjguNjI1IGFuZCBJVFUtVCBYLjczMSI7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBMT0NLRUQgewogICAgICAgIHZhbHVlIDA7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSByZXNvdXJjZSBpcyBhZG1pbmlzdHJhdGl2ZWx5IHByb2hpYml0ZWQgZnJvbSBwZXJmb3JtaW5nCiAgICAgICAgICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4iOwogICAgICB9CgogICAgICBlbnVtIFVOTE9DS0VEIHsKICAgICAgICB2YWx1ZSAxOwogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgcmVzb3VyY2UgaXMgYWRtaW5pc3RyYXRpdmVseSBwZXJtaXR0ZWQgdG8gcGVyZm9ybQogICAgICAgICAgc2VydmljZXMgZm9yIGl0cyB1c2Vycy4gVGhpcyBpcyBpbmRlcGVuZGVudCBvZiBpdHMgaW5oZXJlbnQKICAgICAgICAgIG9wZXJhYmlsaXR5LiI7CiAgICAgIH0KCiAgICAgIGVudW0gU0hVVFRJTkdET1dOIHsKICAgICAgICB2YWx1ZSAyOwogICAgICAgIGRlc2NyaXB0aW9uICJVc2Ugb2YgdGhlIHJlc291cmNlIGlzIGFkbWluaXN0cmF0aXZlbHkgcGVybWl0dGVkIHRvCiAgICAgICAgICBleGlzdGluZyBpbnN0YW5jZXMgb2YgdXNlIG9ubHkuIFdoaWxlIHRoZSBzeXN0ZW0gcmVtYWlucyBpbgogICAgICAgICAgdGhlIHNodXR0aW5nIGRvd24gc3RhdGUgdGhlIG1hbmFnZXIgb3IgdGhlIG1hbmFnZWQgZWxlbWVudAogICAgICAgICAgbWF5IGF0IGFueSB0aW1lIGNhdXNlIHRoZSByZXNvdXJjZSB0byB0cmFuc2l0aW9uIHRvIHRoZQogICAgICAgICAgbG9ja2VkIHN0YXRlLiI7CiAgICAgIH0KICAgIH0KICB9CgogIHR5cGVkZWYgQXZhaWxhYmlsaXR5U3RhdHVzIHsKICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICBlbnVtIElOX1RFU1Q7CiAgICAgICAgICBlbnVtIEZBSUxFRDsKICAgICAgICAgIGVudW0gUE9XRVJfT0ZGOwogICAgICAgICAgZW51bSBPRkZfTElORTsKICAgICAgICAgIGVudW0gT0ZGX0RVVFk7CiAgICAgICAgICBlbnVtIERFUEVOREVOQ1k7CiAgICAgICAgICBlbnVtIERFR1JBREVEOwogICAgICAgICAgZW51bSBOT1RfSU5TVEFMTEVEOwogICAgICAgICAgZW51bSBMT0dfRlVMTDsKICAgICAgIH0KICB9CgogIHR5cGVkZWYgQ2VsbFN0YXRlIHsKICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgZW51bSBJRExFOwogICAgICAgIGVudW0gSU5BQ1RJVkU7CiAgICAgICAgZW51bSBBQ1RJVkU7CiAgICAgfQogIH0KCiAgdHlwZWRlZiBOcnBjaSB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uICJQaHlzaWNhbCBDZWxsIElkZW50aXR5IChQQ0kpIG9mIHRoZSBOUiBjZWxsLiI7CiAgICByZWZlcmVuY2UgIlRTIDM2LjIxMSBzdWJjbGF1c2UgNi4xMSI7CiAgfQoKICB0eXBlZGVmIFRhYyB7CiAgICB0eXBlIGludDMyIHsKICAgICAgcmFuZ2UgMC4uMTY3NzcyMTUgOwogICAgfQogICAgZGVzY3JpcHRpb24gIlRyYWNraW5nIEFyZWEgQ29kZSI7CiAgICByZWZlcmVuY2UgIlRTIDIzLjAwMyBjbGF1c2UgMTkuNC4yLjMiOwogIH0KCiAgZ3JvdXBpbmcgVGFpR3JwIHsKICAgIGRlc2NyaXB0aW9uICJUaGlzIDw8ZGF0YVR5cGU+PiBkZWZpbmVzIGEgVHJhY2tpbmcgQXJlYSBJZGVudGl0eSAoVEFJKQogICAgICBhcyBzcGVjaWZpZWQgaW4gY2xhdXNlIDI4LjYgb2YgVFMgMjMuMDAzLCBjbGF1c2UgOC4yIG9mIFRTIDM4LjMwMAogICAgICBhbmQgY2xhdXNlIDkuMy4zLjExIG9mIFRTIDM4LjQxMy4gSXQgaXMgY29tcG9zZWQgb2YgdGhlIFBMTU4KICAgICAgaWRlbnRpZmllciAoUExNTi1JZCwgd2hpY2ggaXMgY29tcG9zZWQgb2YgdGhlIE1DQyBhbmQgTU5DKSBhbmQKICAgICAgdGhlIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKS4gIjsKICAgIGxpc3QgcGxtbklkIHsKICAgICAgZGVzY3JpcHRpb24gIlBMTU4gSWRlbnRpdHkuIjsKICAgICAgbWluLWVsZW1lbnRzIDE7CiAgICAgIG1heC1lbGVtZW50cyAxOwogICAgICBrZXkgIm1jYyBtbmMiOwogICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICB9CgogICAgbGVhZiB0YWMgeyB0eXBlIFRhYzsgfQogIH0KCiAgZ3JvdXBpbmcgR2VvQ29vcmRpbmF0ZUdycCB7CiAgICBkZXNjcmlwdGlvbiAiR2VvZ3JhcGhpY2FsIGxvY2F0aW9uIG9uIGVhcnRoIjsKICAgIGxlYWYgbGF0aXR1ZGUgewogICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDQ7CiAgICAgICAgcmFuZ2UgLTkwLi45MCA7CiAgICAgIH0KICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgIGRlc2NyaXB0aW9uICJMYXRpdHVkZSBiYXNlZCBvbiBXb3JsZCBHZW9kZXRpYyBTeXN0ZW0gKDE5ODQgdmVyc2lvbikKICAgICAgICBnbG9iYWwgcmVmZXJlbmNlIGZyYW1lIChXR1MgODQpLiBQb3NpdGl2ZSB2YWx1ZXMgY29ycmVzcG9uZCB0byB0aGUKICAgICAgICBub3J0aGVybiBoZW1pc3BoZXJlLiI7CiAgICAgIH0KCiAgICBsZWFmIGxvbmdpdHVkZSB7CiAgICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNDsKICAgICAgICByYW5nZSAtMTgwLi4xODAgOwogICAgICB9CiAgICAgIG1hbmRhdG9yeSB0cnVlOwogICAgICBkZXNjcmlwdGlvbiAiTG9uZ2l0dWRlIGJhc2VkIG9uIFdvcmxkIEdlb2RldGljIFN5c3RlbSAoMTk4NCB2ZXJzaW9uKQogICAgICAgIGdsb2JhbCByZWZlcmVuY2UgZnJhbWUgKFdHUyA4NCkuIFBvc2l0aXZlIHZhbHVlcyBjb3JyZXNwb25kIHRvCiAgICAgICAgZGVncmVlcyBlYXN0IG9mIDAgZGVncmVlcyBsb25naXR1ZGUuIjsKICAgIH0KICB9CgogIGdyb3VwaW5nIEdlb0FyZWFHcnAgewogICAgZGVzY3JpcHRpb24gIlRoaXMgZGF0YSB0eXBlIGRlZmluZXMgYSBnZW9ncmFwaGljYWwgYXJlYS4KICAgICAgVGhlIGdlby1hcmVhIGlzIGRlZmluZWQgdXNpbmcgYSBjb252ZXggcG9seWdvbiBpbiB0aGUgYXR0cmlidXRlCiAgICAgICdjb252ZXhHZW9Qb2x5Z29uJy4iOwoKICAgIGxpc3QgY29udmV4R2VvUG9seWdvbiB7CiAgICAgIGRlc2NyaXB0aW9uICJTcGVjaWZpZXMgdGhlIGdlb2dyYXBoaWNhbCBhcmVhIHdpdGggYSBjb252ZXggcG9seWdvbi4KICAgICAgICBUaGUgY29udmV4IHBvbHlnb24gaXMgc3BlY2lmaWVkIGJ5IGl0cyBjb3JuZXJzLiI7CiAgICAgICAga2V5ICJsYXRpdHVkZSBsb25naXR1ZGUiOwogICAgICBtaW4tZWxlbWVudHMgMzsKICAgICAgb3JkZXJlZC1ieSB1c2VyOwoKICAgICAgdXNlcyBHZW9Db29yZGluYXRlR3JwOwogICAgfQogIH0KCiAgdHlwZWRlZiBBbWZSZWdpb25JZCB7CiAgICB0eXBlIHVuaW9uIHsKICAgICAgdHlwZSB1aW50OCA7CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggODsKICAgICAgICBwYXR0ZXJuICdbMDFdKic7CiAgICAgIH0KICAgIH0KICAgIHJlZmVyZW5jZSAiY2xhdXNlIDIuMTAuMSBvZiAzR1BQIFRTIDIzLjAwMyI7CiAgfQoKICB0eXBlZGVmIEFtZlNldElkIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIHVpbnQxNiB7CiAgICAgICAgcmFuZ2UgJzAuLjEwMjMnOwogICAgICB9CiAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICBsZW5ndGggODsKICAgICAgICBwYXR0ZXJuICdbMDFdKic7CiAgICAgIH0KICAgIH0KICAgIHJlZmVyZW5jZSAiY2xhdXNlIDIuMTAuMSBvZiAzR1BQIFRTIDIzLjAwMyI7CiAgfQoKICB0eXBlZGVmIEFtZlBvaW50ZXIgewogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgdWludDggewogICAgICAgIHJhbmdlICcwLi42Myc7CiAgICAgIH0KICAgICAgdHlwZSBzdHJpbmcgewogICAgICAgIGxlbmd0aCA2OwogICAgICAgIHBhdHRlcm4gJ1swMV0qJzsKICAgICAgfQogICAgfQogICAgcmVmZXJlbmNlICJjbGF1c2UgMi4xMC4xIG9mIDNHUFAgVFMgMjMuMDAzIjsKICB9CgogIGdyb3VwaW5nIEFtZklkZW50aWZpZXIgewogICAgbGVhZiBhbWZSZWdpb25JZCB7CiAgICAgIHR5cGUgQW1mUmVnaW9uSWQ7CiAgICB9CiAgICBsZWFmIGFtZlNldElkIHsKICAgICAgdHlwZSBBbWZTZXRJZDsKICAgIH0KICAgIGxlYWYgYW1mUG9pbnRlciB7CiAgICAgIHR5cGUgQW1mUG9pbnRlcjsKICAgIH0KICAgIGRlc2NyaXB0aW9uICJUaGUgQU1GSSBpcyBjb25zdHJ1Y3RlZCBmcm9tIGFuIEFNRiBSZWdpb24gSUQsCiAgICAgIGFuIEFNRiBTZXQgSUQgYW5kIGFuIEFNRiBQb2ludGVyLgogICAgICBUaGUgQU1GIFJlZ2lvbiBJRCBpZGVudGlmaWVzIHRoZSByZWdpb24sCiAgICAgIHRoZSBBTUYgU2V0IElEIHVuaXF1ZWx5IGlkZW50aWZpZXMgdGhlIEFNRiBTZXQgd2l0aGluIHRoZSBBTUYgUmVnaW9uLCBhbmQKICAgICAgdGhlIEFNRiBQb2ludGVyIHVuaXF1ZWx5IGlkZW50aWZpZXMgdGhlIEFNRiB3aXRoaW4gdGhlIEFNRiBTZXQuICI7CiAgfQoKLy8gdHlwZSBkZWZpbml0aW9ucyBlc3BlY2lhbGx5IGZvciBjb3JlIE5GcwoKICB0eXBlZGVmIE5mVHlwZSB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBOUkY7CiAgICAgIGVudW0gVURNOwogICAgICBlbnVtIEFNRjsKICAgICAgZW51bSBTTUY7CiAgICAgIGVudW0gQVVTRjsKICAgICAgZW51bSBORUY7CiAgICAgIGVudW0gUENGOwogICAgICBlbnVtIFNNU0Y7CiAgICAgIGVudW0gTlNTRjsKICAgICAgZW51bSBVRFI7CiAgICAgIGVudW0gTE1GOwogICAgICBlbnVtIEdNTEM7CiAgICAgIGVudW0gNUdfRUlSOwogICAgICBlbnVtIFNFUFA7CiAgICAgIGVudW0gVVBGOwogICAgICBlbnVtIE4zSVdGOwogICAgICBlbnVtIEFGOwogICAgICBlbnVtIFVEU0Y7CiAgICAgIGVudW0gQlNGOwogICAgICBlbnVtIENIRjsKICAgIH0KICB9CgogIHR5cGVkZWYgTm90aWZpY2F0aW9uVHlwZSB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBOMV9NRVNTQUdFUzsKICAgICAgZW51bSBOMl9JTkZPUk1BVElPTjsKICAgICAgZW51bSBMT0NBVElPTl9OT1RJRklDQVRJT047CiAgICB9CiAgfQoKICB0eXBlZGVmIExvYWQgewogICAgZGVzY3JpcHRpb24gIkxhdGVzdCBrbm93biBsb2FkIGluZm9ybWF0aW9uIG9mIHRoZSBORiwgcGVyY2VudGFnZSAiOwogICAgdHlwZSB1aW50OCB7CiAgICAgIHJhbmdlIDAuLjEwMDsKICAgIH0KICB9CgogIHR5cGVkZWYgTjFNZXNzYWdlQ2xhc3MgewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gNUdNTTsKICAgICAgZW51bSBTTTsKICAgICAgZW51bSBMUFA7CiAgICAgIGVudW0gU01TOwogICAgfQogIH0KCiAgdHlwZWRlZiBOMkluZm9ybWF0aW9uQ2xhc3MgewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gU007CiAgICAgIGVudW0gTlJQUEE7CiAgICAgIGVudW0gUFdTOwogICAgICBlbnVtIFBXU19CQ0FMOwogICAgICBlbnVtIFBXU19SRjsKICAgIH0KICB9CgogIGdyb3VwaW5nIERlZmF1bHROb3RpZmljYXRpb25TdWJzY3JpcHRpb24gewoKICAgIGxlYWYgbm90aWZpY2F0aW9uVHlwZSB7CiAgICAgIHR5cGUgTm90aWZpY2F0aW9uVHlwZTsKICAgIH0KCiAgICBsZWFmIGNhbGxiYWNrVXJpIHsKICAgICAgdHlwZSBpbmV0OnVyaTsKICAgIH0KCiAgICBsZWFmIG4xTWVzc2FnZUNsYXNzIHsKICAgICAgdHlwZSBOMU1lc3NhZ2VDbGFzczsKICAgIH0KCiAgICBsZWFmIG4ySW5mb3JtYXRpb25DbGFzcyB7CiAgICAgIHR5cGUgTjJJbmZvcm1hdGlvbkNsYXNzOwogICAgfQogIH0KCiAgZ3JvdXBpbmcgSXB2NEFkZHJlc3NSYW5nZSB7CiAgbGVhZiBzdGFydCB7CiAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzOwogICAgfQogIGxlYWYgZW5kIHsKICAgIHR5cGUgaW5ldDppcHY0LWFkZHJlc3M7CiAgICB9CiAgfQoKICBncm91cGluZyBJcHY2UHJlZml4UmFuZ2UgewogIGxlYWYgc3RhcnQgewogICAgdHlwZSBpbmV0OmlwdjYtcHJlZml4OwogICAgfQogIGxlYWYgZW5kIHsKICAgIHR5cGUgaW5ldDppcHY2LXByZWZpeDsKICAgIH0KICB9CgogIHR5cGVkZWYgTnNpSWQgewogICAgdHlwZSBzdHJpbmc7CiAgfQoKICB0eXBlZGVmIFVlTW9iaWxpdHlMZXZlbCB7CiAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgZW51bSBTVEFUSU9OQVJZOwogICAgICBlbnVtIE5PTUFESUM7CiAgICAgIGVudW0gUkVTVFJJQ1RFRF9NT0JJTElUWTsKICAgICAgZW51bSBGVUxMWV9NT0JJTElUWTsKICAgIH0KICB9CgogIHR5cGVkZWYgUmVzb3VyY2VTaGFyaW5nTGV2ZWwgewogICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICBlbnVtIFNIQVJFRDsKICAgICAgICBlbnVtIE5PVF9TSEFSRUQ7CiAgICAgIH0KICB9CgogIHR5cGVkZWYgVHhEaXJlY3Rpb24gewogICAgICB0eXBlIGVudW1lcmF0aW9uIHsKICAgICAgICBlbnVtIERMOwogICAgICAgIGVudW0gVUw7CiAgICAgICAgZW51bSBETF9BTkRfVUw7CiAgICAgIH0KICB9CgogIGdyb3VwaW5nIEFkZHJlc3NXaXRoVmxhbiB7CiAgICBsZWFmIGlwQWRkcmVzcyB7CiAgICAgIHR5cGUgaW5ldDppcC1hZGRyZXNzOwogICAgfQogICAgbGVhZiB2bGFuSWQgewogICAgICAgdHlwZSB1aW50MTY7CiAgICB9CiAgfQoKICAvKiBEaXN0aW5ndWlzaGVkTmFtZSBwYXR0ZXJuIGlzIGJ1aWx0IHVwIGJhc2VkIG9uIHRoZQogICAgRUJORiBpbiAzMi4zMDAgY2xhdXNlIDcuMyAgRUJORiBvZiBETiBTdHJpbmcgUmVwcmVzZW50YXRpb24KCiAgICBsZWFmIEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vICBTYW1lIHBhdHRlcm4gYXMgTG9jYWxETgogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPygsW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKj0oW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pKic7CiAgICB9IH0KCiAgICBsZWFmIGZ1bGxMb2NhbEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIExvY2FsUkROICwgeyBSRE5TZXBhcmF0b3IgLCBMb2NhbFJETiB9ICAgIFJETlNlcGFyYXRvciBpcyBhIHNpbmdsZSAsIG5vIHNwYWNlIG9yIFxSIGFsbG93ZWQgICBNZS5teWtleT0xIGFsbG93ZWQKICAgICAgLy8gIChmdWxsTG9jYWxSRE4pKCwoZnVsbExvY2FsUkROKSkqCiAgICAgIHBhdHRlcm4gJygoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKikpPSgoW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pKSgsKChbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qfChbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qXC5bYS16XVteLD0rPD4jO1xcIlxyXG4qLl0qKSk9KChbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykpKSonOwogICAgfSB9CgogICAgbGVhZiBMb2NhbEROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIExvY2FsUkROICwgeyBSRE5TZXBhcmF0b3IgLCBMb2NhbFJETiB9ICAgIFJETlNlcGFyYXRvciBpcyBhIHNpbmdsZSAsIG5vIHNwYWNlIG9yIFxSIGFsbG93ZWQKICAgICAgLy8gIExvY2FsUkROKCxMb2NhbFJETikqCiAgICAgIHBhdHRlcm4gJ1tBLVpdW14sPSs8PiM7XFwiXHJcbiouXSo9KFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/KCxbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykqJzsKICAgIH0gfQoKICAgIGxlYWYgZnVsbExvY2FsUkROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIHNhbWUgYXMgZnVsbExvY2FsRE5BdHRyaWJ1dGVUeXBlQW5kVmFsdWUKICAgICAgcGF0dGVybiAnKFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSp8KFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSpcLlthLXpdW14sPSs8PiM7XFwiXHJcbiouXSopKT0oKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/KSc7CiAgICB9IH0KCiAgICBsZWFmIExvY2FsUkROIHsgdHlwZSBzdHJpbmcgeyAgIC8vIHNhbWUgYXMgTG9jYWxETkF0dHJpYnV0ZVR5cGVBbmRWYWx1ZQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPyc7CiAgICB9IH0KCiAgICBsZWFmIGZ1bGxMb2NhbEROQXR0cmlidXRlVHlwZUFuZFZhbHVlIHsgdHlwZSBzdHJpbmcgeyAvLyBMb2NhbEROQXR0cmlidXRlVHlwZSAsIEF0dHJpYnV0ZVR5cGVBbmRWYWx1ZVNlcGFyYXRvciAsIFJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICAvLyBwYXR0ZXJuIExvY2FsRE5BdHRyaWJ1dGVUeXBlPVJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICBwYXR0ZXJuICcoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKikpPSgoW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSooW14sPSs8PiM7XFwiXHJcbiogXXwoXFxbYS1mQS1GMC05XXsyfSkpKT8pJzsKICAgIH0gfQoKICAgICAgLy8gbGltaXRhdGlvbjogTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlbm90IHN1cHBvcnRlZCBNZS5teWtleT0xCiAgICBsZWFmIExvY2FsRE5BdHRyaWJ1dGVUeXBlQW5kVmFsdWUgeyB0eXBlIHN0cmluZyB7CiAgICAgIC8vIGVibmYxICAgICAgICAgIExvY2FsRE5BdHRyaWJ1dGVUeXBlICwgQXR0cmlidXRlVHlwZUFuZFZhbHVlU2VwYXJhdG9yICwgUmVndWxhckF0dHJpYnV0ZVZhbHVlCiAgICAgIC8vIGVibmYyLWxpbWl0ZWQgIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlICwgQXR0cmlidXRlVHlwZUFuZFZhbHVlU2VwYXJhdG9yICwgUmVndWxhckF0dHJpYnV0ZVZhbHVlCiAgICAgIC8vIHBhdHRlcm4gICAgICAgIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlPVJlZ3VsYXJBdHRyaWJ1dGVWYWx1ZQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qPShbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKihbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPyc7CiAgICB9IH0KCiAgICBsZWFmIExvY2FsRE5BdHRyaWJ1dGVUeXBlIHsgdHlwZSBzdHJpbmcgeyAgIC8vIE5hbWVPZkNsYXNzV2l0aElkQXR0cmlidXRlIHwgTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlICBSRE5TZXBhcmF0b3IgaXMgYSBzaW5nbGUgLCBubyBzcGFjZSBvciBcUiBhbGxvd2VkCiAgICAgIC8vICBOYW1lT2ZDbGFzc1dpdGhJZEF0dHJpYnV0ZXxOYW1lc09mQ2xhc3NBbmROYW1pbmdBdHRyaWJ1dGUKICAgICAgcGF0dGVybiAnW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKnwoW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKlwuW2Etel1bXiw9Kzw+IztcXCJcclxuKi5dKiknOwogICAgfSB9CgogICAgbGVhZiBSZWd1bGFyQXR0cmlidXRlVmFsdWUgeyB0eXBlIHN0cmluZyB7ICAgICAgIC8vICggQXR0cmlidXRlVmFsdWVDaGFyIC0gU3BhY2VDaGFyICkgLCBbIHsgQXR0cmlidXRlVmFsdWVDaGFyIH0gLCAoIEF0dHJpYnV0ZVZhbHVlQ2hhciAtIFNwYWNlQ2hhciApIF0KICAgICAgcGF0dGVybiAnKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSgoW14sPSs8PiM7XFwiXHJcbipdfChcXFthLWZBLUYwLTldezJ9KSkqKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/JyA7CiAgICB9IH0KCiAgICBsZWFmIE5hbWVzT2ZDbGFzc0FuZE5hbWluZ0F0dHJpYnV0ZSAgeyB0eXBlIHN0cmluZyB7ICAvLyBDbGFzc05hbWUgLCBDbGFzc05hbWluZ0F0dHJpYnV0ZVNlcGFyYXRvciAsIE5hbWluZ0F0dHJpYnV0ZU5hbWUKICAgICAgLy8gcGF0dGVybjogQ2xhc3NOYW1lXC5OYW1pbmdBdHRyaWJ1dGVOYW1lCiAgICAgIHBhdHRlcm4gJ1tBLVpdW14sPSs8PiM7XFwiXHJcbiouXSpcLlthLXpdW14sPSs8PiM7XFwiXHJcbiouXSonIDsKICAgIH0gfQoKICAgIGxlYWYgcmVzdHJpY3RpdmVDbGFzc05hbWUgeyB0eXBlIHN0cmluZyB7ICAgICAvLwogICAgICBwYXR0ZXJuICdbYS16QS1aXVthLXpBLVowLTktX10qJyA7CiAgICB9IH0KCiAgICBsZWFmIENsYXNzTmFtZSB7IHR5cGUgc3RyaW5nIHsgICAgIC8vIENhcGl0YWxMZXR0ZXJDaGFyICwgeyBMb2NhbEROQXR0cmlidXRlVHlwZUNoYXIgfQogICAgICBwYXR0ZXJuICdbQS1aXVteLD0rPD4jO1xcIlxyXG4qLl0qJyA7CiAgICB9IH0KCiAgICBsZWFmIE5hbWluZ0F0dHJpYnV0ZU5hbWUgeyB0eXBlIHN0cmluZyB7ICAgLy8gU21hbGxMZXR0ZXJDaGFyICwgeyBMb2NhbEROQXR0cmlidXRlVHlwZUNoYXIgfQogICAgICBwYXR0ZXJuICdbYS16XVteLD0rPD4jO1xcIlxyXG4qLl0qJyA7CiAgICB9IH0KCiAgKi8KICB0eXBlZGVmIERpc3Rpbmd1aXNoZWROYW1lIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnW0EtWl1bXiw9Kzw+IztcXCJcclxuKi5dKj0oW14sPSs8PiM7XFwiXHJcbiogXXwnCiAgICAgICsgJyhcXFthLWZBLUYwLTldezJ9KSkoKFteLD0rPD4jO1xcIlxyXG4qXXwoXFxbYS1mQS1GMC05XXsyfSkpKicKICAgICAgKyAnKFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKSk/JwogICAgICArICcoLFtBLVpdW14sPSs8PiM7XFwiXHJcbiouXSo9KFteLD0rPD4jO1xcIlxyXG4qIF18KFxcW2EtZkEtRjAtOV17Mn0pKScKICAgICAgKyAnKChbXiw9Kzw+IztcXCJcclxuKl18KFxcW2EtZkEtRjAtOV17Mn0pKSonCiAgICAgICsgJyhbXiw9Kzw+IztcXCJcclxuKiBdfChcXFthLWZBLUYwLTldezJ9KSkpPykqJzsKICAgIH0KICAgIGRlc2NyaXB0aW9uICJSZXByZXNlbnRzIHRoZSAzR1BQIHN0YW5kYXJkIGZvciBEaXN0aW5ndWlzaGVkTmFtZS4KCiAgICAgIExpbWl0YXRpb25zOgogICAgICAtIFJETlNlcGFyYXRvcjogZG9uJ3QgYWxsb3cgU3BhY2VDaGFyIG9yIENhcnJpYWdlUmV0dXJuQ2hhcgogICAgICAtIE51bGxETjogRGlzYWxsb3cgbnVsbEROIHRoYXQgaXMgdGhlIHNhbWUgYXMgbm90IHByb3ZpZGluZyBhIEROCiAgICAgIC0gTmFtZXNPZkNsYXNzQW5kTmFtaW5nQXR0cmlidXRlIGZvcm1hdCBub3QgYWxsb3dlZAogICAgICAgIChlZy4gTWFuYWdlZEVsZW1lbnQubXlrZXk9MzQ1NDM2KSI7CiAgICByZWZlcmVuY2UgICIzR1BQIFRTIDMyLjMwMCI7CiAgfQoKICB0eXBlZGVmIFFPZmZzZXRSYW5nZSAgewogICAgdHlwZSBpbnQ4IHsKICAgICAgcmFuZ2UgIi0yNCB8IC0yMiB8IC0yMCB8IC0xOCB8IC0xNiB8IC0xNCB8IC0xMiB8IC0xMCB8IC04IHwgLTYgfCAiICsKICAgICAgICAiIC01IHwgLTQgfCAtMyB8IC0yIHwgLTEgfCAwIHwgMSB8IDIgfCAzIHwgNCB8IDUgfCA2IHwgOCB8IDEwIHwgIiArCiAgICAgICAgIiAxMiB8IDE0IHwgMTYgfCAxOCB8IDIwIHwgMjIgfCAyNCI7CiAgICB9CiAgICB1bml0cyBkQjsKICB9CgogIGdyb3VwaW5nIFJlcG9ydGluZ0N0cmwgewogICAgY2hvaWNlIHJlcG9ydGluZ0N0cmwgewogICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgZGVzY3JpcHRpb24gIgogICAgICAgIFRoaXMgY2hvaWNlIGRlZmluZXMgdGhlIG1ldGhvZCBmb3IgcmVwb3J0aW5nIGNvbGxlY3RlZCBwZXJmb3JtYW5jZQogICAgICAgIG1ldHJpY3MgdG8gTW5TIGNvbnN1bWVycyBhcyB3ZWxsIGFzIHRoZSBwYXJhbWV0ZXJzIGZvciBjb25maWd1cmluZyB0aGUKICAgICAgICByZXBvcnRpbmcgZnVuY3Rpb24uIEl0IGlzIGEgY2hvaWNlIGJldHdlZW4gdGhlIGNvbnRyb2wgcGFyYW1ldGVyCiAgICAgICAgcmVxdWlyZWQgZm9yIHRoZSByZXBvcnRpbmcgbWV0aG9kcywgd2hvc2UgcHJlc2VuY2Ugc2VsZWN0cyB0aGUKICAgICAgICByZXBvcnRpbmcgbWV0aG9kIGFzIGZvbGxvd3M6CgogICAgICAgIC0gV2hlbiBvbmx5IHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGF0dHJpYnV0ZSBpcyBwcmVzZW50LCB0aGUgTW5TCiAgICAgICAgcHJvZHVjZXIgc2hhbGwgc3RvcmUgZmlsZXMgb24gdGhlIE1uUyBwcm9kdWNlciBhdCBhIGxvY2F0aW9uIHNlbGVjdGVkCiAgICAgICAgYnkgdGhlIE1uUyBwcm9kdWNlciBhbmQsIG9uIGNvbmRpdGlvbiB0aGF0IGFuIGFwcHJvcHJpYXRlIHN1YnNjcmlwdGlvbgogICAgICAgIGlzIGluIHBsYWNlLCBpbmZvcm0gdGhlIE1uUyBjb25zdW1lciBhYm91dCB0aGUgYXZhaWxhYmlsaXR5IG9mIG5ldwogICAgICAgIGZpbGVzIGFuZCB0aGUgZmlsZSBsb2NhdGlvbiB1c2luZyB0aGUgbm90aWZ5RmlsZVJlYWR5IG5vdGlmaWNhdGlvbi4KICAgICAgICBJbiBjYXNlIHRoZSBwcmVwYXJhdGlvbiBvZiBhIGZpbGUgZmFpbHMsICdub3RpZnlGaWxlUHJlcGFyYXRpb25FcnJvcicKICAgICAgICBzaGFsbCBiZSBzZW50IGluc3RlYWQuCgogICAgICAgIC0gV2hlbiB0aGUgJ2ZpbGVSZXBvcnRpbmdQZXJpb2QnIGFuZCAnbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcycKICAgICAgICBhdHRyaWJ1dGVzIGFyZSBwcmVzZW50LCB0aGVuIHRoZSBNblMgcHJvZHVjZXIgc2hhbGwgYmVoYXZlIGxpa2UKICAgICAgICBkZXNjcmliZWQgZm9yIHRoZSBjYXNlIHRoYXQgb25seSB0aGUgJ2ZpbGVSZXBvcnRpbmdQZXJpb2QnIGlzIHByZXNlbnQuCiAgICAgICAgSW4gYWRkaXRpb24sIHRoZSBNblMgcHJvZHVjZXIgc2hhbGwgY3JlYXRlIG9uIGJlaGFsZiBvZiB0aGUgTW5TCiAgICAgICAgY29uc3VtZXIgYSBzdWJzY3JpcHRpb24sIHVzaW5nICdOdGZTdWJzY3JpcHRpb25Db250cm9sJywgZm9yIHRoZQogICAgICAgIG5vdGlmaWNhdGlvbiB0eXBlcyAnbm90aWZ5TU9JQ3JlYXRpb24nIGFuZCAnbm90aWZ5TU9JRGVsZXRpb24nIHJlbGF0ZWQKICAgICAgICB0byB0aGUgJ0ZpbGUnIGluc3RhbmNlcyB0aGF0IHdpbGwgYmUgcHJvZHVjZWQgbGF0ZXIuIEluIGNhc2UgYW4gZXhpc3RpbmcKICAgICAgICBzdWJzY3JpcHRpb24gZG9lcyBhbHJlYWR5IGluY2x1ZGUgdGhlICdGaWxlJyBpbnN0YW5jZXMgdG8gYmUgcHJvZHVjZWQsCiAgICAgICAgbm8gbmV3IHN1YnNjcmlwdGlvbiBzaGFsbCBiZSBjcmVhdGVkLiBUaGUKICAgICAgICAnbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcycgYXR0cmlidXRlIGluIHRoZSBjcmVhdGVkCiAgICAgICAgJ050ZlN1YnNjcmlwdGlvbkNvbnRyb2wnIGluc3RhbmNlIHNoYWxsIGJlIHNldCB0byB0aGUgdmFsdWUgb2YgdGhlCiAgICAgICAgJ25vdGlmaWNhdGlvblJlY2lwaWVudEFkZHJlc3MnIGluIHRoZSByZWxhdGVkICdQZXJmTWV0cmljSm9iJy4gVGhpcwogICAgICAgIGZlYXR1cmUgaXMgY2FsbGVkIGltcGxpY2l0IG5vdGlmaWNhdGlvbiBzdWJzY3JpcHRpb24sIGFzIG9wcG9zZWQgdG8gdGhlCiAgICAgICAgY2FzZSB3aGVyZSB0aGUgTW5TIGNvbnN1bWVyIGNyZWF0ZXMgdGhlIHN1YnNjcmlwdGlvbiAoZXhwbGljaXQKICAgICAgICBub3RpZmljYXRpb24gc3Vic2NyaXB0aW9uKS4gV2hlbiB0aGUgcmVsYXRlZCAnUGVyZk1ldHJpY0pvYicgaXMKICAgICAgICBkZWxldGVkLCB0aGUgJ050ZlN1YnNjcmlwdGlvbkNvbnRyb2wnIGluc3RhbmNlIGNyZWF0ZWQgZHVlIHRvIHRoZQogICAgICAgIHJlcXVlc3QgZm9yIGltcGxpY2l0IHN1YnNjcmlwdGlvbiBzaGFsbCBiZSBkZWxldGVkIGFzIHdlbGwuCgogICAgICAgIC0gV2hlbiBvbmx5IHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGFuZCBmaWxlTG9jYXRpb24gYXR0cmlidXRlcyBhcmUKICAgICAgICBwcmVzZW50LCB0aGUgTW5TIHByb2R1Y2VyIHNoYWxsIHN0b3JlIHRoZSBmaWxlcyBvbiBhIE1uUyBjb25zdW1lciwgdGhhdAogICAgICAgIGNhbiBiZSBhbnkgZW50aXR5IHN1Y2ggYXMgYSBmaWxlIHNlcnZlciwgYXQgdGhlIGxvY2F0aW9uIHNwZWNpZmllZCBieQogICAgICAgIGZpbGVMb2NhdGlvbi4gTm8gbm90aWZpY2F0aW9uIGlzIGVtaXR0ZWQgYnkgdGhlIE1uUyBwcm9kdWNlci4KCiAgICAgICAgLSBXaGVuIG9ubHkgdGhlIHN0cmVhbVRhcmdldCBhdHRyaWJ1dGUgaXMgcHJlc2VudCwgdGhlIE1uUyBwcm9kdWNlcgogICAgICAgIHNoYWxsIHN0cmVhbSB0aGUgZGF0YSB0byB0aGUgbG9jYXRpb24gc3BlY2lmaWVkIGJ5IHN0cmVhbVRhcmdldC4KCiAgICAgICAgRm9yIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2RzIHRoZSBmaWxlUmVwb3J0aW5nUGVyaW9kIGF0dHJpYnV0ZQogICAgICAgIHNwZWNpZmllcyB0aGUgdGltZSB3aW5kb3cgZHVyaW5nIHdoaWNoIGNvbGxlY3RlZCBtZWFzdXJlbWVudHMgYXJlCiAgICAgICAgc3RvcmVkIGludG8gdGhlIHNhbWUgZmlsZSBiZWZvcmUgdGhlIGZpbGUgaXMgY2xvc2VkIGFuZCBhIG5ldyBmaWxlIGlzCiAgICAgICAgb3BlbmVkLiI7CgogICAgICBjYXNlIGZpbGUtYmFzZWQtcmVwb3J0aW5nIHsKICAgICAgICBsZWFmIGZpbGVSZXBvcnRpbmdQZXJpb2QgewogICAgICAgICAgdHlwZSB1aW50MzIgewogICAgICAgICAgICByYW5nZSAxLi5tYXg7CiAgICAgICAgICB9CiAgICAgICAgICB1bml0cyBtaW51dGVzOwogICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgICBkZXNjcmlwdGlvbiAiRm9yIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2QgdGhpcyBpcyB0aGUgdGltZQogICAgICAgICAgICB3aW5kb3cgZHVyaW5nIHdoaWNoIGNvbGxlY3RlZCBtZWFzdXJlbWVudHMgYXJlIHN0b3JlZCBpbnRvIHRoZSBzYW1lCiAgICAgICAgICAgIGZpbGUgYmVmb3JlIHRoZSBmaWxlIGlzIGNsb3NlZCBhbmQgYSBuZXcgZmlsZSBpcyBvcGVuZWQuCiAgICAgICAgICAgIFRoZSB0aW1lLXBlcmlvZCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgdGhlIGdyYW51bGFyaXR5UGVyaW9kLgoKICAgICAgICAgICAgQXBwbGljYWJsZSB3aGVuIHRoZSBmaWxlLWJhc2VkIHJlcG9ydGluZyBtZXRob2QgaXMgc3VwcG9ydGVkLiI7CiAgICAgICAgfQogICAgICAgIGNob2ljZSByZXBvcnRpbmctdGFyZ2V0IHsKICAgICAgICAgIGNhc2UgZmlsZS10YXJnZXQgewogICAgICAgICAgICBsZWFmIGZpbGVMb2NhdGlvbiB7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nIDsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFwcGxpY2FibGUgYW5kIG11c3QgYmUgcHJlc2VudCB3aGVuIHRoZSBmaWxlLWJhc2VkCiAgICAgICAgICAgICAgcmVwb3J0aW5nIG1ldGhvZCBpcyBzdXBwb3J0ZWQsIGFuZCB0aGUgZmlsZXMgYXJlIHN0b3JlZCBvbiB0aGUgTW5TCiAgICAgICAgICAgICAgY29uc3VtZXIuIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY2FzZSBub3RpZmljYXRpb24tdGFyZ2V0IHsKICAgICAgICAgICAgbGVhZiBub3RpZmljYXRpb25SZWNpcGllbnRBZGRyZXNzIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNdXN0IGJlIHByZXNlbnQgd2hlbiB0aGUgbm90aWZpY2F0aW9uLWJhc2VkIHJlcG9ydGluZwogICAgICAgICAgICAgIG1ldGhvZCBpcyBzdXBwb3J0ZWQsIGFuZCB0aGUgdGhlIGZpbGVzIGFyZSBhdmFpbGFibGUgYXMKICAgICAgICAgICAgICBub3RpZmljYXRpb25zIGZvciB0aGUgTW5TIGNvbnN1bWVyIHRvIHN1YnNjcmliZSB0by4iOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgZGVzY3JpcHRpb24gIldoZW4gbmV0aWhlciBmaWxlTG9jYXRpb24gb3Igbm90aWZpY2F0aW9uUmVjaXBpZW50QWRkcmVzcwogICAgICAgICAgYXJlIHByZXNlbnQsIHRoZSBmaWxlcyBhcmUgc3RvcmVkIGFuZCBhdmFpbGFibGUgdG8gdGhlIE1uUyBjb25zdW1lcgogICAgICAgICAgaWYgdGhlIE1uUyBzdWJzY3JpYmVzIHRvIHRoZSBub3RpZnlGaWxlUmVhZHkgbm90aWZpY2F0aW9uLiI7CiAgICAgICAgfQogICAgICB9CgogICAgICBjYXNlIHN0cmVhbS1iYXNlZC1yZXBvcnRpbmcgewogICAgICAgIGxlYWYgc3RyZWFtVGFyZ2V0IHsKICAgICAgICAgIHR5cGUgc3RyaW5nOwogICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgICBkZXNjcmlwdGlvbiAiQXBwbGljYWJsZSB3aGVuIHN0cmVhbS1iYXNlZCByZXBvcnRpbmcgbWV0aG9kIGlzCiAgICAgICAgICAgIHN1cHBvcnRlZC4iOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KfQo= +ietf-geo-location urn:ietf:params:xml:ns:yang:ietf-geo-location \N [] 2022-02-11 bW9kdWxlIGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjppZXRmOnBhcmFtczp4bWw6bnM6eWFuZzppZXRmLWdlby1sb2NhdGlvbiI7CiAgICBwcmVmaXggZ2VvOwogICAgaW1wb3J0IGlldGYteWFuZy10eXBlcyB7CiAgICBwcmVmaXggeWFuZzsKICAgIHJlZmVyZW5jZSAiUkZDIDY5OTE6IENvbW1vbiBZQU5HIERhdGEgVHlwZXMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbgogICAgIklFVEYgTkVUTU9EIFdvcmtpbmcgR3JvdXAgKE5FVE1PRCkiOwogICAgY29udGFjdAogICAgIldHIFdlYjogICA8aHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy93Zy9uZXRtb2QvPgogICAgV0cgTGlzdDogIDxtYWlsdG86bmV0bW9kQGlldGYub3JnPgoKICAgIEVkaXRvcjogICBDaHJpc3RpYW4gSG9wcHMKICAgICAgICAgICAgICAgIDxtYWlsdG86Y2hvcHBzQGNob3Bwcy5vcmc+IjsKCiAgICBkZXNjcmlwdGlvbgogICAgIlRoaXMgbW9kdWxlIGRlZmluZXMgYSBncm91cGluZyBvZiBhIGNvbnRhaW5lciBvYmplY3QgZm9yCiAgICBzcGVjaWZ5aW5nIGEgbG9jYXRpb24gb24gb3IgYXJvdW5kIGFuIGFzdHJvbm9taWNhbCBvYmplY3QgKGUuZy4sCiAgICAnZWFydGgnKS4KCiAgICBUaGUga2V5IHdvcmRzICdNVVNUJywgJ01VU1QgTk9UJywgJ1JFUVVJUkVEJywgJ1NIQUxMJywgJ1NIQUxMCiAgICBOT1QnLCAnU0hPVUxEJywgJ1NIT1VMRCBOT1QnLCAnUkVDT01NRU5ERUQnLCAnTk9UIFJFQ09NTUVOREVEJywKICAgICdNQVknLCBhbmQgJ09QVElPTkFMJyBpbiB0aGlzIGRvY3VtZW50IGFyZSB0byBiZSBpbnRlcnByZXRlZCBhcwogICAgZGVzY3JpYmVkIGluIEJDUCAxNCAoUkZDIDIxMTkpIChSRkMgODE3NCkgd2hlbiwgYW5kIG9ubHkgd2hlbiwKICAgIHRoZXkgYXBwZWFyIGluIGFsbCBjYXBpdGFscywgYXMgc2hvd24gaGVyZS4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjIgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3JtcywKICAgIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywKICAgIGFuZCBzdWJqZWN0IHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlCiAgICBSZXZpc2VkIEJTRCBMaWNlbnNlIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUKICAgIElFVEYgVHJ1c3QncyBMZWdhbCBQcm92aXNpb25zIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cHM6Ly90cnVzdGVlLmlldGYub3JnL2xpY2Vuc2UtaW5mbykuCgogICAgVGhpcyB2ZXJzaW9uIG9mIHRoaXMgWUFORyBtb2R1bGUgaXMgcGFydCBvZiBSRkMgOTE3OQogICAgKGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL2luZm8vcmZjOTE3OSk7IHNlZSB0aGUgUkZDIGl0c2VsZgogICAgZm9yIGZ1bGwgbGVnYWwgbm90aWNlcy4iOwoKICAgIHJldmlzaW9uIDIwMjItMDItMTEgewogICAgZGVzY3JpcHRpb24KICAgICAgICAiSW5pdGlhbCBSZXZpc2lvbiI7CiAgICByZWZlcmVuY2UKICAgICAgICAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIGZlYXR1cmUgYWx0ZXJuYXRlLXN5c3RlbXMgewogICAgZGVzY3JpcHRpb24KICAgICAgICAiVGhpcyBmZWF0dXJlIG1lYW5zIHRoZSBkZXZpY2Ugc3VwcG9ydHMgc3BlY2lmeWluZyBsb2NhdGlvbnMKICAgICAgICB1c2luZyBhbHRlcm5hdGUgc3lzdGVtcyBmb3IgcmVmZXJlbmNlIGZyYW1lcy4iOwogICAgfQoKICAgIGdyb3VwaW5nIGdlby1sb2NhdGlvbiB7CiAgICBkZXNjcmlwdGlvbgogICAgICAgICJHcm91cGluZyB0byBpZGVudGlmeSBhIGxvY2F0aW9uIG9uIGFuIGFzdHJvbm9taWNhbCBvYmplY3QuIjsKCiAgICBjb250YWluZXIgZ2VvLWxvY2F0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICJBIGxvY2F0aW9uIG9uIGFuIGFzdHJvbm9taWNhbCBib2R5IChlLmcuLCAnZWFydGgnKQogICAgICAgIHNvbWV3aGVyZSBpbiBhIHVuaXZlcnNlLiI7CgogICAgICAgIGNvbnRhaW5lciByZWZlcmVuY2UtZnJhbWUgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgRnJhbWUgb2YgUmVmZXJlbmNlIGZvciB0aGUgbG9jYXRpb24gdmFsdWVzLiI7CgogICAgICAgIGxlYWYgYWx0ZXJuYXRlLXN5c3RlbSB7CiAgICAgICAgICAgIGlmLWZlYXR1cmUgImFsdGVybmF0ZS1zeXN0ZW1zIjsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgc3lzdGVtIGluIHdoaWNoIHRoZSBhc3Ryb25vbWljYWwgYm9keSBhbmQKICAgICAgICAgICAgZ2VvZGV0aWMtZGF0dW0gaXMgZGVmaW5lZC4gIE5vcm1hbGx5LCB0aGlzIHZhbHVlIGlzIG5vdAogICAgICAgICAgICBwcmVzZW50IGFuZCB0aGUgc3lzdGVtIGlzIHRoZSBuYXR1cmFsIHVuaXZlcnNlOyBob3dldmVyLAogICAgICAgICAgICB3aGVuIHByZXNlbnQsIHRoaXMgdmFsdWUgYWxsb3dzIGZvciBzcGVjaWZ5aW5nIGFsdGVybmF0ZQogICAgICAgICAgICBzeXN0ZW1zIChlLmcuLCB2aXJ0dWFsIHJlYWxpdGllcykuICBBbiBhbHRlcm5hdGUtc3lzdGVtCiAgICAgICAgICAgIG1vZGlmaWVzIHRoZSBkZWZpbml0aW9uIChidXQgbm90IHRoZSB0eXBlKSBvZiB0aGUgb3RoZXIKICAgICAgICAgICAgdmFsdWVzIGluIHRoZSByZWZlcmVuY2UgZnJhbWUuIjsKICAgICAgICB9CiAgICAgICAgbGVhZiBhc3Ryb25vbWljYWwtYm9keSB7CiAgICAgICAgICAgIHR5cGUgc3RyaW5nIHsKICAgICAgICAgICAgcGF0dGVybiAnWyAtQFxbLVxeXy1+XSonOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlZmF1bHQgImVhcnRoIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIkFuIGFzdHJvbm9taWNhbCBib2R5IGFzIG5hbWVkIGJ5IHRoZSBJbnRlcm5hdGlvbmFsCiAgICAgICAgICAgIEFzdHJvbm9taWNhbCBVbmlvbiAoSUFVKSBvciBhY2NvcmRpbmcgdG8gdGhlIGFsdGVybmF0ZQogICAgICAgICAgICBzeXN0ZW0gaWYgc3BlY2lmaWVkLiAgRXhhbXBsZXMgaW5jbHVkZSAnc3VuJyAob3VyIHN0YXIpLAogICAgICAgICAgICAnZWFydGgnIChvdXIgcGxhbmV0KSwgJ21vb24nIChvdXIgbW9vbiksICdlbmNlbGFkdXMnIChhCiAgICAgICAgICAgIG1vb24gb2YgU2F0dXJuKSwgJ2NlcmVzJyAoYW4gYXN0ZXJvaWQpLCBhbmQKICAgICAgICAgICAgJzY3cC9jaHVyeXVtb3YtZ2VyYXNpbWVua28gKGEgY29tZXQpLiAgVGhlIEFTQ0lJIHZhbHVlCiAgICAgICAgICAgIFNIT1VMRCBoYXZlIHVwcGVyY2FzZSBjb252ZXJ0ZWQgdG8gbG93ZXJjYXNlIGFuZCBub3QKICAgICAgICAgICAgaW5jbHVkZSBjb250cm9sIGNoYXJhY3RlcnMgKGkuZS4sIHZhbHVlcyAzMi4uNjQsIGFuZAogICAgICAgICAgICA5MS4uMTI2KS4gIEFueSBwcmVjZWRpbmcgJ3RoZScgaW4gdGhlIG5hbWUgU0hPVUxEIE5PVCBiZQogICAgICAgICAgICBpbmNsdWRlZC4iOwogICAgICAgICAgICByZWZlcmVuY2UKICAgICAgICAgICAgImh0dHBzOi8vd3d3LmlhdS5vcmcvIjsKICAgICAgICB9CiAgICAgICAgY29udGFpbmVyIGdlb2RldGljLXN5c3RlbSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgZ2VvZGV0aWMgc3lzdGVtIG9mIHRoZSBsb2NhdGlvbiBkYXRhLiI7CiAgICAgICAgICAgIGxlYWYgZ2VvZGV0aWMtZGF0dW0gewogICAgICAgICAgICB0eXBlIHN0cmluZyB7CiAgICAgICAgICAgICAgICBwYXR0ZXJuICdbIC1AXFstXF5fLX5dKic7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJBIGdlb2RldGljLWRhdHVtIGRlZmluaW5nIHRoZSBtZWFuaW5nIG9mIGxhdGl0dWRlLAogICAgICAgICAgICAgICAgbG9uZ2l0dWRlLCBhbmQgaGVpZ2h0LiAgVGhlIGRlZmF1bHQgd2hlbiB0aGUKICAgICAgICAgICAgICAgIGFzdHJvbm9taWNhbCBib2R5IGlzICdlYXJ0aCcgaXMgJ3dncy04NCcsIHdoaWNoIGlzCiAgICAgICAgICAgICAgICB1c2VkIGJ5IHRoZSBHbG9iYWwgUG9zaXRpb25pbmcgU3lzdGVtIChHUFMpLiAgVGhlCiAgICAgICAgICAgICAgICBBU0NJSSB2YWx1ZSBTSE9VTEQgaGF2ZSB1cHBlcmNhc2UgY29udmVydGVkIHRvCiAgICAgICAgICAgICAgICBsb3dlcmNhc2UgYW5kIG5vdCBpbmNsdWRlIGNvbnRyb2wgY2hhcmFjdGVycwogICAgICAgICAgICAgICAgKGkuZS4sIHZhbHVlcyAzMi4uNjQsIGFuZCA5MS4uMTI2KS4gIFRoZSBJQU5BIHJlZ2lzdHJ5CiAgICAgICAgICAgICAgICBmdXJ0aGVyIHJlc3RyaWN0cyB0aGUgdmFsdWUgYnkgY29udmVydGluZyBhbGwgc3BhY2VzCiAgICAgICAgICAgICAgICAoJyAnKSB0byBkYXNoZXMgKCctJykuCiAgICAgICAgICAgICAgICBUaGUgc3BlY2lmaWNhdGlvbiBmb3IgdGhlIGdlb2RldGljLWRhdHVtIGluZGljYXRlcwogICAgICAgICAgICAgICAgaG93IGFjY3VyYXRlbHkgaXQgbW9kZWxzIHRoZSBhc3Ryb25vbWljYWwgYm9keSBpbgogICAgICAgICAgICAgICAgcXVlc3Rpb24sIGJvdGggZm9yIHRoZSAnaG9yaXpvbnRhbCcKICAgICAgICAgICAgICAgIGxhdGl0dWRlL2xvbmdpdHVkZSBjb29yZGluYXRlcyBhbmQgZm9yIGhlaWdodAogICAgICAgICAgICAgICAgY29vcmRpbmF0ZXMuIjsKICAgICAgICAgICAgcmVmZXJlbmNlCiAgICAgICAgICAgICAgICAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMsCiAgICAgICAgICAgICAgICBTZWN0aW9uIDYuMSI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVhZiBjb29yZC1hY2N1cmFjeSB7CiAgICAgICAgICAgIHR5cGUgZGVjaW1hbDY0IHsKICAgICAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyA2OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGFjY3VyYWN5IG9mIHRoZSBsYXRpdHVkZS9sb25naXR1ZGUgcGFpciBmb3IKICAgICAgICAgICAgICAgIGVsbGlwc29pZGFsIGNvb3JkaW5hdGVzLCBvciB0aGUgWCwgWSwgYW5kIFogY29tcG9uZW50cwogICAgICAgICAgICAgICAgZm9yIENhcnRlc2lhbiBjb29yZGluYXRlcy4gIFdoZW4gY29vcmQtYWNjdXJhY3kgaXMKICAgICAgICAgICAgICAgIHNwZWNpZmllZCwgaXQgaW5kaWNhdGVzIGhvdyBwcmVjaXNlbHkgdGhlIGNvb3JkaW5hdGVzCiAgICAgICAgICAgICAgICBpbiB0aGUgYXNzb2NpYXRlZCBsaXN0IG9mIGxvY2F0aW9ucyBoYXZlIGJlZW4KICAgICAgICAgICAgICAgIGRldGVybWluZWQgd2l0aCByZXNwZWN0IHRvIHRoZSBjb29yZGluYXRlIHN5c3RlbQogICAgICAgICAgICAgICAgZGVmaW5lZCBieSB0aGUgZ2VvZGV0aWMtZGF0dW0uICBGb3IgZXhhbXBsZSwgdGhlcmUKICAgICAgICAgICAgICAgIG1pZ2h0IGJlIHVuY2VydGFpbnR5IGR1ZSB0byBtZWFzdXJlbWVudCBlcnJvciBpZiBhbgogICAgICAgICAgICAgICAgZXhwZXJpbWVudGFsIG1lYXN1cmVtZW50IHdhcyBtYWRlIHRvIGRldGVybWluZSBlYWNoCiAgICAgICAgICAgICAgICBsb2NhdGlvbi4iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlYWYgaGVpZ2h0LWFjY3VyYWN5IHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGFjY3VyYWN5IG9mIHRoZSBoZWlnaHQgdmFsdWUgZm9yIGVsbGlwc29pZGFsCiAgICAgICAgICAgICAgICBjb29yZGluYXRlczsgdGhpcyB2YWx1ZSBpcyBub3QgdXNlZCB3aXRoIENhcnRlc2lhbgogICAgICAgICAgICAgICAgY29vcmRpbmF0ZXMuICBXaGVuIGhlaWdodC1hY2N1cmFjeSBpcyBzcGVjaWZpZWQsIGl0CiAgICAgICAgICAgICAgICBpbmRpY2F0ZXMgaG93IHByZWNpc2VseSB0aGUgaGVpZ2h0cyBpbiB0aGUKICAgICAgICAgICAgICAgIGFzc29jaWF0ZWQgbGlzdCBvZiBsb2NhdGlvbnMgaGF2ZSBiZWVuIGRldGVybWluZWQKICAgICAgICAgICAgICAgIHdpdGggcmVzcGVjdCB0byB0aGUgY29vcmRpbmF0ZSBzeXN0ZW0gZGVmaW5lZCBieSB0aGUKICAgICAgICAgICAgICAgIGdlb2RldGljLWRhdHVtLiAgRm9yIGV4YW1wbGUsIHRoZXJlIG1pZ2h0IGJlCiAgICAgICAgICAgICAgICB1bmNlcnRhaW50eSBkdWUgdG8gbWVhc3VyZW1lbnQgZXJyb3IgaWYgYW4KICAgICAgICAgICAgICAgIGV4cGVyaW1lbnRhbCBtZWFzdXJlbWVudCB3YXMgbWFkZSB0byBkZXRlcm1pbmUgZWFjaAogICAgICAgICAgICAgICAgbG9jYXRpb24uIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY2hvaWNlIGxvY2F0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhlIGxvY2F0aW9uIGRhdGEgZWl0aGVyIGluIGxhdGl0dWRlL2xvbmdpdHVkZSBvcgogICAgICAgICAgICBDYXJ0ZXNpYW4gdmFsdWVzIjsKICAgICAgICBjYXNlIGVsbGlwc29pZCB7CiAgICAgICAgICAgIGxlYWYgbGF0aXR1ZGUgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgImRlY2ltYWwgZGVncmVlcyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGxhdGl0dWRlIHZhbHVlIG9uIHRoZSBhc3Ryb25vbWljYWwgYm9keS4gIFRoZQogICAgICAgICAgICAgICAgZGVmaW5pdGlvbiBhbmQgcHJlY2lzaW9uIG9mIHRoaXMgbWVhc3VyZW1lbnQgaXMKICAgICAgICAgICAgICAgIGluZGljYXRlZCBieSB0aGUgcmVmZXJlbmNlLWZyYW1lLiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVhZiBsb25naXR1ZGUgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgImRlY2ltYWwgZGVncmVlcyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiVGhlIGxvbmdpdHVkZSB2YWx1ZSBvbiB0aGUgYXN0cm9ub21pY2FsIGJvZHkuICBUaGUKICAgICAgICAgICAgICAgIGRlZmluaXRpb24gYW5kIHByZWNpc2lvbiBvZiB0aGlzIG1lYXN1cmVtZW50IGlzCiAgICAgICAgICAgICAgICBpbmRpY2F0ZWQgYnkgdGhlIHJlZmVyZW5jZS1mcmFtZS4iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlYWYgaGVpZ2h0IHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyI7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICAgICAiSGVpZ2h0IGZyb20gYSByZWZlcmVuY2UgMCB2YWx1ZS4gIFRoZSBwcmVjaXNpb24gYW5kCiAgICAgICAgICAgICAgICAnMCcgdmFsdWUgaXMgZGVmaW5lZCBieSB0aGUgcmVmZXJlbmNlLWZyYW1lLiI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY2FzZSBjYXJ0ZXNpYW4gewogICAgICAgICAgICBsZWFmIHggewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWCB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZWFmIHkgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWSB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZWFmIHogewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgNjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgICAgICJUaGUgWiB2YWx1ZSBhcyBkZWZpbmVkIGJ5IHRoZSByZWZlcmVuY2UtZnJhbWUuIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29udGFpbmVyIHZlbG9jaXR5IHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiSWYgdGhlIG9iamVjdCBpcyBpbiBtb3Rpb24sIHRoZSB2ZWxvY2l0eSB2ZWN0b3IgZGVzY3JpYmVzCiAgICAgICAgICAgIHRoaXMgbW90aW9uIGF0IHRoZSB0aW1lIGdpdmVuIGJ5IHRoZSB0aW1lc3RhbXAuICBGb3IgYQogICAgICAgICAgICBmb3JtdWxhIHRvIGNvbnZlcnQgdGhlc2UgdmFsdWVzIHRvIHNwZWVkIGFuZCBoZWFkaW5nLCBzZWUKICAgICAgICAgICAgUkZDIDkxNzkuIjsKICAgICAgICByZWZlcmVuY2UKICAgICAgICAgICAgIlJGQyA5MTc5OiBBIFlBTkcgR3JvdXBpbmcgZm9yIEdlb2dyYXBoaWMgTG9jYXRpb25zIjsKCiAgICAgICAgbGVhZiB2LW5vcnRoIHsKICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjQgewogICAgICAgICAgICBmcmFjdGlvbi1kaWdpdHMgMTI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdW5pdHMgIm1ldGVycyBwZXIgc2Vjb25kIjsKICAgICAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgInYtbm9ydGggaXMgdGhlIHJhdGUgb2YgY2hhbmdlIChpLmUuLCBzcGVlZCkgdG93YXJkcwogICAgICAgICAgICB0cnVlIG5vcnRoIGFzIGRlZmluZWQgYnkgdGhlIGdlb2RldGljLXN5c3RlbS4iOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB2LWVhc3QgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyAxMjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIHBlciBzZWNvbmQiOwogICAgICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAidi1lYXN0IGlzIHRoZSByYXRlIG9mIGNoYW5nZSAoaS5lLiwgc3BlZWQpIHBlcnBlbmRpY3VsYXIKICAgICAgICAgICAgdG8gdGhlIHJpZ2h0IG9mIHRydWUgbm9ydGggYXMgZGVmaW5lZCBieQogICAgICAgICAgICB0aGUgZ2VvZGV0aWMtc3lzdGVtLiI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHYtdXAgewogICAgICAgICAgICB0eXBlIGRlY2ltYWw2NCB7CiAgICAgICAgICAgIGZyYWN0aW9uLWRpZ2l0cyAxMjsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bml0cyAibWV0ZXJzIHBlciBzZWNvbmQiOwogICAgICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAidi11cCBpcyB0aGUgcmF0ZSBvZiBjaGFuZ2UgKGkuZS4sIHNwZWVkKSBhd2F5IGZyb20gdGhlCiAgICAgICAgICAgIGNlbnRlciBvZiBtYXNzLiI7CiAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZWFmIHRpbWVzdGFtcCB7CiAgICAgICAgdHlwZSB5YW5nOmRhdGUtYW5kLXRpbWU7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIlJlZmVyZW5jZSB0aW1lIHdoZW4gbG9jYXRpb24gd2FzIHJlY29yZGVkLiI7CiAgICAgICAgfQogICAgICAgIGxlYWYgdmFsaWQtdW50aWwgewogICAgICAgIHR5cGUgeWFuZzpkYXRlLWFuZC10aW1lOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGUgdGltZXN0YW1wIGZvciB3aGljaCB0aGlzIGdlby1sb2NhdGlvbiBpcyB2YWxpZCB1bnRpbC4KICAgICAgICAgICAgSWYgdW5zcGVjaWZpZWQsIHRoZSBnZW8tbG9jYXRpb24gaGFzIG5vIHNwZWNpZmljCiAgICAgICAgICAgIGV4cGlyYXRpb24gdGltZS4iOwogICAgICAgIH0KICAgIH0KICAgIH0KfQo= +ietf-inet-types urn:ietf:params:xml:ns:yang:ietf-inet-types \N [] 2013-07-15 bW9kdWxlIGlldGYtaW5ldC10eXBlcyB7CgogIG5hbWVzcGFjZSAidXJuOmlldGY6cGFyYW1zOnhtbDpuczp5YW5nOmlldGYtaW5ldC10eXBlcyI7CiAgcHJlZml4ICJpbmV0IjsKCiAgb3JnYW5pemF0aW9uCiAgICJJRVRGIE5FVE1PRCAoTkVUQ09ORiBEYXRhIE1vZGVsaW5nIExhbmd1YWdlKSBXb3JraW5nIEdyb3VwIjsKCiAgY29udGFjdAogICAiV0cgV2ViOiAgIDxodHRwOi8vdG9vbHMuaWV0Zi5vcmcvd2cvbmV0bW9kLz4KICAgIFdHIExpc3Q6ICA8bWFpbHRvOm5ldG1vZEBpZXRmLm9yZz4KCiAgICBXRyBDaGFpcjogRGF2aWQgS2Vzc2VucwogICAgICAgICAgICAgIDxtYWlsdG86ZGF2aWQua2Vzc2Vuc0Buc24uY29tPgoKICAgIFdHIENoYWlyOiBKdWVyZ2VuIFNjaG9lbndhZWxkZXIKICAgICAgICAgICAgICA8bWFpbHRvOmouc2Nob2Vud2FlbGRlckBqYWNvYnMtdW5pdmVyc2l0eS5kZT4KCiAgICBFZGl0b3I6ICAgSnVlcmdlbiBTY2hvZW53YWVsZGVyCiAgICAgICAgICAgICAgPG1haWx0bzpqLnNjaG9lbndhZWxkZXJAamFjb2JzLXVuaXZlcnNpdHkuZGU+IjsKCiAgZGVzY3JpcHRpb24KICAgIlRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiBnZW5lcmFsbHkgdXNlZnVsIGRlcml2ZWQKICAgIFlBTkcgZGF0YSB0eXBlcyBmb3IgSW50ZXJuZXQgYWRkcmVzc2VzIGFuZCByZWxhdGVkIHRoaW5ncy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTMgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvcgogICAgd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywgYW5kIHN1YmplY3QKICAgIHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlIFNpbXBsaWZpZWQgQlNEIExpY2Vuc2UKICAgIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUgSUVURiBUcnVzdCdzIExlZ2FsIFByb3Zpc2lvbnMKICAgIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cDovL3RydXN0ZWUuaWV0Zi5vcmcvbGljZW5zZS1pbmZvKS4KCiAgICBUaGlzIHZlcnNpb24gb2YgdGhpcyBZQU5HIG1vZHVsZSBpcyBwYXJ0IG9mIFJGQyA2OTkxOyBzZWUKICAgIHRoZSBSRkMgaXRzZWxmIGZvciBmdWxsIGxlZ2FsIG5vdGljZXMuIjsKCiAgcmV2aXNpb24gMjAxMy0wNy0xNSB7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHJldmlzaW9uIGFkZHMgdGhlIGZvbGxvd2luZyBuZXcgZGF0YSB0eXBlczoKICAgICAgLSBpcC1hZGRyZXNzLW5vLXpvbmUKICAgICAgLSBpcHY0LWFkZHJlc3Mtbm8tem9uZQogICAgICAtIGlwdjYtYWRkcmVzcy1uby16b25lIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjk5MTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICByZXZpc2lvbiAyMDEwLTA5LTI0IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgIkluaXRpYWwgcmV2aXNpb24uIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjAyMTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgdHlwZXMgcmVsYXRlZCB0byBwcm90b2NvbCBmaWVsZHMgKioqLwoKICB0eXBlZGVmIGlwLXZlcnNpb24gewogICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgIGVudW0gdW5rbm93biB7CiAgICAgICAgdmFsdWUgIjAiOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICJBbiB1bmtub3duIG9yIHVuc3BlY2lmaWVkIHZlcnNpb24gb2YgdGhlIEludGVybmV0CiAgICAgICAgICBwcm90b2NvbC4iOwogICAgICB9CiAgICAgIGVudW0gaXB2NCB7CiAgICAgICAgdmFsdWUgIjEiOwogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICJUaGUgSVB2NCBwcm90b2NvbCBhcyBkZWZpbmVkIGluIFJGQyA3OTEuIjsKICAgICAgfQogICAgICBlbnVtIGlwdjYgewogICAgICAgIHZhbHVlICIyIjsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAiVGhlIElQdjYgcHJvdG9jb2wgYXMgZGVmaW5lZCBpbiBSRkMgMjQ2MC4iOwogICAgICB9CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHZhbHVlIHJlcHJlc2VudHMgdGhlIHZlcnNpb24gb2YgdGhlIElQIHByb3RvY29sLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIEluZXRWZXJzaW9uIHRleHR1YWwgY29udmVudGlvbiBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgIDc5MTogSW50ZXJuZXQgUHJvdG9jb2wKICAgICAgUkZDIDI0NjA6IEludGVybmV0IFByb3RvY29sLCBWZXJzaW9uIDYgKElQdjYpIFNwZWNpZmljYXRpb24KICAgICAgUkZDIDQwMDE6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIEludGVybmV0IE5ldHdvcmsgQWRkcmVzc2VzIjsKICB9CgogIHR5cGVkZWYgZHNjcCB7CiAgICB0eXBlIHVpbnQ4IHsKICAgICAgcmFuZ2UgIjAuLjYzIjsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBkc2NwIHR5cGUgcmVwcmVzZW50cyBhIERpZmZlcmVudGlhdGVkIFNlcnZpY2VzIENvZGUgUG9pbnQKICAgICAgdGhhdCBtYXkgYmUgdXNlZCBmb3IgbWFya2luZyBwYWNrZXRzIGluIGEgdHJhZmZpYyBzdHJlYW0uCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBEc2NwIHRleHR1YWwgY29udmVudGlvbiBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzI4OTogTWFuYWdlbWVudCBJbmZvcm1hdGlvbiBCYXNlIGZvciB0aGUgRGlmZmVyZW50aWF0ZWQKICAgICAgICAgICAgICAgIFNlcnZpY2VzIEFyY2hpdGVjdHVyZQogICAgICBSRkMgMjQ3NDogRGVmaW5pdGlvbiBvZiB0aGUgRGlmZmVyZW50aWF0ZWQgU2VydmljZXMgRmllbGQKICAgICAgICAgICAgICAgIChEUyBGaWVsZCkgaW4gdGhlIElQdjQgYW5kIElQdjYgSGVhZGVycwogICAgICBSRkMgMjc4MDogSUFOQSBBbGxvY2F0aW9uIEd1aWRlbGluZXMgRm9yIFZhbHVlcyBJbgogICAgICAgICAgICAgICAgdGhlIEludGVybmV0IFByb3RvY29sIGFuZCBSZWxhdGVkIEhlYWRlcnMiOwogIH0KCiAgdHlwZWRlZiBpcHY2LWZsb3ctbGFiZWwgewogICAgdHlwZSB1aW50MzIgewogICAgICByYW5nZSAiMC4uMTA0ODU3NSI7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXB2Ni1mbG93LWxhYmVsIHR5cGUgcmVwcmVzZW50cyB0aGUgZmxvdyBpZGVudGlmaWVyIG9yIEZsb3cKICAgICAgTGFiZWwgaW4gYW4gSVB2NiBwYWNrZXQgaGVhZGVyIHRoYXQgbWF5IGJlIHVzZWQgdG8KICAgICAgZGlzY3JpbWluYXRlIHRyYWZmaWMgZmxvd3MuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgSVB2NkZsb3dMYWJlbCB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDM1OTU6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIElQdjYgRmxvdyBMYWJlbAogICAgICBSRkMgMjQ2MDogSW50ZXJuZXQgUHJvdG9jb2wsIFZlcnNpb24gNiAoSVB2NikgU3BlY2lmaWNhdGlvbiI7CiAgfQoKICB0eXBlZGVmIHBvcnQtbnVtYmVyIHsKICAgIHR5cGUgdWludDE2IHsKICAgICAgcmFuZ2UgIjAuLjY1NTM1IjsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBwb3J0LW51bWJlciB0eXBlIHJlcHJlc2VudHMgYSAxNi1iaXQgcG9ydCBudW1iZXIgb2YgYW4KICAgICAgSW50ZXJuZXQgdHJhbnNwb3J0LWxheWVyIHByb3RvY29sIHN1Y2ggYXMgVURQLCBUQ1AsIERDQ1AsIG9yCiAgICAgIFNDVFAuICBQb3J0IG51bWJlcnMgYXJlIGFzc2lnbmVkIGJ5IElBTkEuICBBIGN1cnJlbnQgbGlzdCBvZgogICAgICBhbGwgYXNzaWdubWVudHMgaXMgYXZhaWxhYmxlIGZyb20gPGh0dHA6Ly93d3cuaWFuYS5vcmcvPi4KCiAgICAgIE5vdGUgdGhhdCB0aGUgcG9ydCBudW1iZXIgdmFsdWUgemVybyBpcyByZXNlcnZlZCBieSBJQU5BLiAgSW4KICAgICAgc2l0dWF0aW9ucyB3aGVyZSB0aGUgdmFsdWUgemVybyBkb2VzIG5vdCBtYWtlIHNlbnNlLCBpdCBjYW4KICAgICAgYmUgZXhjbHVkZWQgYnkgc3VidHlwaW5nIHRoZSBwb3J0LW51bWJlciB0eXBlLgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgSW5ldFBvcnROdW1iZXIgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAgNzY4OiBVc2VyIERhdGFncmFtIFByb3RvY29sCiAgICAgIFJGQyAgNzkzOiBUcmFuc21pc3Npb24gQ29udHJvbCBQcm90b2NvbAogICAgICBSRkMgNDk2MDogU3RyZWFtIENvbnRyb2wgVHJhbnNtaXNzaW9uIFByb3RvY29sCiAgICAgIFJGQyA0MzQwOiBEYXRhZ3JhbSBDb25nZXN0aW9uIENvbnRyb2wgUHJvdG9jb2wgKERDQ1ApCiAgICAgIFJGQyA0MDAxOiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBJbnRlcm5ldCBOZXR3b3JrIEFkZHJlc3NlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgdHlwZXMgcmVsYXRlZCB0byBhdXRvbm9tb3VzIHN5c3RlbXMgKioqLwoKICB0eXBlZGVmIGFzLW51bWJlciB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBhcy1udW1iZXIgdHlwZSByZXByZXNlbnRzIGF1dG9ub21vdXMgc3lzdGVtIG51bWJlcnMKICAgICAgd2hpY2ggaWRlbnRpZnkgYW4gQXV0b25vbW91cyBTeXN0ZW0gKEFTKS4gIEFuIEFTIGlzIGEgc2V0CiAgICAgIG9mIHJvdXRlcnMgdW5kZXIgYSBzaW5nbGUgdGVjaG5pY2FsIGFkbWluaXN0cmF0aW9uLCB1c2luZwogICAgICBhbiBpbnRlcmlvciBnYXRld2F5IHByb3RvY29sIGFuZCBjb21tb24gbWV0cmljcyB0byByb3V0ZQogICAgICBwYWNrZXRzIHdpdGhpbiB0aGUgQVMsIGFuZCB1c2luZyBhbiBleHRlcmlvciBnYXRld2F5CiAgICAgIHByb3RvY29sIHRvIHJvdXRlIHBhY2tldHMgdG8gb3RoZXIgQVNlcy4gIElBTkEgbWFpbnRhaW5zCiAgICAgIHRoZSBBUyBudW1iZXIgc3BhY2UgYW5kIGhhcyBkZWxlZ2F0ZWQgbGFyZ2UgcGFydHMgdG8gdGhlCiAgICAgIHJlZ2lvbmFsIHJlZ2lzdHJpZXMuCgogICAgICBBdXRvbm9tb3VzIHN5c3RlbSBudW1iZXJzIHdlcmUgb3JpZ2luYWxseSBsaW1pdGVkIHRvIDE2CiAgICAgIGJpdHMuICBCR1AgZXh0ZW5zaW9ucyBoYXZlIGVubGFyZ2VkIHRoZSBhdXRvbm9tb3VzIHN5c3RlbQogICAgICBudW1iZXIgc3BhY2UgdG8gMzIgYml0cy4gIFRoaXMgdHlwZSB0aGVyZWZvcmUgdXNlcyBhbiB1aW50MzIKICAgICAgYmFzZSB0eXBlIHdpdGhvdXQgYSByYW5nZSByZXN0cmljdGlvbiBpbiBvcmRlciB0byBzdXBwb3J0CiAgICAgIGEgbGFyZ2VyIGF1dG9ub21vdXMgc3lzdGVtIG51bWJlciBzcGFjZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBJbmV0QXV0b25vbW91c1N5c3RlbU51bWJlciB0ZXh0dWFsIGNvbnZlbnRpb24gb2YKICAgICAgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDE5MzA6IEd1aWRlbGluZXMgZm9yIGNyZWF0aW9uLCBzZWxlY3Rpb24sIGFuZCByZWdpc3RyYXRpb24KICAgICAgICAgICAgICAgIG9mIGFuIEF1dG9ub21vdXMgU3lzdGVtIChBUykKICAgICAgUkZDIDQyNzE6IEEgQm9yZGVyIEdhdGV3YXkgUHJvdG9jb2wgNCAoQkdQLTQpCiAgICAgIFJGQyA0MDAxOiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBJbnRlcm5ldCBOZXR3b3JrIEFkZHJlc3NlcwogICAgICBSRkMgNjc5MzogQkdQIFN1cHBvcnQgZm9yIEZvdXItT2N0ZXQgQXV0b25vbW91cyBTeXN0ZW0gKEFTKQogICAgICAgICAgICAgICAgTnVtYmVyIFNwYWNlIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiB0eXBlcyByZWxhdGVkIHRvIElQIGFkZHJlc3NlcyBhbmQgaG9zdG5hbWVzICoqKi8KCiAgdHlwZWRlZiBpcC1hZGRyZXNzIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzOwogICAgICB0eXBlIGluZXQ6aXB2Ni1hZGRyZXNzOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGlwLWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQIGFkZHJlc3MgYW5kIGlzIElQCiAgICAgIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb24KICAgICAgaW1wbGllcyB0aGUgSVAgdmVyc2lvbi4gIFRoaXMgdHlwZSBzdXBwb3J0cyBzY29wZWQgYWRkcmVzc2VzCiAgICAgIGJ5IGFsbG93aW5nIHpvbmUgaWRlbnRpZmllcnMgaW4gdGhlIGFkZHJlc3MgZm9ybWF0LiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDQwMDc6IElQdjYgU2NvcGVkIEFkZHJlc3MgQXJjaGl0ZWN0dXJlIjsKICB9CgogIHR5cGVkZWYgaXB2NC1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybgogICAgICAgICcoKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSlcLil7M30nCiAgICAgICsgICcoWzAtOV18WzEtOV1bMC05XXwxWzAtOV1bMC05XXwyWzAtNF1bMC05XXwyNVswLTVdKScKICAgICAgKyAnKCVbXHB7Tn1ccHtMfV0rKT8nOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIlRoZSBpcHY0LWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQdjQgYWRkcmVzcyBpbgogICAgICAgZG90dGVkLXF1YWQgbm90YXRpb24uICBUaGUgSVB2NCBhZGRyZXNzIG1heSBpbmNsdWRlIGEgem9uZQogICAgICAgaW5kZXgsIHNlcGFyYXRlZCBieSBhICUgc2lnbi4KCiAgICAgICBUaGUgem9uZSBpbmRleCBpcyB1c2VkIHRvIGRpc2FtYmlndWF0ZSBpZGVudGljYWwgYWRkcmVzcwogICAgICAgdmFsdWVzLiAgRm9yIGxpbmstbG9jYWwgYWRkcmVzc2VzLCB0aGUgem9uZSBpbmRleCB3aWxsCiAgICAgICB0eXBpY2FsbHkgYmUgdGhlIGludGVyZmFjZSBpbmRleCBudW1iZXIgb3IgdGhlIG5hbWUgb2YgYW4KICAgICAgIGludGVyZmFjZS4gIElmIHRoZSB6b25lIGluZGV4IGlzIG5vdCBwcmVzZW50LCB0aGUgZGVmYXVsdAogICAgICAgem9uZSBvZiB0aGUgZGV2aWNlIHdpbGwgYmUgdXNlZC4KCiAgICAgICBUaGUgY2Fub25pY2FsIGZvcm1hdCBmb3IgdGhlIHpvbmUgaW5kZXggaXMgdGhlIG51bWVyaWNhbAogICAgICAgZm9ybWF0IjsKICB9CgogIHR5cGVkZWYgaXB2Ni1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKCg6fFswLTlhLWZBLUZdezAsNH0pOikoWzAtOWEtZkEtRl17MCw0fTopezAsNX0nCiAgICAgICAgICAgICsgJygoKFswLTlhLWZBLUZdezAsNH06KT8oOnxbMC05YS1mQS1GXXswLDR9KSl8JwogICAgICAgICAgICArICcoKCgyNVswLTVdfDJbMC00XVswLTldfFswMV0/WzAtOV0/WzAtOV0pXC4pezN9JwogICAgICAgICAgICArICcoMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdP1swLTldP1swLTldKSkpJwogICAgICAgICAgICArICcoJVtccHtOfVxwe0x9XSspPyc7CiAgICAgIHBhdHRlcm4gJygoW146XSs6KXs2fSgoW146XSs6W146XSspfCguKlwuLiopKSl8JwogICAgICAgICAgICArICcoKChbXjpdKzopKlteOl0rKT86OigoW146XSs6KSpbXjpdKyk/KScKICAgICAgICAgICAgKyAnKCUuKyk/JzsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBpcHY2LWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElQdjYgYWRkcmVzcyBpbiBmdWxsLAogICAgICBtaXhlZCwgc2hvcnRlbmVkLCBhbmQgc2hvcnRlbmVkLW1peGVkIG5vdGF0aW9uLiAgVGhlIElQdjYKICAgICAgYWRkcmVzcyBtYXkgaW5jbHVkZSBhIHpvbmUgaW5kZXgsIHNlcGFyYXRlZCBieSBhICUgc2lnbi4KCiAgICAgIFRoZSB6b25lIGluZGV4IGlzIHVzZWQgdG8gZGlzYW1iaWd1YXRlIGlkZW50aWNhbCBhZGRyZXNzCiAgICAgIHZhbHVlcy4gIEZvciBsaW5rLWxvY2FsIGFkZHJlc3NlcywgdGhlIHpvbmUgaW5kZXggd2lsbAogICAgICB0eXBpY2FsbHkgYmUgdGhlIGludGVyZmFjZSBpbmRleCBudW1iZXIgb3IgdGhlIG5hbWUgb2YgYW4KICAgICAgaW50ZXJmYWNlLiAgSWYgdGhlIHpvbmUgaW5kZXggaXMgbm90IHByZXNlbnQsIHRoZSBkZWZhdWx0CiAgICAgIHpvbmUgb2YgdGhlIGRldmljZSB3aWxsIGJlIHVzZWQuCgogICAgICBUaGUgY2Fub25pY2FsIGZvcm1hdCBvZiBJUHY2IGFkZHJlc3NlcyB1c2VzIHRoZSB0ZXh0dWFsCiAgICAgIHJlcHJlc2VudGF0aW9uIGRlZmluZWQgaW4gU2VjdGlvbiA0IG9mIFJGQyA1OTUyLiAgVGhlCiAgICAgIGNhbm9uaWNhbCBmb3JtYXQgZm9yIHRoZSB6b25lIGluZGV4IGlzIHRoZSBudW1lcmljYWwKICAgICAgZm9ybWF0IGFzIGRlc2NyaWJlZCBpbiBTZWN0aW9uIDExLjIgb2YgUkZDIDQwMDcuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDI5MTogSVAgVmVyc2lvbiA2IEFkZHJlc3NpbmcgQXJjaGl0ZWN0dXJlCiAgICAgIFJGQyA0MDA3OiBJUHY2IFNjb3BlZCBBZGRyZXNzIEFyY2hpdGVjdHVyZQogICAgICBSRkMgNTk1MjogQSBSZWNvbW1lbmRhdGlvbiBmb3IgSVB2NiBBZGRyZXNzIFRleHQKICAgICAgICAgICAgICAgIFJlcHJlc2VudGF0aW9uIjsKICB9CgogIHR5cGVkZWYgaXAtYWRkcmVzcy1uby16b25lIHsKICAgIHR5cGUgdW5pb24gewogICAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzLW5vLXpvbmU7CiAgICAgIHR5cGUgaW5ldDppcHY2LWFkZHJlc3Mtbm8tem9uZTsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBpcC1hZGRyZXNzLW5vLXpvbmUgdHlwZSByZXByZXNlbnRzIGFuIElQIGFkZHJlc3MgYW5kIGlzCiAgICAgIElQIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb24KICAgICAgaW1wbGllcyB0aGUgSVAgdmVyc2lvbi4gIFRoaXMgdHlwZSBkb2VzIG5vdCBzdXBwb3J0IHNjb3BlZAogICAgICBhZGRyZXNzZXMgc2luY2UgaXQgZG9lcyBub3QgYWxsb3cgem9uZSBpZGVudGlmaWVycyBpbiB0aGUKICAgICAgYWRkcmVzcyBmb3JtYXQuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDAwNzogSVB2NiBTY29wZWQgQWRkcmVzcyBBcmNoaXRlY3R1cmUiOwogIH0KCiAgdHlwZWRlZiBpcHY0LWFkZHJlc3Mtbm8tem9uZSB7CiAgICB0eXBlIGluZXQ6aXB2NC1hZGRyZXNzIHsKICAgICAgcGF0dGVybiAnWzAtOVwuXSonOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIkFuIElQdjQgYWRkcmVzcyB3aXRob3V0IGEgem9uZSBpbmRleC4gIFRoaXMgdHlwZSwgZGVyaXZlZCBmcm9tCiAgICAgICBpcHY0LWFkZHJlc3MsIG1heSBiZSB1c2VkIGluIHNpdHVhdGlvbnMgd2hlcmUgdGhlIHpvbmUgaXMKICAgICAgIGtub3duIGZyb20gdGhlIGNvbnRleHQgYW5kIGhlbmNlIG5vIHpvbmUgaW5kZXggaXMgbmVlZGVkLiI7CiAgfQoKICB0eXBlZGVmIGlwdjYtYWRkcmVzcy1uby16b25lIHsKICAgIHR5cGUgaW5ldDppcHY2LWFkZHJlc3MgewogICAgICBwYXR0ZXJuICdbMC05YS1mQS1GOlwuXSonOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAgIkFuIElQdjYgYWRkcmVzcyB3aXRob3V0IGEgem9uZSBpbmRleC4gIFRoaXMgdHlwZSwgZGVyaXZlZCBmcm9tCiAgICAgICBpcHY2LWFkZHJlc3MsIG1heSBiZSB1c2VkIGluIHNpdHVhdGlvbnMgd2hlcmUgdGhlIHpvbmUgaXMKICAgICAgIGtub3duIGZyb20gdGhlIGNvbnRleHQgYW5kIGhlbmNlIG5vIHpvbmUgaW5kZXggaXMgbmVlZGVkLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDQyOTE6IElQIFZlcnNpb24gNiBBZGRyZXNzaW5nIEFyY2hpdGVjdHVyZQogICAgICBSRkMgNDAwNzogSVB2NiBTY29wZWQgQWRkcmVzcyBBcmNoaXRlY3R1cmUKICAgICAgUkZDIDU5NTI6IEEgUmVjb21tZW5kYXRpb24gZm9yIElQdjYgQWRkcmVzcyBUZXh0CiAgICAgICAgICAgICAgICBSZXByZXNlbnRhdGlvbiI7CiAgfQoKICB0eXBlZGVmIGlwLXByZWZpeCB7CiAgICB0eXBlIHVuaW9uIHsKICAgICAgdHlwZSBpbmV0OmlwdjQtcHJlZml4OwogICAgICB0eXBlIGluZXQ6aXB2Ni1wcmVmaXg7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXAtcHJlZml4IHR5cGUgcmVwcmVzZW50cyBhbiBJUCBwcmVmaXggYW5kIGlzIElQCiAgICAgIHZlcnNpb24gbmV1dHJhbC4gIFRoZSBmb3JtYXQgb2YgdGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb25zCiAgICAgIGltcGxpZXMgdGhlIElQIHZlcnNpb24uIjsKICB9CgogIHR5cGVkZWYgaXB2NC1wcmVmaXggewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuCiAgICAgICAgICcoKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSlcLil7M30nCiAgICAgICArICAnKFswLTldfFsxLTldWzAtOV18MVswLTldWzAtOV18MlswLTRdWzAtOV18MjVbMC01XSknCiAgICAgICArICcvKChbMC05XSl8KFsxLTJdWzAtOV0pfCgzWzAtMl0pKSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaXB2NC1wcmVmaXggdHlwZSByZXByZXNlbnRzIGFuIElQdjQgYWRkcmVzcyBwcmVmaXguCiAgICAgIFRoZSBwcmVmaXggbGVuZ3RoIGlzIGdpdmVuIGJ5IHRoZSBudW1iZXIgZm9sbG93aW5nIHRoZQogICAgICBzbGFzaCBjaGFyYWN0ZXIgYW5kIG11c3QgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDMyLgoKICAgICAgQSBwcmVmaXggbGVuZ3RoIHZhbHVlIG9mIG4gY29ycmVzcG9uZHMgdG8gYW4gSVAgYWRkcmVzcwogICAgICBtYXNrIHRoYXQgaGFzIG4gY29udGlndW91cyAxLWJpdHMgZnJvbSB0aGUgbW9zdAogICAgICBzaWduaWZpY2FudCBiaXQgKE1TQikgYW5kIGFsbCBvdGhlciBiaXRzIHNldCB0byAwLgoKICAgICAgVGhlIGNhbm9uaWNhbCBmb3JtYXQgb2YgYW4gSVB2NCBwcmVmaXggaGFzIGFsbCBiaXRzIG9mCiAgICAgIHRoZSBJUHY0IGFkZHJlc3Mgc2V0IHRvIHplcm8gdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlCiAgICAgIElQdjQgcHJlZml4LiI7CiAgfQoKICB0eXBlZGVmIGlwdjYtcHJlZml4IHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKCg6fFswLTlhLWZBLUZdezAsNH0pOikoWzAtOWEtZkEtRl17MCw0fTopezAsNX0nCiAgICAgICAgICAgICsgJygoKFswLTlhLWZBLUZdezAsNH06KT8oOnxbMC05YS1mQS1GXXswLDR9KSl8JwogICAgICAgICAgICArICcoKCgyNVswLTVdfDJbMC00XVswLTldfFswMV0/WzAtOV0/WzAtOV0pXC4pezN9JwogICAgICAgICAgICArICcoMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdP1swLTldP1swLTldKSkpJwogICAgICAgICAgICArICcoLygoWzAtOV0pfChbMC05XXsyfSl8KDFbMC0xXVswLTldKXwoMTJbMC04XSkpKSc7CiAgICAgIHBhdHRlcm4gJygoW146XSs6KXs2fSgoW146XSs6W146XSspfCguKlwuLiopKSl8JwogICAgICAgICAgICArICcoKChbXjpdKzopKlteOl0rKT86OigoW146XSs6KSpbXjpdKyk/KScKICAgICAgICAgICAgKyAnKC8uKyknOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGlwdjYtcHJlZml4IHR5cGUgcmVwcmVzZW50cyBhbiBJUHY2IGFkZHJlc3MgcHJlZml4LgogICAgICBUaGUgcHJlZml4IGxlbmd0aCBpcyBnaXZlbiBieSB0aGUgbnVtYmVyIGZvbGxvd2luZyB0aGUKICAgICAgc2xhc2ggY2hhcmFjdGVyIGFuZCBtdXN0IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byAxMjguCgogICAgICBBIHByZWZpeCBsZW5ndGggdmFsdWUgb2YgbiBjb3JyZXNwb25kcyB0byBhbiBJUCBhZGRyZXNzCiAgICAgIG1hc2sgdGhhdCBoYXMgbiBjb250aWd1b3VzIDEtYml0cyBmcm9tIHRoZSBtb3N0CiAgICAgIHNpZ25pZmljYW50IGJpdCAoTVNCKSBhbmQgYWxsIG90aGVyIGJpdHMgc2V0IHRvIDAuCgogICAgICBUaGUgSVB2NiBhZGRyZXNzIHNob3VsZCBoYXZlIGFsbCBiaXRzIHRoYXQgZG8gbm90IGJlbG9uZwogICAgICB0byB0aGUgcHJlZml4IHNldCB0byB6ZXJvLgoKICAgICAgVGhlIGNhbm9uaWNhbCBmb3JtYXQgb2YgYW4gSVB2NiBwcmVmaXggaGFzIGFsbCBiaXRzIG9mCiAgICAgIHRoZSBJUHY2IGFkZHJlc3Mgc2V0IHRvIHplcm8gdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlCiAgICAgIElQdjYgcHJlZml4LiAgRnVydGhlcm1vcmUsIHRoZSBJUHY2IGFkZHJlc3MgaXMgcmVwcmVzZW50ZWQKICAgICAgYXMgZGVmaW5lZCBpbiBTZWN0aW9uIDQgb2YgUkZDIDU5NTIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNTk1MjogQSBSZWNvbW1lbmRhdGlvbiBmb3IgSVB2NiBBZGRyZXNzIFRleHQKICAgICAgICAgICAgICAgIFJlcHJlc2VudGF0aW9uIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBkb21haW4gbmFtZSBhbmQgVVJJIHR5cGVzICoqKi8KCiAgdHlwZWRlZiBkb21haW4tbmFtZSB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIGxlbmd0aCAiMS4uMjUzIjsKICAgICAgcGF0dGVybgogICAgICAgICcoKChbYS16QS1aMC05X10oW2EtekEtWjAtOVwtX10pezAsNjF9KT9bYS16QS1aMC05XVwuKSonCiAgICAgICsgJyhbYS16QS1aMC05X10oW2EtekEtWjAtOVwtX10pezAsNjF9KT9bYS16QS1aMC05XVwuPyknCiAgICAgICsgJ3xcLic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgZG9tYWluLW5hbWUgdHlwZSByZXByZXNlbnRzIGEgRE5TIGRvbWFpbiBuYW1lLiAgVGhlCiAgICAgIG5hbWUgU0hPVUxEIGJlIGZ1bGx5IHF1YWxpZmllZCB3aGVuZXZlciBwb3NzaWJsZS4KCiAgICAgIEludGVybmV0IGRvbWFpbiBuYW1lcyBhcmUgb25seSBsb29zZWx5IHNwZWNpZmllZC4gIFNlY3Rpb24KICAgICAgMy41IG9mIFJGQyAxMDM0IHJlY29tbWVuZHMgYSBzeW50YXggKG1vZGlmaWVkIGluIFNlY3Rpb24KICAgICAgMi4xIG9mIFJGQyAxMTIzKS4gIFRoZSBwYXR0ZXJuIGFib3ZlIGlzIGludGVuZGVkIHRvIGFsbG93CiAgICAgIGZvciBjdXJyZW50IHByYWN0aWNlIGluIGRvbWFpbiBuYW1lIHVzZSwgYW5kIHNvbWUgcG9zc2libGUKICAgICAgZnV0dXJlIGV4cGFuc2lvbi4gIEl0IGlzIGRlc2lnbmVkIHRvIGhvbGQgdmFyaW91cyB0eXBlcyBvZgogICAgICBkb21haW4gbmFtZXMsIGluY2x1ZGluZyBuYW1lcyB1c2VkIGZvciBBIG9yIEFBQUEgcmVjb3JkcwogICAgICAoaG9zdCBuYW1lcykgYW5kIG90aGVyIHJlY29yZHMsIHN1Y2ggYXMgU1JWIHJlY29yZHMuICBOb3RlCiAgICAgIHRoYXQgSW50ZXJuZXQgaG9zdCBuYW1lcyBoYXZlIGEgc3RyaWN0ZXIgc3ludGF4IChkZXNjcmliZWQKICAgICAgaW4gUkZDIDk1MikgdGhhbiB0aGUgRE5TIHJlY29tbWVuZGF0aW9ucyBpbiBSRkNzIDEwMzQgYW5kCiAgICAgIDExMjMsIGFuZCB0aGF0IHN5c3RlbXMgdGhhdCB3YW50IHRvIHN0b3JlIGhvc3QgbmFtZXMgaW4KICAgICAgc2NoZW1hIG5vZGVzIHVzaW5nIHRoZSBkb21haW4tbmFtZSB0eXBlIGFyZSByZWNvbW1lbmRlZCB0bwogICAgICBhZGhlcmUgdG8gdGhpcyBzdHJpY3RlciBzdGFuZGFyZCB0byBlbnN1cmUgaW50ZXJvcGVyYWJpbGl0eS4KCiAgICAgIFRoZSBlbmNvZGluZyBvZiBETlMgbmFtZXMgaW4gdGhlIEROUyBwcm90b2NvbCBpcyBsaW1pdGVkCiAgICAgIHRvIDI1NSBjaGFyYWN0ZXJzLiAgU2luY2UgdGhlIGVuY29kaW5nIGNvbnNpc3RzIG9mIGxhYmVscwogICAgICBwcmVmaXhlZCBieSBhIGxlbmd0aCBieXRlcyBhbmQgdGhlcmUgaXMgYSB0cmFpbGluZyBOVUxMCiAgICAgIGJ5dGUsIG9ubHkgMjUzIGNoYXJhY3RlcnMgY2FuIGFwcGVhciBpbiB0aGUgdGV4dHVhbCBkb3R0ZWQKICAgICAgbm90YXRpb24uCgogICAgICBUaGUgZGVzY3JpcHRpb24gY2xhdXNlIG9mIHNjaGVtYSBub2RlcyB1c2luZyB0aGUgZG9tYWluLW5hbWUKICAgICAgdHlwZSBNVVNUIGRlc2NyaWJlIHdoZW4gYW5kIGhvdyB0aGVzZSBuYW1lcyBhcmUgcmVzb2x2ZWQgdG8KICAgICAgSVAgYWRkcmVzc2VzLiAgTm90ZSB0aGF0IHRoZSByZXNvbHV0aW9uIG9mIGEgZG9tYWluLW5hbWUgdmFsdWUKICAgICAgbWF5IHJlcXVpcmUgdG8gcXVlcnkgbXVsdGlwbGUgRE5TIHJlY29yZHMgKGUuZy4sIEEgZm9yIElQdjQKICAgICAgYW5kIEFBQUEgZm9yIElQdjYpLiAgVGhlIG9yZGVyIG9mIHRoZSByZXNvbHV0aW9uIHByb2Nlc3MgYW5kCiAgICAgIHdoaWNoIEROUyByZWNvcmQgdGFrZXMgcHJlY2VkZW5jZSBjYW4gZWl0aGVyIGJlIGRlZmluZWQKICAgICAgZXhwbGljaXRseSBvciBtYXkgZGVwZW5kIG9uIHRoZSBjb25maWd1cmF0aW9uIG9mIHRoZQogICAgICByZXNvbHZlci4KCiAgICAgIERvbWFpbi1uYW1lIHZhbHVlcyB1c2UgdGhlIFVTLUFTQ0lJIGVuY29kaW5nLiAgVGhlaXIgY2Fub25pY2FsCiAgICAgIGZvcm1hdCB1c2VzIGxvd2VyY2FzZSBVUy1BU0NJSSBjaGFyYWN0ZXJzLiAgSW50ZXJuYXRpb25hbGl6ZWQKICAgICAgZG9tYWluIG5hbWVzIE1VU1QgYmUgQS1sYWJlbHMgYXMgcGVyIFJGQyA1ODkwLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDICA5NTI6IERvRCBJbnRlcm5ldCBIb3N0IFRhYmxlIFNwZWNpZmljYXRpb24KICAgICAgUkZDIDEwMzQ6IERvbWFpbiBOYW1lcyAtIENvbmNlcHRzIGFuZCBGYWNpbGl0aWVzCiAgICAgIFJGQyAxMTIzOiBSZXF1aXJlbWVudHMgZm9yIEludGVybmV0IEhvc3RzIC0tIEFwcGxpY2F0aW9uCiAgICAgICAgICAgICAgICBhbmQgU3VwcG9ydAogICAgICBSRkMgMjc4MjogQSBETlMgUlIgZm9yIHNwZWNpZnlpbmcgdGhlIGxvY2F0aW9uIG9mIHNlcnZpY2VzCiAgICAgICAgICAgICAgICAoRE5TIFNSVikKICAgICAgUkZDIDU4OTA6IEludGVybmF0aW9uYWxpemVkIERvbWFpbiBOYW1lcyBpbiBBcHBsaWNhdGlvbnMKICAgICAgICAgICAgICAgIChJRE5BKTogRGVmaW5pdGlvbnMgYW5kIERvY3VtZW50IEZyYW1ld29yayI7CiAgfQoKICB0eXBlZGVmIGhvc3QgewogICAgdHlwZSB1bmlvbiB7CiAgICAgIHR5cGUgaW5ldDppcC1hZGRyZXNzOwogICAgICB0eXBlIGluZXQ6ZG9tYWluLW5hbWU7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgaG9zdCB0eXBlIHJlcHJlc2VudHMgZWl0aGVyIGFuIElQIGFkZHJlc3Mgb3IgYSBETlMKICAgICAgZG9tYWluIG5hbWUuIjsKICB9CgogIHR5cGVkZWYgdXJpIHsKICAgIHR5cGUgc3RyaW5nOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIHVyaSB0eXBlIHJlcHJlc2VudHMgYSBVbmlmb3JtIFJlc291cmNlIElkZW50aWZpZXIKICAgICAgKFVSSSkgYXMgZGVmaW5lZCBieSBTVEQgNjYuCgogICAgICBPYmplY3RzIHVzaW5nIHRoZSB1cmkgdHlwZSBNVVNUIGJlIGluIFVTLUFTQ0lJIGVuY29kaW5nLAogICAgICBhbmQgTVVTVCBiZSBub3JtYWxpemVkIGFzIGRlc2NyaWJlZCBieSBSRkMgMzk4NiBTZWN0aW9ucwogICAgICA2LjIuMSwgNi4yLjIuMSwgYW5kIDYuMi4yLjIuICBBbGwgdW5uZWNlc3NhcnkKICAgICAgcGVyY2VudC1lbmNvZGluZyBpcyByZW1vdmVkLCBhbmQgYWxsIGNhc2UtaW5zZW5zaXRpdmUKICAgICAgY2hhcmFjdGVycyBhcmUgc2V0IHRvIGxvd2VyY2FzZSBleGNlcHQgZm9yIGhleGFkZWNpbWFsCiAgICAgIGRpZ2l0cywgd2hpY2ggYXJlIG5vcm1hbGl6ZWQgdG8gdXBwZXJjYXNlIGFzIGRlc2NyaWJlZCBpbgogICAgICBTZWN0aW9uIDYuMi4yLjEuCgogICAgICBUaGUgcHVycG9zZSBvZiB0aGlzIG5vcm1hbGl6YXRpb24gaXMgdG8gaGVscCBwcm92aWRlCiAgICAgIHVuaXF1ZSBVUklzLiAgTm90ZSB0aGF0IHRoaXMgbm9ybWFsaXphdGlvbiBpcyBub3QKICAgICAgc3VmZmljaWVudCB0byBwcm92aWRlIHVuaXF1ZW5lc3MuICBUd28gVVJJcyB0aGF0IGFyZQogICAgICB0ZXh0dWFsbHkgZGlzdGluY3QgYWZ0ZXIgdGhpcyBub3JtYWxpemF0aW9uIG1heSBzdGlsbCBiZQogICAgICBlcXVpdmFsZW50LgoKICAgICAgT2JqZWN0cyB1c2luZyB0aGUgdXJpIHR5cGUgbWF5IHJlc3RyaWN0IHRoZSBzY2hlbWVzIHRoYXQKICAgICAgdGhleSBwZXJtaXQuICBGb3IgZXhhbXBsZSwgJ2RhdGE6JyBhbmQgJ3VybjonIHNjaGVtZXMKICAgICAgbWlnaHQgbm90IGJlIGFwcHJvcHJpYXRlLgoKICAgICAgQSB6ZXJvLWxlbmd0aCBVUkkgaXMgbm90IGEgdmFsaWQgVVJJLiAgVGhpcyBjYW4gYmUgdXNlZCB0bwogICAgICBleHByZXNzICdVUkkgYWJzZW50JyB3aGVyZSByZXF1aXJlZC4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBVcmkgU01JdjIgdGV4dHVhbCBjb252ZW50aW9uIGRlZmluZWQgaW4gUkZDIDUwMTcuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzk4NjogVW5pZm9ybSBSZXNvdXJjZSBJZGVudGlmaWVyIChVUkkpOiBHZW5lcmljIFN5bnRheAogICAgICBSRkMgMzMwNTogUmVwb3J0IGZyb20gdGhlIEpvaW50IFczQy9JRVRGIFVSSSBQbGFubmluZyBJbnRlcmVzdAogICAgICAgICAgICAgICAgR3JvdXA6IFVuaWZvcm0gUmVzb3VyY2UgSWRlbnRpZmllcnMgKFVSSXMpLCBVUkxzLAogICAgICAgICAgICAgICAgYW5kIFVuaWZvcm0gUmVzb3VyY2UgTmFtZXMgKFVSTnMpOiBDbGFyaWZpY2F0aW9ucwogICAgICAgICAgICAgICAgYW5kIFJlY29tbWVuZGF0aW9ucwogICAgICBSRkMgNTAxNzogTUlCIFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFVuaWZvcm0gUmVzb3VyY2UKICAgICAgICAgICAgICAgIElkZW50aWZpZXJzIChVUklzKSI7CiAgfQoKfQ== +ietf-yang-types urn:ietf:params:xml:ns:yang:ietf-yang-types \N [] 2013-07-15 bW9kdWxlIGlldGYteWFuZy10eXBlcyB7CgogIG5hbWVzcGFjZSAidXJuOmlldGY6cGFyYW1zOnhtbDpuczp5YW5nOmlldGYteWFuZy10eXBlcyI7CiAgcHJlZml4ICJ5YW5nIjsKCiAgb3JnYW5pemF0aW9uCiAgICJJRVRGIE5FVE1PRCAoTkVUQ09ORiBEYXRhIE1vZGVsaW5nIExhbmd1YWdlKSBXb3JraW5nIEdyb3VwIjsKCiAgY29udGFjdAogICAiV0cgV2ViOiAgIDxodHRwOi8vdG9vbHMuaWV0Zi5vcmcvd2cvbmV0bW9kLz4KICAgIFdHIExpc3Q6ICA8bWFpbHRvOm5ldG1vZEBpZXRmLm9yZz4KCiAgICBXRyBDaGFpcjogRGF2aWQgS2Vzc2VucwogICAgICAgICAgICAgIDxtYWlsdG86ZGF2aWQua2Vzc2Vuc0Buc24uY29tPgoKICAgIFdHIENoYWlyOiBKdWVyZ2VuIFNjaG9lbndhZWxkZXIKICAgICAgICAgICAgICA8bWFpbHRvOmouc2Nob2Vud2FlbGRlckBqYWNvYnMtdW5pdmVyc2l0eS5kZT4KCiAgICBFZGl0b3I6ICAgSnVlcmdlbiBTY2hvZW53YWVsZGVyCiAgICAgICAgICAgICAgPG1haWx0bzpqLnNjaG9lbndhZWxkZXJAamFjb2JzLXVuaXZlcnNpdHkuZGU+IjsKCiAgZGVzY3JpcHRpb24KICAgIlRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiBnZW5lcmFsbHkgdXNlZnVsIGRlcml2ZWQKICAgIFlBTkcgZGF0YSB0eXBlcy4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMTMgSUVURiBUcnVzdCBhbmQgdGhlIHBlcnNvbnMgaWRlbnRpZmllZCBhcwogICAgYXV0aG9ycyBvZiB0aGUgY29kZS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvcgogICAgd2l0aG91dCBtb2RpZmljYXRpb24sIGlzIHBlcm1pdHRlZCBwdXJzdWFudCB0bywgYW5kIHN1YmplY3QKICAgIHRvIHRoZSBsaWNlbnNlIHRlcm1zIGNvbnRhaW5lZCBpbiwgdGhlIFNpbXBsaWZpZWQgQlNEIExpY2Vuc2UKICAgIHNldCBmb3J0aCBpbiBTZWN0aW9uIDQuYyBvZiB0aGUgSUVURiBUcnVzdCdzIExlZ2FsIFByb3Zpc2lvbnMKICAgIFJlbGF0aW5nIHRvIElFVEYgRG9jdW1lbnRzCiAgICAoaHR0cDovL3RydXN0ZWUuaWV0Zi5vcmcvbGljZW5zZS1pbmZvKS4KCiAgICBUaGlzIHZlcnNpb24gb2YgdGhpcyBZQU5HIG1vZHVsZSBpcyBwYXJ0IG9mIFJGQyA2OTkxOyBzZWUKICAgIHRoZSBSRkMgaXRzZWxmIGZvciBmdWxsIGxlZ2FsIG5vdGljZXMuIjsKCiAgcmV2aXNpb24gMjAxMy0wNy0xNSB7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGlzIHJldmlzaW9uIGFkZHMgdGhlIGZvbGxvd2luZyBuZXcgZGF0YSB0eXBlczoKICAgICAgLSB5YW5nLWlkZW50aWZpZXIKICAgICAgLSBoZXgtc3RyaW5nCiAgICAgIC0gdXVpZAogICAgICAtIGRvdHRlZC1xdWFkIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjk5MTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICByZXZpc2lvbiAyMDEwLTA5LTI0IHsKICAgIGRlc2NyaXB0aW9uCiAgICAgIkluaXRpYWwgcmV2aXNpb24uIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNjAyMTogQ29tbW9uIFlBTkcgRGF0YSBUeXBlcyI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2YgY291bnRlciBhbmQgZ2F1Z2UgdHlwZXMgKioqLwoKICB0eXBlZGVmIGNvdW50ZXIzMiB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBjb3VudGVyMzIgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIKICAgICAgdGhhdCBtb25vdG9uaWNhbGx5IGluY3JlYXNlcyB1bnRpbCBpdCByZWFjaGVzIGEKICAgICAgbWF4aW11bSB2YWx1ZSBvZiAyXjMyLTEgKDQyOTQ5NjcyOTUgZGVjaW1hbCksIHdoZW4gaXQKICAgICAgd3JhcHMgYXJvdW5kIGFuZCBzdGFydHMgaW5jcmVhc2luZyBhZ2FpbiBmcm9tIHplcm8uCgogICAgICBDb3VudGVycyBoYXZlIG5vIGRlZmluZWQgJ2luaXRpYWwnIHZhbHVlLCBhbmQgdGh1cywgYQogICAgICBzaW5nbGUgdmFsdWUgb2YgYSBjb3VudGVyIGhhcyAoaW4gZ2VuZXJhbCkgbm8gaW5mb3JtYXRpb24KICAgICAgY29udGVudC4gIERpc2NvbnRpbnVpdGllcyBpbiB0aGUgbW9ub3RvbmljYWxseSBpbmNyZWFzaW5nCiAgICAgIHZhbHVlIG5vcm1hbGx5IG9jY3VyIGF0IHJlLWluaXRpYWxpemF0aW9uIG9mIHRoZQogICAgICBtYW5hZ2VtZW50IHN5c3RlbSwgYW5kIGF0IG90aGVyIHRpbWVzIGFzIHNwZWNpZmllZCBpbiB0aGUKICAgICAgZGVzY3JpcHRpb24gb2YgYSBzY2hlbWEgbm9kZSB1c2luZyB0aGlzIHR5cGUuICBJZiBzdWNoCiAgICAgIG90aGVyIHRpbWVzIGNhbiBvY2N1ciwgZm9yIGV4YW1wbGUsIHRoZSBjcmVhdGlvbiBvZgogICAgICBhIHNjaGVtYSBub2RlIG9mIHR5cGUgY291bnRlcjMyIGF0IHRpbWVzIG90aGVyIHRoYW4KICAgICAgcmUtaW5pdGlhbGl6YXRpb24sIHRoZW4gYSBjb3JyZXNwb25kaW5nIHNjaGVtYSBub2RlCiAgICAgIHNob3VsZCBiZSBkZWZpbmVkLCB3aXRoIGFuIGFwcHJvcHJpYXRlIHR5cGUsIHRvIGluZGljYXRlCiAgICAgIHRoZSBsYXN0IGRpc2NvbnRpbnVpdHkuCgogICAgICBUaGUgY291bnRlcjMyIHR5cGUgc2hvdWxkIG5vdCBiZSB1c2VkIGZvciBjb25maWd1cmF0aW9uCiAgICAgIHNjaGVtYSBub2Rlcy4gIEEgZGVmYXVsdCBzdGF0ZW1lbnQgU0hPVUxEIE5PVCBiZSB1c2VkIGluCiAgICAgIGNvbWJpbmF0aW9uIHdpdGggdGhlIHR5cGUgY291bnRlcjMyLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIENvdW50ZXIzMiB0eXBlIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyNTc4OiBTdHJ1Y3R1cmUgb2YgTWFuYWdlbWVudCBJbmZvcm1hdGlvbiBWZXJzaW9uIDIKICAgICAgICAgICAgICAgIChTTUl2MikiOwogIH0KCiAgdHlwZWRlZiB6ZXJvLWJhc2VkLWNvdW50ZXIzMiB7CiAgICB0eXBlIHlhbmc6Y291bnRlcjMyOwogICAgZGVmYXVsdCAiMCI7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgemVyby1iYXNlZC1jb3VudGVyMzIgdHlwZSByZXByZXNlbnRzIGEgY291bnRlcjMyCiAgICAgIHRoYXQgaGFzIHRoZSBkZWZpbmVkICdpbml0aWFsJyB2YWx1ZSB6ZXJvLgoKICAgICAgQSBzY2hlbWEgbm9kZSBvZiB0aGlzIHR5cGUgd2lsbCBiZSBzZXQgdG8gemVybyAoMCkgb24gY3JlYXRpb24KICAgICAgYW5kIHdpbGwgdGhlcmVhZnRlciBpbmNyZWFzZSBtb25vdG9uaWNhbGx5IHVudGlsIGl0IHJlYWNoZXMKICAgICAgYSBtYXhpbXVtIHZhbHVlIG9mIDJeMzItMSAoNDI5NDk2NzI5NSBkZWNpbWFsKSwgd2hlbiBpdAogICAgICB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIFByb3ZpZGVkIHRoYXQgYW4gYXBwbGljYXRpb24gZGlzY292ZXJzIGEgbmV3IHNjaGVtYSBub2RlCiAgICAgIG9mIHRoaXMgdHlwZSB3aXRoaW4gdGhlIG1pbmltdW0gdGltZSB0byB3cmFwLCBpdCBjYW4gdXNlIHRoZQogICAgICAnaW5pdGlhbCcgdmFsdWUgYXMgYSBkZWx0YS4gIEl0IGlzIGltcG9ydGFudCBmb3IgYSBtYW5hZ2VtZW50CiAgICAgIHN0YXRpb24gdG8gYmUgYXdhcmUgb2YgdGhpcyBtaW5pbXVtIHRpbWUgYW5kIHRoZSBhY3R1YWwgdGltZQogICAgICBiZXR3ZWVuIHBvbGxzLCBhbmQgdG8gZGlzY2FyZCBkYXRhIGlmIHRoZSBhY3R1YWwgdGltZSBpcyB0b28KICAgICAgbG9uZyBvciB0aGVyZSBpcyBubyBkZWZpbmVkIG1pbmltdW0gdGltZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBaZXJvQmFzZWRDb3VudGVyMzIgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgICJSRkMgNDUwMjogUmVtb3RlIE5ldHdvcmsgTW9uaXRvcmluZyBNYW5hZ2VtZW50IEluZm9ybWF0aW9uCiAgICAgICAgICAgICAgICAgQmFzZSBWZXJzaW9uIDIiOwogIH0KCiAgdHlwZWRlZiBjb3VudGVyNjQgewogICAgdHlwZSB1aW50NjQ7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgY291bnRlcjY0IHR5cGUgcmVwcmVzZW50cyBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyCiAgICAgIHRoYXQgbW9ub3RvbmljYWxseSBpbmNyZWFzZXMgdW50aWwgaXQgcmVhY2hlcyBhCiAgICAgIG1heGltdW0gdmFsdWUgb2YgMl42NC0xICgxODQ0Njc0NDA3MzcwOTU1MTYxNSBkZWNpbWFsKSwKICAgICAgd2hlbiBpdCB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIENvdW50ZXJzIGhhdmUgbm8gZGVmaW5lZCAnaW5pdGlhbCcgdmFsdWUsIGFuZCB0aHVzLCBhCiAgICAgIHNpbmdsZSB2YWx1ZSBvZiBhIGNvdW50ZXIgaGFzIChpbiBnZW5lcmFsKSBubyBpbmZvcm1hdGlvbgogICAgICBjb250ZW50LiAgRGlzY29udGludWl0aWVzIGluIHRoZSBtb25vdG9uaWNhbGx5IGluY3JlYXNpbmcKICAgICAgdmFsdWUgbm9ybWFsbHkgb2NjdXIgYXQgcmUtaW5pdGlhbGl6YXRpb24gb2YgdGhlCiAgICAgIG1hbmFnZW1lbnQgc3lzdGVtLCBhbmQgYXQgb3RoZXIgdGltZXMgYXMgc3BlY2lmaWVkIGluIHRoZQogICAgICBkZXNjcmlwdGlvbiBvZiBhIHNjaGVtYSBub2RlIHVzaW5nIHRoaXMgdHlwZS4gIElmIHN1Y2gKICAgICAgb3RoZXIgdGltZXMgY2FuIG9jY3VyLCBmb3IgZXhhbXBsZSwgdGhlIGNyZWF0aW9uIG9mCiAgICAgIGEgc2NoZW1hIG5vZGUgb2YgdHlwZSBjb3VudGVyNjQgYXQgdGltZXMgb3RoZXIgdGhhbgogICAgICByZS1pbml0aWFsaXphdGlvbiwgdGhlbiBhIGNvcnJlc3BvbmRpbmcgc2NoZW1hIG5vZGUKICAgICAgc2hvdWxkIGJlIGRlZmluZWQsIHdpdGggYW4gYXBwcm9wcmlhdGUgdHlwZSwgdG8gaW5kaWNhdGUKICAgICAgdGhlIGxhc3QgZGlzY29udGludWl0eS4KCiAgICAgIFRoZSBjb3VudGVyNjQgdHlwZSBzaG91bGQgbm90IGJlIHVzZWQgZm9yIGNvbmZpZ3VyYXRpb24KICAgICAgc2NoZW1hIG5vZGVzLiAgQSBkZWZhdWx0IHN0YXRlbWVudCBTSE9VTEQgTk9UIGJlIHVzZWQgaW4KICAgICAgY29tYmluYXRpb24gd2l0aCB0aGUgdHlwZSBjb3VudGVyNjQuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgQ291bnRlcjY0IHR5cGUgb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDI1Nzg6IFN0cnVjdHVyZSBvZiBNYW5hZ2VtZW50IEluZm9ybWF0aW9uIFZlcnNpb24gMgogICAgICAgICAgICAgICAgKFNNSXYyKSI7CiAgfQoKICB0eXBlZGVmIHplcm8tYmFzZWQtY291bnRlcjY0IHsKICAgIHR5cGUgeWFuZzpjb3VudGVyNjQ7CiAgICBkZWZhdWx0ICIwIjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSB6ZXJvLWJhc2VkLWNvdW50ZXI2NCB0eXBlIHJlcHJlc2VudHMgYSBjb3VudGVyNjQgdGhhdAogICAgICBoYXMgdGhlIGRlZmluZWQgJ2luaXRpYWwnIHZhbHVlIHplcm8uCgoKCgogICAgICBBIHNjaGVtYSBub2RlIG9mIHRoaXMgdHlwZSB3aWxsIGJlIHNldCB0byB6ZXJvICgwKSBvbiBjcmVhdGlvbgogICAgICBhbmQgd2lsbCB0aGVyZWFmdGVyIGluY3JlYXNlIG1vbm90b25pY2FsbHkgdW50aWwgaXQgcmVhY2hlcwogICAgICBhIG1heGltdW0gdmFsdWUgb2YgMl42NC0xICgxODQ0Njc0NDA3MzcwOTU1MTYxNSBkZWNpbWFsKSwKICAgICAgd2hlbiBpdCB3cmFwcyBhcm91bmQgYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGZyb20gemVyby4KCiAgICAgIFByb3ZpZGVkIHRoYXQgYW4gYXBwbGljYXRpb24gZGlzY292ZXJzIGEgbmV3IHNjaGVtYSBub2RlCiAgICAgIG9mIHRoaXMgdHlwZSB3aXRoaW4gdGhlIG1pbmltdW0gdGltZSB0byB3cmFwLCBpdCBjYW4gdXNlIHRoZQogICAgICAnaW5pdGlhbCcgdmFsdWUgYXMgYSBkZWx0YS4gIEl0IGlzIGltcG9ydGFudCBmb3IgYSBtYW5hZ2VtZW50CiAgICAgIHN0YXRpb24gdG8gYmUgYXdhcmUgb2YgdGhpcyBtaW5pbXVtIHRpbWUgYW5kIHRoZSBhY3R1YWwgdGltZQogICAgICBiZXR3ZWVuIHBvbGxzLCBhbmQgdG8gZGlzY2FyZCBkYXRhIGlmIHRoZSBhY3R1YWwgdGltZSBpcyB0b28KICAgICAgbG9uZyBvciB0aGVyZSBpcyBubyBkZWZpbmVkIG1pbmltdW0gdGltZS4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBaZXJvQmFzZWRDb3VudGVyNjQgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyODU2OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBBZGRpdGlvbmFsIEhpZ2ggQ2FwYWNpdHkKICAgICAgICAgICAgICAgIERhdGEgVHlwZXMiOwogIH0KCiAgdHlwZWRlZiBnYXVnZTMyIHsKICAgIHR5cGUgdWludDMyOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhlIGdhdWdlMzIgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIsIHdoaWNoCiAgICAgIG1heSBpbmNyZWFzZSBvciBkZWNyZWFzZSwgYnV0IHNoYWxsIG5ldmVyIGV4Y2VlZCBhIG1heGltdW0KICAgICAgdmFsdWUsIG5vciBmYWxsIGJlbG93IGEgbWluaW11bSB2YWx1ZS4gIFRoZSBtYXhpbXVtIHZhbHVlCiAgICAgIGNhbm5vdCBiZSBncmVhdGVyIHRoYW4gMl4zMi0xICg0Mjk0OTY3Mjk1IGRlY2ltYWwpLCBhbmQKICAgICAgdGhlIG1pbmltdW0gdmFsdWUgY2Fubm90IGJlIHNtYWxsZXIgdGhhbiAwLiAgVGhlIHZhbHVlIG9mCiAgICAgIGEgZ2F1Z2UzMiBoYXMgaXRzIG1heGltdW0gdmFsdWUgd2hlbmV2ZXIgdGhlIGluZm9ybWF0aW9uCiAgICAgIGJlaW5nIG1vZGVsZWQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGl0cyBtYXhpbXVtCiAgICAgIHZhbHVlLCBhbmQgaGFzIGl0cyBtaW5pbXVtIHZhbHVlIHdoZW5ldmVyIHRoZSBpbmZvcm1hdGlvbgogICAgICBiZWluZyBtb2RlbGVkIGlzIHNtYWxsZXIgdGhhbiBvciBlcXVhbCB0byBpdHMgbWluaW11bSB2YWx1ZS4KICAgICAgSWYgdGhlIGluZm9ybWF0aW9uIGJlaW5nIG1vZGVsZWQgc3Vic2VxdWVudGx5IGRlY3JlYXNlcwogICAgICBiZWxvdyAoaW5jcmVhc2VzIGFib3ZlKSB0aGUgbWF4aW11bSAobWluaW11bSkgdmFsdWUsIHRoZQogICAgICBnYXVnZTMyIGFsc28gZGVjcmVhc2VzIChpbmNyZWFzZXMpLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIEdhdWdlMzIgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgZ2F1Z2U2NCB7CiAgICB0eXBlIHVpbnQ2NDsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSBnYXVnZTY0IHR5cGUgcmVwcmVzZW50cyBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyLCB3aGljaAogICAgICBtYXkgaW5jcmVhc2Ugb3IgZGVjcmVhc2UsIGJ1dCBzaGFsbCBuZXZlciBleGNlZWQgYSBtYXhpbXVtCiAgICAgIHZhbHVlLCBub3IgZmFsbCBiZWxvdyBhIG1pbmltdW0gdmFsdWUuICBUaGUgbWF4aW11bSB2YWx1ZQogICAgICBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuIDJeNjQtMSAoMTg0NDY3NDQwNzM3MDk1NTE2MTUpLCBhbmQKICAgICAgdGhlIG1pbmltdW0gdmFsdWUgY2Fubm90IGJlIHNtYWxsZXIgdGhhbiAwLiAgVGhlIHZhbHVlIG9mCiAgICAgIGEgZ2F1Z2U2NCBoYXMgaXRzIG1heGltdW0gdmFsdWUgd2hlbmV2ZXIgdGhlIGluZm9ybWF0aW9uCiAgICAgIGJlaW5nIG1vZGVsZWQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGl0cyBtYXhpbXVtCiAgICAgIHZhbHVlLCBhbmQgaGFzIGl0cyBtaW5pbXVtIHZhbHVlIHdoZW5ldmVyIHRoZSBpbmZvcm1hdGlvbgogICAgICBiZWluZyBtb2RlbGVkIGlzIHNtYWxsZXIgdGhhbiBvciBlcXVhbCB0byBpdHMgbWluaW11bSB2YWx1ZS4KICAgICAgSWYgdGhlIGluZm9ybWF0aW9uIGJlaW5nIG1vZGVsZWQgc3Vic2VxdWVudGx5IGRlY3JlYXNlcwogICAgICBiZWxvdyAoaW5jcmVhc2VzIGFib3ZlKSB0aGUgbWF4aW11bSAobWluaW11bSkgdmFsdWUsIHRoZQogICAgICBnYXVnZTY0IGFsc28gZGVjcmVhc2VzIChpbmNyZWFzZXMpLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIENvdW50ZXJCYXNlZEdhdWdlNjQgU01JdjIgdGV4dHVhbCBjb252ZW50aW9uIGRlZmluZWQKICAgICAgaW4gUkZDIDI4NTYiOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyODU2OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBBZGRpdGlvbmFsIEhpZ2ggQ2FwYWNpdHkKICAgICAgICAgICAgICAgIERhdGEgVHlwZXMiOwogIH0KCiAgLyoqKiBjb2xsZWN0aW9uIG9mIGlkZW50aWZpZXItcmVsYXRlZCB0eXBlcyAqKiovCgogIHR5cGVkZWYgb2JqZWN0LWlkZW50aWZpZXIgewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICcoKFswLTFdKFwuWzEtM10/WzAtOV0pKXwoMlwuKDB8KFsxLTldXGQqKSkpKScKICAgICAgICAgICAgKyAnKFwuKDB8KFsxLTldXGQqKSkpKic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgb2JqZWN0LWlkZW50aWZpZXIgdHlwZSByZXByZXNlbnRzIGFkbWluaXN0cmF0aXZlbHkKICAgICAgYXNzaWduZWQgbmFtZXMgaW4gYSByZWdpc3RyYXRpb24taGllcmFyY2hpY2FsLW5hbWUgdHJlZS4KCiAgICAgIFZhbHVlcyBvZiB0aGlzIHR5cGUgYXJlIGRlbm90ZWQgYXMgYSBzZXF1ZW5jZSBvZiBudW1lcmljYWwKICAgICAgbm9uLW5lZ2F0aXZlIHN1Yi1pZGVudGlmaWVyIHZhbHVlcy4gIEVhY2ggc3ViLWlkZW50aWZpZXIKICAgICAgdmFsdWUgTVVTVCBOT1QgZXhjZWVkIDJeMzItMSAoNDI5NDk2NzI5NSkuICBTdWItaWRlbnRpZmllcnMKICAgICAgYXJlIHNlcGFyYXRlZCBieSBzaW5nbGUgZG90cyBhbmQgd2l0aG91dCBhbnkgaW50ZXJtZWRpYXRlCiAgICAgIHdoaXRlc3BhY2UuCgogICAgICBUaGUgQVNOLjEgc3RhbmRhcmQgcmVzdHJpY3RzIHRoZSB2YWx1ZSBzcGFjZSBvZiB0aGUgZmlyc3QKICAgICAgc3ViLWlkZW50aWZpZXIgdG8gMCwgMSwgb3IgMi4gIEZ1cnRoZXJtb3JlLCB0aGUgdmFsdWUgc3BhY2UKICAgICAgb2YgdGhlIHNlY29uZCBzdWItaWRlbnRpZmllciBpcyByZXN0cmljdGVkIHRvIHRoZSByYW5nZQogICAgICAwIHRvIDM5IGlmIHRoZSBmaXJzdCBzdWItaWRlbnRpZmllciBpcyAwIG9yIDEuICBGaW5hbGx5LAogICAgICB0aGUgQVNOLjEgc3RhbmRhcmQgcmVxdWlyZXMgdGhhdCBhbiBvYmplY3QgaWRlbnRpZmllcgogICAgICBoYXMgYWx3YXlzIGF0IGxlYXN0IHR3byBzdWItaWRlbnRpZmllcnMuICBUaGUgcGF0dGVybgogICAgICBjYXB0dXJlcyB0aGVzZSByZXN0cmljdGlvbnMuCgogICAgICBBbHRob3VnaCB0aGUgbnVtYmVyIG9mIHN1Yi1pZGVudGlmaWVycyBpcyBub3QgbGltaXRlZCwKICAgICAgbW9kdWxlIGRlc2lnbmVycyBzaG91bGQgcmVhbGl6ZSB0aGF0IHRoZXJlIG1heSBiZQogICAgICBpbXBsZW1lbnRhdGlvbnMgdGhhdCBzdGljayB3aXRoIHRoZSBTTUl2MiBsaW1pdCBvZiAxMjgKICAgICAgc3ViLWlkZW50aWZpZXJzLgoKICAgICAgVGhpcyB0eXBlIGlzIGEgc3VwZXJzZXQgb2YgdGhlIFNNSXYyIE9CSkVDVCBJREVOVElGSUVSIHR5cGUKICAgICAgc2luY2UgaXQgaXMgbm90IHJlc3RyaWN0ZWQgdG8gMTI4IHN1Yi1pZGVudGlmaWVycy4gIEhlbmNlLAogICAgICB0aGlzIHR5cGUgU0hPVUxEIE5PVCBiZSB1c2VkIHRvIHJlcHJlc2VudCB0aGUgU01JdjIgT0JKRUNUCiAgICAgIElERU5USUZJRVIgdHlwZTsgdGhlIG9iamVjdC1pZGVudGlmaWVyLTEyOCB0eXBlIFNIT1VMRCBiZQogICAgICB1c2VkIGluc3RlYWQuIjsKICAgIHJlZmVyZW5jZQogICAgICJJU085ODM0LTE6IEluZm9ybWF0aW9uIHRlY2hub2xvZ3kgLS0gT3BlbiBTeXN0ZW1zCiAgICAgIEludGVyY29ubmVjdGlvbiAtLSBQcm9jZWR1cmVzIGZvciB0aGUgb3BlcmF0aW9uIG9mIE9TSQogICAgICBSZWdpc3RyYXRpb24gQXV0aG9yaXRpZXM6IEdlbmVyYWwgcHJvY2VkdXJlcyBhbmQgdG9wCiAgICAgIGFyY3Mgb2YgdGhlIEFTTi4xIE9iamVjdCBJZGVudGlmaWVyIHRyZWUiOwogIH0KCiAgdHlwZWRlZiBvYmplY3QtaWRlbnRpZmllci0xMjggewogICAgdHlwZSBvYmplY3QtaWRlbnRpZmllciB7CiAgICAgIHBhdHRlcm4gJ1xkKihcLlxkKil7MSwxMjd9JzsKICAgIH0KICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoaXMgdHlwZSByZXByZXNlbnRzIG9iamVjdC1pZGVudGlmaWVycyByZXN0cmljdGVkIHRvIDEyOAogICAgICBzdWItaWRlbnRpZmllcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgT0JKRUNUIElERU5USUZJRVIgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgeWFuZy1pZGVudGlmaWVyIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgbGVuZ3RoICIxLi5tYXgiOwogICAgICBwYXR0ZXJuICdbYS16QS1aX11bYS16QS1aMC05XC1fLl0qJzsKICAgICAgcGF0dGVybiAnLnwuLnxbXnhYXS4qfC5bXm1NXS4qfC4uW15sTF0uKic7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICAiQSBZQU5HIGlkZW50aWZpZXIgc3RyaW5nIGFzIGRlZmluZWQgYnkgdGhlICdpZGVudGlmaWVyJwogICAgICAgcnVsZSBpbiBTZWN0aW9uIDEyIG9mIFJGQyA2MDIwLiAgQW4gaWRlbnRpZmllciBtdXN0CiAgICAgICBzdGFydCB3aXRoIGFuIGFscGhhYmV0aWMgY2hhcmFjdGVyIG9yIGFuIHVuZGVyc2NvcmUKICAgICAgIGZvbGxvd2VkIGJ5IGFuIGFyYml0cmFyeSBzZXF1ZW5jZSBvZiBhbHBoYWJldGljIG9yCiAgICAgICBudW1lcmljIGNoYXJhY3RlcnMsIHVuZGVyc2NvcmVzLCBoeXBoZW5zLCBvciBkb3RzLgoKICAgICAgIEEgWUFORyBpZGVudGlmaWVyIE1VU1QgTk9UIHN0YXJ0IHdpdGggYW55IHBvc3NpYmxlCiAgICAgICBjb21iaW5hdGlvbiBvZiB0aGUgbG93ZXJjYXNlIG9yIHVwcGVyY2FzZSBjaGFyYWN0ZXIKICAgICAgIHNlcXVlbmNlICd4bWwnLiI7CiAgICByZWZlcmVuY2UKICAgICAgIlJGQyA2MDIwOiBZQU5HIC0gQSBEYXRhIE1vZGVsaW5nIExhbmd1YWdlIGZvciB0aGUgTmV0d29yawogICAgICAgICAgICAgICAgIENvbmZpZ3VyYXRpb24gUHJvdG9jb2wgKE5FVENPTkYpIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiB0eXBlcyByZWxhdGVkIHRvIGRhdGUgYW5kIHRpbWUqKiovCgogIHR5cGVkZWYgZGF0ZS1hbmQtdGltZSB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4gJ1xkezR9LVxkezJ9LVxkezJ9VFxkezJ9OlxkezJ9OlxkezJ9KFwuXGQrKT8nCiAgICAgICAgICAgICsgJyhafFtcK1wtXVxkezJ9OlxkezJ9KSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgZGF0ZS1hbmQtdGltZSB0eXBlIGlzIGEgcHJvZmlsZSBvZiB0aGUgSVNPIDg2MDEKICAgICAgc3RhbmRhcmQgZm9yIHJlcHJlc2VudGF0aW9uIG9mIGRhdGVzIGFuZCB0aW1lcyB1c2luZyB0aGUKICAgICAgR3JlZ29yaWFuIGNhbGVuZGFyLiAgVGhlIHByb2ZpbGUgaXMgZGVmaW5lZCBieSB0aGUKICAgICAgZGF0ZS10aW1lIHByb2R1Y3Rpb24gaW4gU2VjdGlvbiA1LjYgb2YgUkZDIDMzMzkuCgogICAgICBUaGUgZGF0ZS1hbmQtdGltZSB0eXBlIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgZGF0ZVRpbWUgWE1MCiAgICAgIHNjaGVtYSB0eXBlIHdpdGggdGhlIGZvbGxvd2luZyBub3RhYmxlIGV4Y2VwdGlvbnM6CgogICAgICAoYSkgVGhlIGRhdGUtYW5kLXRpbWUgdHlwZSBkb2VzIG5vdCBhbGxvdyBuZWdhdGl2ZSB5ZWFycy4KCiAgICAgIChiKSBUaGUgZGF0ZS1hbmQtdGltZSB0aW1lLW9mZnNldCAtMDA6MDAgaW5kaWNhdGVzIGFuIHVua25vd24KICAgICAgICAgIHRpbWUgem9uZSAoc2VlIFJGQyAzMzM5KSB3aGlsZSAtMDA6MDAgYW5kICswMDowMCBhbmQgWgogICAgICAgICAgYWxsIHJlcHJlc2VudCB0aGUgc2FtZSB0aW1lIHpvbmUgaW4gZGF0ZVRpbWUuCgogICAgICAoYykgVGhlIGNhbm9uaWNhbCBmb3JtYXQgKHNlZSBiZWxvdykgb2YgZGF0YS1hbmQtdGltZSB2YWx1ZXMKICAgICAgICAgIGRpZmZlcnMgZnJvbSB0aGUgY2Fub25pY2FsIGZvcm1hdCB1c2VkIGJ5IHRoZSBkYXRlVGltZSBYTUwKICAgICAgICAgIHNjaGVtYSB0eXBlLCB3aGljaCByZXF1aXJlcyBhbGwgdGltZXMgdG8gYmUgaW4gVVRDIHVzaW5nCiAgICAgICAgICB0aGUgdGltZS1vZmZzZXQgJ1onLgoKICAgICAgVGhpcyB0eXBlIGlzIG5vdCBlcXVpdmFsZW50IHRvIHRoZSBEYXRlQW5kVGltZSB0ZXh0dWFsCiAgICAgIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyIHNpbmNlIFJGQyAzMzM5IHVzZXMgYSBkaWZmZXJlbnQKICAgICAgc2VwYXJhdG9yIGJldHdlZW4gZnVsbC1kYXRlIGFuZCBmdWxsLXRpbWUgYW5kIHByb3ZpZGVzCiAgICAgIGhpZ2hlciByZXNvbHV0aW9uIG9mIHRpbWUtc2VjZnJhYy4KCiAgICAgIFRoZSBjYW5vbmljYWwgZm9ybWF0IGZvciBkYXRlLWFuZC10aW1lIHZhbHVlcyB3aXRoIGEga25vd24gdGltZQogICAgICB6b25lIHVzZXMgYSBudW1lcmljIHRpbWUgem9uZSBvZmZzZXQgdGhhdCBpcyBjYWxjdWxhdGVkIHVzaW5nCiAgICAgIHRoZSBkZXZpY2UncyBjb25maWd1cmVkIGtub3duIG9mZnNldCB0byBVVEMgdGltZS4gIEEgY2hhbmdlIG9mCiAgICAgIHRoZSBkZXZpY2UncyBvZmZzZXQgdG8gVVRDIHRpbWUgd2lsbCBjYXVzZSBkYXRlLWFuZC10aW1lIHZhbHVlcwogICAgICB0byBjaGFuZ2UgYWNjb3JkaW5nbHkuICBTdWNoIGNoYW5nZXMgbWlnaHQgaGFwcGVuIHBlcmlvZGljYWxseQogICAgICBpbiBjYXNlIGEgc2VydmVyIGZvbGxvd3MgYXV0b21hdGljYWxseSBkYXlsaWdodCBzYXZpbmcgdGltZQogICAgICAoRFNUKSB0aW1lIHpvbmUgb2Zmc2V0IGNoYW5nZXMuICBUaGUgY2Fub25pY2FsIGZvcm1hdCBmb3IKICAgICAgZGF0ZS1hbmQtdGltZSB2YWx1ZXMgd2l0aCBhbiB1bmtub3duIHRpbWUgem9uZSAodXN1YWxseQogICAgICByZWZlcnJpbmcgdG8gdGhlIG5vdGlvbiBvZiBsb2NhbCB0aW1lKSB1c2VzIHRoZSB0aW1lLW9mZnNldAogICAgICAtMDA6MDAuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMzMzOTogRGF0ZSBhbmQgVGltZSBvbiB0aGUgSW50ZXJuZXQ6IFRpbWVzdGFtcHMKICAgICAgUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyCiAgICAgIFhTRC1UWVBFUzogWE1MIFNjaGVtYSBQYXJ0IDI6IERhdGF0eXBlcyBTZWNvbmQgRWRpdGlvbiI7CiAgfQoKICB0eXBlZGVmIHRpbWV0aWNrcyB7CiAgICB0eXBlIHVpbnQzMjsKICAgIGRlc2NyaXB0aW9uCiAgICAgIlRoZSB0aW1ldGlja3MgdHlwZSByZXByZXNlbnRzIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgdGhhdAogICAgICByZXByZXNlbnRzIHRoZSB0aW1lLCBtb2R1bG8gMl4zMiAoNDI5NDk2NzI5NiBkZWNpbWFsKSwgaW4KICAgICAgaHVuZHJlZHRocyBvZiBhIHNlY29uZCBiZXR3ZWVuIHR3byBlcG9jaHMuICBXaGVuIGEgc2NoZW1hCiAgICAgIG5vZGUgaXMgZGVmaW5lZCB0aGF0IHVzZXMgdGhpcyB0eXBlLCB0aGUgZGVzY3JpcHRpb24gb2YKICAgICAgdGhlIHNjaGVtYSBub2RlIGlkZW50aWZpZXMgYm90aCBvZiB0aGUgcmVmZXJlbmNlIGVwb2Nocy4KCiAgICAgIEluIHRoZSB2YWx1ZSBzZXQgYW5kIGl0cyBzZW1hbnRpY3MsIHRoaXMgdHlwZSBpcyBlcXVpdmFsZW50CiAgICAgIHRvIHRoZSBUaW1lVGlja3MgdHlwZSBvZiB0aGUgU01JdjIuIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgMjU3ODogU3RydWN0dXJlIG9mIE1hbmFnZW1lbnQgSW5mb3JtYXRpb24gVmVyc2lvbiAyCiAgICAgICAgICAgICAgICAoU01JdjIpIjsKICB9CgogIHR5cGVkZWYgdGltZXN0YW1wIHsKICAgIHR5cGUgeWFuZzp0aW1ldGlja3M7CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgdGltZXN0YW1wIHR5cGUgcmVwcmVzZW50cyB0aGUgdmFsdWUgb2YgYW4gYXNzb2NpYXRlZAogICAgICB0aW1ldGlja3Mgc2NoZW1hIG5vZGUgYXQgd2hpY2ggYSBzcGVjaWZpYyBvY2N1cnJlbmNlCiAgICAgIGhhcHBlbmVkLiAgVGhlIHNwZWNpZmljIG9jY3VycmVuY2UgbXVzdCBiZSBkZWZpbmVkIGluIHRoZQogICAgICBkZXNjcmlwdGlvbiBvZiBhbnkgc2NoZW1hIG5vZGUgZGVmaW5lZCB1c2luZyB0aGlzIHR5cGUuICBXaGVuCiAgICAgIHRoZSBzcGVjaWZpYyBvY2N1cnJlbmNlIG9jY3VycmVkIHByaW9yIHRvIHRoZSBsYXN0IHRpbWUgdGhlCiAgICAgIGFzc29jaWF0ZWQgdGltZXRpY2tzIGF0dHJpYnV0ZSB3YXMgemVybywgdGhlbiB0aGUgdGltZXN0YW1wCiAgICAgIHZhbHVlIGlzIHplcm8uICBOb3RlIHRoYXQgdGhpcyByZXF1aXJlcyBhbGwgdGltZXN0YW1wIHZhbHVlcwogICAgICB0byBiZSByZXNldCB0byB6ZXJvIHdoZW4gdGhlIHZhbHVlIG9mIHRoZSBhc3NvY2lhdGVkIHRpbWV0aWNrcwogICAgICBhdHRyaWJ1dGUgcmVhY2hlcyA0OTcrIGRheXMgYW5kIHdyYXBzIGFyb3VuZCB0byB6ZXJvLgoKICAgICAgVGhlIGFzc29jaWF0ZWQgdGltZXRpY2tzIHNjaGVtYSBub2RlIG11c3QgYmUgc3BlY2lmaWVkCiAgICAgIGluIHRoZSBkZXNjcmlwdGlvbiBvZiBhbnkgc2NoZW1hIG5vZGUgdXNpbmcgdGhpcyB0eXBlLgoKICAgICAgSW4gdGhlIHZhbHVlIHNldCBhbmQgaXRzIHNlbWFudGljcywgdGhpcyB0eXBlIGlzIGVxdWl2YWxlbnQKICAgICAgdG8gdGhlIFRpbWVTdGFtcCB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBnZW5lcmljIGFkZHJlc3MgdHlwZXMgKioqLwoKICB0eXBlZGVmIHBoeXMtYWRkcmVzcyB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4gJyhbMC05YS1mQS1GXXsyfSg6WzAtOWEtZkEtRl17Mn0pKik/JzsKICAgIH0KCgoKCiAgICBkZXNjcmlwdGlvbgogICAgICJSZXByZXNlbnRzIG1lZGlhLSBvciBwaHlzaWNhbC1sZXZlbCBhZGRyZXNzZXMgcmVwcmVzZW50ZWQKICAgICAgYXMgYSBzZXF1ZW5jZSBvY3RldHMsIGVhY2ggb2N0ZXQgcmVwcmVzZW50ZWQgYnkgdHdvIGhleGFkZWNpbWFsCiAgICAgIG51bWJlcnMuICBPY3RldHMgYXJlIHNlcGFyYXRlZCBieSBjb2xvbnMuICBUaGUgY2Fub25pY2FsCiAgICAgIHJlcHJlc2VudGF0aW9uIHVzZXMgbG93ZXJjYXNlIGNoYXJhY3RlcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgUGh5c0FkZHJlc3MgdGV4dHVhbCBjb252ZW50aW9uIG9mIHRoZSBTTUl2Mi4iOwogICAgcmVmZXJlbmNlCiAgICAgIlJGQyAyNTc5OiBUZXh0dWFsIENvbnZlbnRpb25zIGZvciBTTUl2MiI7CiAgfQoKICB0eXBlZGVmIG1hYy1hZGRyZXNzIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnWzAtOWEtZkEtRl17Mn0oOlswLTlhLWZBLUZdezJ9KXs1fSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJUaGUgbWFjLWFkZHJlc3MgdHlwZSByZXByZXNlbnRzIGFuIElFRUUgODAyIE1BQyBhZGRyZXNzLgogICAgICBUaGUgY2Fub25pY2FsIHJlcHJlc2VudGF0aW9uIHVzZXMgbG93ZXJjYXNlIGNoYXJhY3RlcnMuCgogICAgICBJbiB0aGUgdmFsdWUgc2V0IGFuZCBpdHMgc2VtYW50aWNzLCB0aGlzIHR5cGUgaXMgZXF1aXZhbGVudAogICAgICB0byB0aGUgTWFjQWRkcmVzcyB0ZXh0dWFsIGNvbnZlbnRpb24gb2YgdGhlIFNNSXYyLiI7CiAgICByZWZlcmVuY2UKICAgICAiSUVFRSA4MDI6IElFRUUgU3RhbmRhcmQgZm9yIExvY2FsIGFuZCBNZXRyb3BvbGl0YW4gQXJlYQogICAgICAgICAgICAgICAgTmV0d29ya3M6IE92ZXJ2aWV3IGFuZCBBcmNoaXRlY3R1cmUKICAgICAgUkZDIDI1Nzk6IFRleHR1YWwgQ29udmVudGlvbnMgZm9yIFNNSXYyIjsKICB9CgogIC8qKiogY29sbGVjdGlvbiBvZiBYTUwtc3BlY2lmaWMgdHlwZXMgKioqLwoKICB0eXBlZGVmIHhwYXRoMS4wIHsKICAgIHR5cGUgc3RyaW5nOwogICAgZGVzY3JpcHRpb24KICAgICAiVGhpcyB0eXBlIHJlcHJlc2VudHMgYW4gWFBBVEggMS4wIGV4cHJlc3Npb24uCgogICAgICBXaGVuIGEgc2NoZW1hIG5vZGUgaXMgZGVmaW5lZCB0aGF0IHVzZXMgdGhpcyB0eXBlLCB0aGUKICAgICAgZGVzY3JpcHRpb24gb2YgdGhlIHNjaGVtYSBub2RlIE1VU1Qgc3BlY2lmeSB0aGUgWFBhdGgKICAgICAgY29udGV4dCBpbiB3aGljaCB0aGUgWFBhdGggZXhwcmVzc2lvbiBpcyBldmFsdWF0ZWQuIjsKICAgIHJlZmVyZW5jZQogICAgICJYUEFUSDogWE1MIFBhdGggTGFuZ3VhZ2UgKFhQYXRoKSBWZXJzaW9uIDEuMCI7CiAgfQoKICAvKioqIGNvbGxlY3Rpb24gb2Ygc3RyaW5nIHR5cGVzICoqKi8KCiAgdHlwZWRlZiBoZXgtc3RyaW5nIHsKICAgIHR5cGUgc3RyaW5nIHsKICAgICAgcGF0dGVybiAnKFswLTlhLWZBLUZdezJ9KDpbMC05YS1mQS1GXXsyfSkqKT8nOwogICAgfQogICAgZGVzY3JpcHRpb24KICAgICAiQSBoZXhhZGVjaW1hbCBzdHJpbmcgd2l0aCBvY3RldHMgcmVwcmVzZW50ZWQgYXMgaGV4IGRpZ2l0cwogICAgICBzZXBhcmF0ZWQgYnkgY29sb25zLiAgVGhlIGNhbm9uaWNhbCByZXByZXNlbnRhdGlvbiB1c2VzCiAgICAgIGxvd2VyY2FzZSBjaGFyYWN0ZXJzLiI7CiAgfQoKICB0eXBlZGVmIHV1aWQgewogICAgdHlwZSBzdHJpbmcgewogICAgICBwYXR0ZXJuICdbMC05YS1mQS1GXXs4fS1bMC05YS1mQS1GXXs0fS1bMC05YS1mQS1GXXs0fS0nCiAgICAgICAgICAgICsgJ1swLTlhLWZBLUZdezR9LVswLTlhLWZBLUZdezEyfSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICJBIFVuaXZlcnNhbGx5IFVuaXF1ZSBJRGVudGlmaWVyIGluIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24KICAgICAgZGVmaW5lZCBpbiBSRkMgNDEyMi4gIFRoZSBjYW5vbmljYWwgcmVwcmVzZW50YXRpb24gdXNlcwogICAgICBsb3dlcmNhc2UgY2hhcmFjdGVycy4KCiAgICAgIFRoZSBmb2xsb3dpbmcgaXMgYW4gZXhhbXBsZSBvZiBhIFVVSUQgaW4gc3RyaW5nIHJlcHJlc2VudGF0aW9uOgogICAgICBmODFkNGZhZS03ZGVjLTExZDAtYTc2NS0wMGEwYzkxZTZiZjYKICAgICAgIjsKICAgIHJlZmVyZW5jZQogICAgICJSRkMgNDEyMjogQSBVbml2ZXJzYWxseSBVbmlxdWUgSURlbnRpZmllciAoVVVJRCkgVVJOCiAgICAgICAgICAgICAgICBOYW1lc3BhY2UiOwogIH0KCiAgdHlwZWRlZiBkb3R0ZWQtcXVhZCB7CiAgICB0eXBlIHN0cmluZyB7CiAgICAgIHBhdHRlcm4KICAgICAgICAnKChbMC05XXxbMS05XVswLTldfDFbMC05XVswLTldfDJbMC00XVswLTldfDI1WzAtNV0pXC4pezN9JwogICAgICArICcoWzAtOV18WzEtOV1bMC05XXwxWzAtOV1bMC05XXwyWzAtNF1bMC05XXwyNVswLTVdKSc7CiAgICB9CiAgICBkZXNjcmlwdGlvbgogICAgICAiQW4gdW5zaWduZWQgMzItYml0IG51bWJlciBleHByZXNzZWQgaW4gdGhlIGRvdHRlZC1xdWFkCiAgICAgICBub3RhdGlvbiwgaS5lLiwgZm91ciBvY3RldHMgd3JpdHRlbiBhcyBkZWNpbWFsIG51bWJlcnMKICAgICAgIGFuZCBzZXBhcmF0ZWQgd2l0aCB0aGUgJy4nIChmdWxsIHN0b3ApIGNoYXJhY3Rlci4iOwogIH0KfQ== +o-ran-smo-teiv-common-yang-extensions urn:o-ran:smo-teiv-common-yang-extensions \N [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgewogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOm8tcmFuOnNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMiOwogICAgcHJlZml4IG9yLXRlaXYteWV4dDsKCiAgICBvcmdhbml6YXRpb24gIkVyaWNzc29uIEFCIjsKICAgIGNvbnRhY3QgIkVyaWNzc29uIGZpcnN0IGxpbmUgc3VwcG9ydCB2aWEgZW1haWwiOwogICAgZGVzY3JpcHRpb24KICAgICJUb3BvbG9neSBhbmQgSW52ZW50b3J5IFlBTkcgZXh0ZW5zaW9ucyBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyBleHRlbnNpb25zIHRvIHRoZSBZQU5HIGxhbmd1YWdlIHRoYXQgdG9wb2xvZ3kgYW5kCiAgICBpbnZlbnRvcnkgbW9kZWxzIHdpbGwgdXNlIHRvIGRlZmluZSBhbmQgYW5ub3RhdGUgdHlwZXMgYW5kIHJlbGF0aW9uc2hpcHMuIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0yNCIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIGV4dGVuc2lvbiBiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJEZWZpbmVzIGEgYmktZGlyZWN0aW9uYWwgcmVsYXRpb25zaGlwIGluIHRoZSB0b3BvbG9neS4KCiAgICAgICAgICAgIEEgYmktZGlyZWN0aW9uYWwtYXNzb2NpYXRpb24gKEJEQSkgaXMgYSByZWxhdGlvbnNoaXAgY29tcHJpc2luZyBvZgogICAgICAgICAgICBhbiBBLXNpZGUgYW5kIGEgQi1zaWRlLiBUaGUgQS1zaWRlIGlzIGNvbnNpZGVyZWQgdGhlIG9yaWdpbmF0aW5nCiAgICAgICAgICAgIHNpZGUgb2YgdGhlIHJlbGF0aW9uc2hpcDsgdGhlIEItc2lkZSBpcyBjb25zaWRlcmVkIHRoZSB0ZXJtaW5hdGluZwogICAgICAgICAgICBzaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSBvcmRlciBvZiBBLXNpZGUgYW5kIEItc2lkZSBpcyBvZgogICAgICAgICAgICBpbXBvcnRhbmNlIGFuZCBNVVNUIE5PVCBiZSBjaGFuZ2VkIG9uY2UgZGVmaW5lZC4KCiAgICAgICAgICAgIEJvdGggQS1zaWRlIGFuZCBCLXNpZGUgYXJlIGRlZmluZWQgb24gYSB0eXBlLCBhbmQgYXJlIGdpdmVuIGEgcm9sZS4KICAgICAgICAgICAgQSB0eXBlIG1heSBoYXZlIG11bHRpcGxlIG9yaWdpbmF0aW5nIGFuZC9vciB0ZXJtaW5hdGluZyBzaWRlcyBvZiBhCiAgICAgICAgICAgIHJlbGF0aW9uc2hpcCwgYWxsIGRpc3Rpbmd1aXNoZWQgYnkgcm9sZSBuYW1lLgoKICAgICAgICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIG9ubHkgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlICdtb2R1bGUnIHN0YXRlbWVudC4KICAgICAgICAgICAgTXVsdGlwbGUgJ2JpLWRpcmVjdGlvbmFsLXRvcG9sb2d5LXJlbGF0aW9uc2hpcCcgc3RhdGVtZW50cyBhcmUKICAgICAgICAgICAgYWxsb3dlZCBwZXIgcGFyZW50IHN0YXRlbWVudC4KCiAgICAgICAgICAgIFN1YnN0YXRlbWVudHMgdG8gdGhlICdiaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIGRlZmluZQogICAgICAgICAgICB0aGUgQS1zaWRlIGFuZCB0aGUgQi1zaWRlLCByZXNwZWN0aXZlbHksIGFuZCBvcHRpb25hbGx5IHByb3BlcnRpZXMKICAgICAgICAgICAgb2YgdGhlIHJlbGF0aW9uc2hpcC4gRGF0YSBub2RlcyBvZiB0eXBlcyAnbGVhZicgYW5kICdsZWFmLWxpc3QnIGFyZQogICAgICAgICAgICB1c2VkIGZvciB0aGlzIHB1cnBvc2UuIE9uZSBvZiB0aGUgZGF0YSBub2RlcyBNVVNUIGJlIGFubm90YXRlZCB3aXRoCiAgICAgICAgICAgIHRoZSAnYS1zaWRlJyBleHRlbnNpb247IGFub3RoZXIgZGF0YSBub2RlIE1VU1QgYmUgYW5ub3RhdGVkIHdpdGggdGhlCiAgICAgICAgICAgICdiLXNpZGUnIGV4dGVuc2lvbi4gT3RoZXIgZGF0YSBub2RlcyBkZWZpbmUgcHJvcGVydGllcyBvZiB0aGUKICAgICAgICAgICAgcmVsYXRpb25zaGlwLgoKICAgICAgICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSByZWxhdGlvbnNoaXAgbmFtZQogICAgICAgICAgICBpcyBzY29wZWQgdG8gdGhlIG5hbWVzcGFjZSBvZiB0aGUgZGVjbGFyaW5nIG1vZHVsZSBhbmQgTVVTVCBiZQogICAgICAgICAgICB1bmlxdWUgd2l0aGluIHRoZSBzY29wZS4iOwoKICAgICAgICBhcmd1bWVudCByZWxhdGlvbnNoaXBOYW1lOwogICAgfQoKICAgIGV4dGVuc2lvbiBhU2lkZSB7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICAgICAgIkRlZmluZXMgdGhlIEEtc2lkZSBvZiBhIHJlbGF0aW9uc2hpcC4KCiAgICAgICAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIGEgJ2xlYWYnIG9yICdsZWFmLWxpc3QnCiAgICAgICAgICAgIHN0YXRlbWVudCwgd2hpY2ggaXRzZWxmIG11c3QgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgdGhlCiAgICAgICAgICAgICd1bmktZGlyZWN0aW9uYWwtdG9wb2xvZ3ktcmVsYXRpb25zaGlwJyBzdGF0ZW1lbnQuCgogICAgICAgICAgICBUaGUgZGF0YSB0eXBlIG9mIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIE1VU1QgYmUKICAgICAgICAgICAgJ2luc3RhbmNlLWlkZW50aWZpZXInLiBDb25zdHJhaW50cyBNQVkgYmUgdXNlZCBhcyBwYXJ0IG9mIHRoZSBwYXJlbnQKICAgICAgICAgICAgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIHRvIGVuZm9yY2UgY2FyZGluYWxpdHkuCgogICAgICAgICAgICBUaGUgaWRlbnRpZmllciBvZiB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBpcyB1c2VkIGFzIG5hbWUKICAgICAgICAgICAgb2YgdGhlIHJvbGUgb2YgdGhlIEEtc2lkZSBvZiB0aGUgcmVsYXRpb25zaGlwLiBUaGUgbmFtZSBvZiB0aGUgcm9sZQogICAgICAgICAgICBpcyBzY29wZWQgdG8gdGhlIHR5cGUgb24gd2hpY2ggdGhlIEEtc2lkZSBpcyBkZWZpbmVkIGFuZCBNVVNUIGJlCiAgICAgICAgICAgIHVuaXF1ZSB3aXRoaW4gdGhlIHNjb3BlLgoKICAgICAgICAgICAgV2hpbGUgdGhlIHBhcmVudCAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgZG9lcyBub3QgcmVzdWx0IGluIGEgcHJvcGVydHkKICAgICAgICAgICAgb2YgdGhlIHJlbGF0aW9uc2hpcCwgaXQgaXMgUkVDT01NRU5ERUQgdG8gYXZvaWQgdXNpbmcgdGhlIG5hbWUgb2YgYW4KICAgICAgICAgICAgZXhpc3RpbmcgdHlwZSBwcm9wZXJ0eSBhcyByb2xlIG5hbWUgdG8gYXZvaWQgcG90ZW50aWFsIGFtYmlndWl0aWVzCiAgICAgICAgICAgIGJldHdlZW4gcHJvcGVydGllcyBvZiBhIHR5cGUsIGFuZCByb2xlcyBvZiBhIHJlbGF0aW9uc2hpcCBvbiB0aGUKICAgICAgICAgICAgdHlwZS4KCiAgICAgICAgICAgIFRoZSBhcmd1bWVudCBpcyB0aGUgbmFtZSBvZiB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQS1zaWRlIHJlc2lkZXMuCiAgICAgICAgICAgIElmIHRoZSB0eXBlIGlzIGRlY2xhcmVkIGluIGFub3RoZXIgbW9kdWxlLCB0aGUgdHlwZSBtdXN0IGJlCiAgICAgICAgICAgIHByZWZpeGVkLCBhbmQgYSBjb3JyZXNwb25kaW5nICdpbXBvcnQnIHN0YXRlbWVudCBiZSB1c2VkIHRvIGRlY2xhcmUKICAgICAgICAgICAgdGhlIHByZWZpeC4iOwoKICAgICAgICBhcmd1bWVudCBhU2lkZVR5cGU7CiAgICB9CgogICAgZXh0ZW5zaW9uIGJTaWRlIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiRGVmaW5lcyB0aGUgQi1zaWRlIG9mIGEgcmVsYXRpb25zaGlwLgoKICAgICAgICAgICAgVGhlIHN0YXRlbWVudCBNVVNUIG9ubHkgYmUgYSBzdWJzdGF0ZW1lbnQgb2YgYSAnbGVhZicgb3IgJ2xlYWYtbGlzdCcKICAgICAgICAgICAgc3RhdGVtZW50LCB3aGljaCBpdHNlbGYgbXVzdCBiZSBhIHN1YnN0YXRlbWVudCBvZiB0aGUKICAgICAgICAgICAgJ3VuaS1kaXJlY3Rpb25hbC10b3BvbG9neS1yZWxhdGlvbnNoaXAnIHN0YXRlbWVudC4KCiAgICAgICAgICAgIFRoZSBkYXRhIHR5cGUgb2YgdGhlIHBhcmVudCAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgTVVTVCBiZQogICAgICAgICAgICAnaW5zdGFuY2UtaWRlbnRpZmllcicuIENvbnN0cmFpbnRzIE1BWSBiZSB1c2VkIGFzIHBhcnQgb2YgdGhlIHBhcmVudAogICAgICAgICAgICAnbGVhZicgb3IgJ2xlYWYtbGlzdCcgdG8gZW5mb3JjZSBjYXJkaW5hbGl0eS4KCiAgICAgICAgICAgIFRoZSBpZGVudGlmaWVyIG9mIHRoZSBwYXJlbnQgJ2xlYWYnIG9yICdsZWFmLWxpc3QnIGlzIHVzZWQgYXMgbmFtZQogICAgICAgICAgICBvZiB0aGUgcm9sZSBvZiB0aGUgQi1zaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAuIFRoZSBuYW1lIG9mIHRoZSByb2xlCiAgICAgICAgICAgIGlzIHNjb3BlZCB0byB0aGUgdHlwZSBvbiB3aGljaCB0aGUgQi1zaWRlIGlzIGRlZmluZWQgYW5kIE1VU1QgYmUKICAgICAgICAgICAgdW5pcXVlIHdpdGhpbiB0aGUgc2NvcGUuCgogICAgICAgICAgICBXaGlsZSB0aGUgcGFyZW50ICdsZWFmJyBvciAnbGVhZi1saXN0JyBkb2VzIG5vdCByZXN1bHQgaW4gYSBwcm9wZXJ0eQogICAgICAgICAgICBvZiB0aGUgcmVsYXRpb25zaGlwLCBpdCBpcyBSRUNPTU1FTkRFRCB0byBhdm9pZCB1c2luZyB0aGUgbmFtZSBvZiBhbgogICAgICAgICAgICBleGlzdGluZyB0eXBlIHByb3BlcnR5IGFzIHJvbGUgbmFtZSB0byBhdm9pZCBwb3RlbnRpYWwgYW1iaWd1aXRpZXMKICAgICAgICAgICAgYmV0d2VlbiBwcm9wZXJ0aWVzIG9mIGEgdHlwZSwgYW5kIHJvbGVzIG9mIGEgcmVsYXRpb25zaGlwIG9uIHRoZQogICAgICAgICAgICB0eXBlLgoKICAgICAgICAgICAgVGhlIGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSB0eXBlIG9uIHdoaWNoIHRoZSBCLXNpZGUgcmVzaWRlcy4KICAgICAgICAgICAgSWYgdGhlIHR5cGUgaXMgZGVjbGFyZWQgaW4gYW5vdGhlciBtb2R1bGUsIHRoZSB0eXBlIG11c3QgYmUKICAgICAgICAgICAgcHJlZml4ZWQsIGFuZCBhIGNvcnJlc3BvbmRpbmcgJ2ltcG9ydCcgc3RhdGVtZW50IGJlIHVzZWQgdG8gZGVjbGFyZQogICAgICAgICAgICB0aGUgcHJlZml4LiI7CgogICAgICAgIGFyZ3VtZW50IGJTaWRlVHlwZTsKICAgIH0KCiAgICBleHRlbnNpb24gZG9tYWluIHsKICAgICAgICBkZXNjcmlwdGlvbiAiS2V5d29yZCB1c2VkIHRvIGNhcnJ5IGRvbWFpbiBpbmZvcm1hdGlvbi4iOwogICAgICAgIGFyZ3VtZW50IGRvbWFpbk5hbWU7CiAgICB9CgogICAgZXh0ZW5zaW9uIGxhYmVsIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhlIGxhYmVsIGNhbiBiZSB1c2VkIHRvIGdpdmUgbW9kdWxlcyBhbmQgc3VibW9kdWxlcyBhIHNlbWFudGljCiAgICAgICAgICAgIHZlcnNpb24sIGluIGFkZGl0aW9uIHRvIHRoZWlyIHJldmlzaW9uLgoKICAgICAgICAgICAgVGhlIGZvcm1hdCBvZiB0aGUgbGFiZWwgaXMg4oCYeC55LnrigJkg4oCTIGV4cHJlc3NlZCBhcyBwYXR0ZXJuLCBpdCBpcwogICAgICAgICAgICBbMC05XStcXC5bMC05XStcXC5bMC05XSsKCiAgICAgICAgICAgIFRoZSBzdGF0ZW1lbnQgTVVTVCBvbmx5IGJlIGEgc3Vic3RhdGVtZW50IG9mIHRoZSByZXZpc2lvbiBzdGF0ZW1lbnQuCiAgICAgICAgICAgIFplcm8gb3Igb25lIHJldmlzaW9uIGxhYmVsIHN0YXRlbWVudHMgcGVyIHBhcmVudCBzdGF0ZW1lbnQgYXJlCiAgICAgICAgICAgIGFsbG93ZWQuCgogICAgICAgICAgICBSZXZpc2lvbiBsYWJlbHMgTVVTVCBiZSB1bmlxdWUgYW1vbmdzdCBhbGwgcmV2aXNpb25zIG9mIGEgbW9kdWxlIG9yCiAgICAgICAgICAgIHN1Ym1vZHVsZS4iOwoKICAgICAgICBhcmd1bWVudCBzZW12ZXJzaW9uOwogICAgfQp9 +o-ran-smo-teiv-common-yang-types urn:o-ran:smo-teiv-common-yang-types \N [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyI7CiAgICBwcmVmaXggb3ItdGVpdi10eXBlczsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7IHByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgXzNncHAtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggdHlwZXMzZ3BwOyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiVG9wb2xvZ3kgYW5kIEludmVudG9yeSBjb21tb24gdHlwZXMgbW9kZWwuCgogICAgQ29weXJpZ2h0IChjKSAyMDI0IEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKICAgIFRoaXMgbW9kZWwgY29udGFpbnMgcmUtdXNhYmxlIGRhdGEgdHlwZXMgdGhhdCB0b3BvbG9neSBhbmQgaW52ZW50b3J5IG1vZGVscwogICAgd2lsbCBmcmVxdWVudGx5IHVzZSBhcyBwYXJ0IG9mIHR5cGVzIGFuZCByZWxhdGlvbnNoaXBzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBncm91cGluZyBUb3BfR3JwX1R5cGUgewogICAgICAgIGRlc2NyaXB0aW9uICJHcm91cGluZyBjb250YWluaW5nIHRoZSBrZXkgYXR0cmlidXRlIGNvbW1vbiB0byBhbGwgdHlwZXMuCiAgICAgICAgICAgIEFsbCB0eXBlcyBNVVNUIHVzZSB0aGlzIGdyb3VwaW5nLiI7CgogICAgICAgIGxlYWYgaWQgewogICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVuaXF1ZSBpZGVudGlmaWVyIG9mIHRvcG9sb2d5IGVudGl0aWVzLiBSZXByZXNlbnRzIHRoZQogICAgICAgICAgICAgICAgRW50aXR5IEluc3RhbmNlIElkZW50aWZpZXIuIjsKICAgICAgICB9CiAgICB9CgogICAgY29udGFpbmVyIGRlY29yYXRvcnMgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJUaGlzIGNvbnRhaW5lciBzZXJ2ZXMgYXMgZXh0ZW5zaW9uIHBvaW50IGZvciBhcHBsaWNhdGlvbnMgd2lzaGluZwogICAgICAgICAgICB0byBkZWZpbmUgdGhlaXIgb3duIGRlY29yYXRvcnMuIFRoaXMgaXMgZG9uZSB2aWEgYXVnbWVudGF0aW9ucy4gVGhleQogICAgICAgICAgICBjYW4gb25seSBiZSBkZWZpbmVkIGluIG5hbWUgdmFsdWUgcGFpci4KCiAgICAgICAgICAgIFRoaXMgaXMgYSBjb25zdW1lciBkYXRhIGFuZCBjYW4gYmUgYXR0YWNoZWQgdG8gVG9wb2xvZ3kgRW50aXR5IG9yCiAgICAgICAgICAgIFRvcG9sb2d5IFJlbGF0aW9uIGluc3RhbmNlLCBvdXRzaWRlIG9mIHRoZSBkZWNsYXJlZCBUb3BvbG9neSBFbnRpdHkKICAgICAgICAgICAgb3IgVG9wb2xvZ3kgUmVsYXRpb25zaGlwJ3MgYXR0cmlidXRlcy4gVGhpcyBjYW5ub3QgYmUgaW5zdGFudGlhdGVkLAogICAgICAgICAgICBhbmQgaXQgTVVTVCBOT1QgYmUgYXVnbWVudGVkIG9yIGRldmlhdGVkIGluIGFueSB3YXksIHVubGVzcyBzdGF0ZWQKICAgICAgICAgICAgb3RoZXJ3aXNlLiI7CiAgICB9CgogICAgbGVhZi1saXN0IGNsYXNzaWZpZXJzIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiQ29uc3VtZXIgZGVmaW5lZCB0YWdzIHRvIHRvcG9sb2d5IGVudGl0aWVzIGFuZCByZWxhdGlvbnNoaXBzLgoKICAgICAgICAgICAgVGhpcyBpcyBhIGNvbnN1bWVyIGRhdGEgYW5kIGNhbiBiZSBhdHRhY2hlZCB0byBUb3BvbG9neSBFbnRpdHkgb3IKICAgICAgICAgICAgVG9wb2xvZ3kgUmVsYXRpb24gaW5zdGFuY2UsIG91dHNpZGUgb2YgdGhlIGRlY2xhcmVkIFRvcG9sb2d5IEVudGl0eQogICAgICAgICAgICBvciBUb3BvbG9neSBSZWxhdGlvbnNoaXAncyBhdHRyaWJ1dGVzLiBUaGlzIGNhbm5vdCBiZSBpbnN0YW50aWF0ZWQsCiAgICAgICAgICAgIGFuZCBpdCBNVVNUIE5PVCBiZSBhdWdtZW50ZWQgb3IgZGV2aWF0ZWQgaW4gYW55IHdheSwgdW5sZXNzIHN0YXRlZAogICAgICAgICAgICBvdGhlcndpc2UuIjsKCiAgICAgICAgdHlwZSBpZGVudGl0eXJlZiB7IGJhc2UgY2xhc3NpZmllcjsgfQogICAgfQoKICAgIGxlYWYtbGlzdCBzb3VyY2VJZHMgewogICAgICAgIGRlc2NyaXB0aW9uCiAgICAgICAgICAgICJBbiBvcmRlcmVkIGxpc3Qgb2YgaWRlbnRpdGllcyB0aGF0IHJlcHJlc2VudCB0aGUgc2V0IG9mIG5hdGl2ZQogICAgICAgICAgICBzb3VyY2UgaWRlbnRpZmllcnMgZm9yIHBhcnRpY2lwYXRpbmcgZW50aXRpZXMuCgogICAgICAgICAgICBUaGlzIGlzIGEgY29uc3VtZXIgZGF0YSBhbmQgY2FuIGJlIGF0dGFjaGVkIHRvIFRvcG9sb2d5IEVudGl0eSBvcgogICAgICAgICAgICBUb3BvbG9neSBSZWxhdGlvbiBpbnN0YW5jZSwgb3V0c2lkZSBvZiB0aGUgZGVjbGFyZWQgVG9wb2xvZ3kgRW50aXR5CiAgICAgICAgICAgIG9yIFRvcG9sb2d5IFJlbGF0aW9uc2hpcCdzIGF0dHJpYnV0ZXMuIFRoaXMgY2Fubm90IGJlIGluc3RhbnRpYXRlZCwKICAgICAgICAgICAgYW5kIGl0IE1VU1QgTk9UIGJlIGF1Z21lbnRlZCBvciBkZXZpYXRlZCBpbiBhbnkgd2F5LCB1bmxlc3Mgc3RhdGVkCiAgICAgICAgICAgIG90aGVyd2lzZS4iOwoKICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICBvcmRlcmVkLWJ5IHVzZXI7CiAgICB9CgogICAgY29udGFpbmVyIG1ldGFkYXRhIHsKICAgICAgICBkZXNjcmlwdGlvbgogICAgICAgICAgICAiVGhpcyBjb250YWluZXIgc2VydmVzIGFzIGV4dGVuc2lvbiBwb2ludCB0byBkZWZpbmUgbWV0YWRhdGEuIFRoZXkKICAgICAgICAgICAgY2FuIG9ubHkgYmUgZGVmaW5lZCBpbiBuYW1lIHZhbHVlIHBhaXIuCgogICAgICAgICAgICBUaGlzIGlzIGEgY29uc3VtZXIgZGF0YSBhbmQgY2FuIGJlIGF0dGFjaGVkIHRvIFRvcG9sb2d5IEVudGl0eSBvcgogICAgICAgICAgICBUb3BvbG9neSBSZWxhdGlvbiBpbnN0YW5jZSwgb3V0c2lkZSBvZiB0aGUgZGVjbGFyZWQgVG9wb2xvZ3kgRW50aXR5CiAgICAgICAgICAgIG9yIFRvcG9sb2d5IFJlbGF0aW9uc2hpcCdzIGF0dHJpYnV0ZXMuIFRoaXMgY2Fubm90IGJlIGluc3RhbnRpYXRlZCwKICAgICAgICAgICAgYW5kIGl0IE1VU1QgTk9UIGJlIGF1Z21lbnRlZCBvciBkZXZpYXRlZCBpbiBhbnkgd2F5LCB1bmxlc3Mgc3RhdGVkCiAgICAgICAgICAgIG90aGVyd2lzZS4iOwogICAgfQoKICAgIGlkZW50aXR5IGNsYXNzaWZpZXJ7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjbGFzc2lmaWVyIGlzIHVzZWQgYXMgYSBiYXNlIHRvIHByb3ZpZGUgYWxsIGNsYXNzaWZpZXJzCiAgICAgICAgICAgIHdpdGggaWRlbnRpdHkuICI7CiAgICB9Cn0= +o-ran-smo-teiv-equipment urn:o-ran:smo-teiv-equipment EQUIPMENT [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LWVxdWlwbWVudCB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtZXF1aXBtZW50IjsKICAgIHByZWZpeCBvci10ZWl2LWVxdWlwOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgeyBwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgICAgICBwcmVmaXggZ2VvOwogICAgICAgIHJlZmVyZW5jZSAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIkVxdWlwbWVudCB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgRXF1aXBtZW50CiAgICBkb21haW4sIHdoaWNoIGlzIG1vZGVsbGVkIHRvIHVuZGVyc3RhbmQgdGhlIHBoeXNpY2FsIGxvY2F0aW9uIG9mIGVxdWlwbWVudAogICAgc3VjaCBhcyBhbnRlbm5hcyBhc3NvY2lhdGVkIHdpdGggYSBjZWxsL2NhcnJpZXIgYW5kIHRoZWlyIHJlbGV2YW50CiAgICBwcm9wZXJ0aWVzIGUuZy4gdGlsdCwgbWF4IHBvd2VyIGV0Yy4iOwoKICAgIHJldmlzaW9uICIyMDI0LTA1LTI0IiB7CiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmRvbWFpbiBFUVVJUE1FTlQ7CgogICAgbGlzdCBBbnRlbm5hTW9kdWxlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gQW50ZW5uYSBNb2R1bGUgcmVwcmVzZW50cyB0aGUgcGh5c2ljYWwgYXNwZWN0IG9mIGFuCiAgICAgICAgICAgIGFudGVubmEuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBhbnRlbm5hTW9kZWxOdW1iZXIgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlZlbmRvci1zcGVjaWZpYyBhbnRlbm5hIG1vZGVsIGlkZW50aWZpZXIuIFRoaXMKICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGUgaXMgcGFydCBvZiBBSVNHIHYzIEFEQiBTdGFuZGFyZCBhbmQgaGFzIG5vCiAgICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uYWwgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBtZWNoYW5pY2FsQW50ZW5uYUJlYXJpbmcgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgYmVhcmluZyBvbiBhbnRlbm5hIHN1YnVuaXQgd2hlcmUgYW50ZW5uYQogICAgICAgICAgICAgICAgICAgIHVuaXQgaXMgaW5zdGFsbGVkLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG1lY2hhbmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGZpeGVkIGFudGVubmEgdGlsdCBvZiB0aGUgaW5zdGFsbGF0aW9uLCBkZWZpbmVkCiAgICAgICAgICAgICAgICAgICAgYXMgdGhlIGluY2xpbmF0aW9uIG9mIHRoZSBhbnRlbm5hIGVsZW1lbnQgcmVzcGVjdCB0byB0aGUKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbCBwbGFuZS4gSXQgaXMgYSBzaWduZWQgdmFsdWUuIFBvc2l0aXZlIGluZGljYXRlcwogICAgICAgICAgICAgICAgICAgIGRvd250aWx0LCBhbmQgbmVnYXRpdmUgaW5kaWNhdGVzIHVwdGlsdC4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBwb3NpdGlvbldpdGhpblNlY3RvciB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSB1bml0IHBvc2l0aW9uIHdpdGhpbiBzZWN0b3IuIFRoaXMgYXR0cmlidXRlCiAgICAgICAgICAgICAgICAgICAgaXMgcGFydCBvZiBBSVNHIHYzIEFEQiBTdGFuZGFyZCBhbmQgaGFzIG5vIG9wZXJhdGlvbmFsCiAgICAgICAgICAgICAgICAgICAgaW1wYWN0LiI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiB0b3RhbFRpbHQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRvdGFsIGFudGVubmEgZWxldmF0aW9uIGluY2x1ZGluZyB0aGUgaW5zdGFsbGVkCiAgICAgICAgICAgICAgICAgICAgdGlsdCBhbmQgdGhlIHRpbHQgYXBwbGllZCBieSB0aGUgUmVtb3RlIEVsZWN0cmljYWwKICAgICAgICAgICAgICAgICAgICBUaWx0IChSRVQpLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVsZWN0cmljYWxBbnRlbm5hVGlsdCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiRWxlY3RyaWNhbGx5LWNvbnRyb2xsZWQgdGlsdCBvZiBtYWluIGJlYW0gbWF4aW11bQogICAgICAgICAgICAgICAgICAgIHdpdGggcmVzcGVjdCB0byBkaXJlY3Rpb24gb3J0aG9nb25hbCB0byBhbnRlbm5hIGVsZW1lbnQKICAgICAgICAgICAgICAgICAgICBheGlzIChzZWUgM0dQUCBUUyAyNS40NjYpLiBWYWx1ZSBpcyBzaWduZWQ7IHRpbHQgZG93biBpcwogICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlLCB0aWx0IHVwIGlzIG5lZ2F0aXZlLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmLWxpc3QgYW50ZW5uYUJlYW1XaWR0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGFuZ3VsYXIgc3BhbiBvZiB0aGUgbWFpbiBsb2JlIG9mIHRoZSBhbnRlbm5hCiAgICAgICAgICAgICAgICAgICAgcmFkaWF0aW9uIHBhdHRlcm4gaW4gdGhlIGhvcml6b250YWwgcGxhbmUuIE1lYXN1cmVkIGluCiAgICAgICAgICAgICAgICAgICAgZGVncmVlcy4iOwogICAgICAgICAgICAgICAgdHlwZSB1aW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHVzZXMgZ2VvOmdlby1sb2NhdGlvbjsKICAgICAgICB9CiAgICB9CgogICAgbGlzdCBTaXRlIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBzaXRlIGlzIGEgcGh5c2ljYWwgbG9jYXRpb24gd2hlcmUgYW4gZXF1aXBtZW50IGNhbiBiZQogICAgICAgICAgICBpbnN0YWxsZWQuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBuYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIFNpdGUiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHVzZXMgZ2VvOmdlby1sb2NhdGlvbjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBBTlRFTk5BTU9EVUxFX0lOU1RBTExFRF9BVF9TSVRFIHsgLy8gMC4ubiB0byAwLi4xCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmIGluc3RhbGxlZC1hdC1zaXRlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIGluc3RhbGxlZCBhdCBTaXRlLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgaW5zdGFsbGVkLWFudGVubmFNb2R1bGUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2l0ZSB3aGVyZSBBbnRlbm5hIE1vZHVsZSBpcyBpbnN0YWxsZWQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIFNpdGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9Cn0= +o-ran-smo-teiv-oam urn:o-ran:smo-teiv-oam OAM [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LW9hbSB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtb2FtIjsKICAgIHByZWZpeCBvci10ZWl2LW9hbTsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggb3ItdGVpdi10eXBlczsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHsgcHJlZml4IG9yLXRlaXYteWV4dDsgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIk8mTSB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgTyZNIGRvbWFpbiwKICAgIHdoaWNoIGFyZSBpbnRlbmRlZCB0byByZXByZXNlbnQgbWFuYWdlbWVudCBzeXN0ZW1zIGFuZCBtYW5hZ2VtZW50CiAgICBpbnRlcmZhY2VzLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIE9BTTsKCiAgICBsaXN0IE1hbmFnZWRFbGVtZW50IHsKICAgICAgICBkZXNjcmlwdGlvbiAiQSBNYW5hZ2VkIEVsZW1lbnQgKE1FKSBpcyBhIG5vZGUgaW50byBhIHRlbGVjb21tdW5pY2F0aW9uCiAgICAgICAgICAgIG5ldHdvcmsgcHJvdmlkaW5nIHN1cHBvcnQgYW5kL29yIHNlcnZpY2UgdG8gc3Vic2NyaWJlcnMuIEFuIE1FCiAgICAgICAgICAgIGNvbW11bmljYXRlcyB3aXRoIGEgbWFuYWdlciBhcHBsaWNhdGlvbiAoZGlyZWN0bHkgb3IgaW5kaXJlY3RseSkKICAgICAgICAgICAgb3ZlciBvbmUgb3IgbW9yZSBpbnRlcmZhY2VzIGZvciB0aGUgcHVycG9zZSBvZiBiZWluZyBtb25pdG9yZWQKICAgICAgICAgICAgYW5kL29yIGNvbnRyb2xsZWQuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CiAgICB9Cn0= +o-ran-smo-teiv-ran urn:o-ran:smo-teiv-ran RAN [] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJhbiB7CiAgICB5YW5nLXZlcnNpb24gMS4xOwogICAgbmFtZXNwYWNlICJ1cm46by1yYW46c21vLXRlaXYtcmFuIjsKICAgIHByZWZpeCBvci10ZWl2LXJhbjsKCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctdHlwZXMge3ByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMge3ByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgXzNncHAtY29tbW9uLXlhbmctdHlwZXMgeyBwcmVmaXggdHlwZXMzZ3BwOyB9CgogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsKICAgICAgICBwcmVmaXggZ2VvOwogICAgICAgIHJlZmVyZW5jZSAiUkZDIDkxNzk6IEEgWUFORyBHcm91cGluZyBmb3IgR2VvZ3JhcGhpYyBMb2NhdGlvbnMiOwogICAgfQoKICAgIG9yZ2FuaXphdGlvbiAiRXJpY3Nzb24gQUIiOwogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7CiAgICBkZXNjcmlwdGlvbgogICAgIlJBTiB0b3BvbG9neSBtb2RlbC4KCiAgICBDb3B5cmlnaHQgKGMpIDIwMjQgRXJpY3Nzb24gQUIuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgdG9wb2xvZ3kgZW50aXRpZXMgYW5kIHJlbGF0aW9ucyBpbiB0aGUgUkFOIGRvbWFpbiwKICAgIHdoaWNoIHJlcHJlc2VudHMgdGhlIGZ1bmN0aW9uYWwgY2FwYWJpbGl0eSBvZiB0aGUgZGVwbG95ZWQgUkFOIHRoYXQgYXJlCiAgICByZWxldmFudCB0byByQXBwcyB1c2UgY2FzZXMuIjsKCiAgICByZXZpc2lvbiAiMjAyNC0wNS0yNCIgewogICAgICAgIGRlc2NyaXB0aW9uICJJbml0aWFsIHJldmlzaW9uLiI7CiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOwogICAgfQoKICAgIG9yLXRlaXYteWV4dDpkb21haW4gUkFOOwoKICAgIGxpc3QgR05CRFVGdW5jdGlvbiB7CiAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQiBEaXN0cmlidXRlZCBVbml0IChnTkItRFUpLgoKICAgICAgICAgICAgQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ2VudHJhbGl6ZWQgVW5pdCAoZ05CLUNVKSBhbmQgYSBnTkItRFUuCiAgICAgICAgICAgIFRoZSBDVSBwcm9jZXNzZXMgbm9uLXJlYWwgdGltZSBwcm90b2NvbHMgYW5kIHNlcnZpY2VzLCBhbmQgdGhlIERVCiAgICAgICAgICAgIHByb2Nlc3NlcyBQSFkgbGV2ZWwgcHJvdG9jb2wgYW5kIHJlYWwgdGltZSBzZXJ2aWNlcy4gVGhlIGdOQi1DVSBhbmQKICAgICAgICAgICAgdGhlIGdOQi1EVSB1bml0cyBhcmUgY29ubmVjdGVkIHZpYSBGMSBsb2dpY2FsIGludGVyZmFjZS4KCiAgICAgICAgICAgIFRoZSBmb2xsb3dpbmcgaXMgdHJ1ZSBmb3IgYSBnTkItRFU6CiAgICAgICAgICAgIElzIGNvbm5lY3RlZCB0byB0aGUgZ05CLUNVLUNQIHRocm91Z2ggdGhlIEYxLUMgaW50ZXJmYWNlLiBJcwogICAgICAgICAgICBjb25uZWN0ZWQgdG8gdGhlIGdOQi1DVS1VUCB0aHJvdWdoIHRoZSBGMS1VIGludGVyZmFjZS4gT25lIGdOQi1EVSBpcwogICAgICAgICAgICBjb25uZWN0ZWQgdG8gb25seSBvbmUgZ05CLUNVLUNQLiBPbmUgZ05CLURVIGNhbiBiZSBjb25uZWN0ZWQgdG8KICAgICAgICAgICAgbXVsdGlwbGUgZ05CLUNVLVVQcyB1bmRlciB0aGUgY29udHJvbCBvZiB0aGUgc2FtZSBnTkItQ1UtQ1AuCgogICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUgZ05CLUNVLVVQcyBhbmQKICAgICAgICAgICAgbXVsdGlwbGUgZ05CLURVcy4gZ05CLURVIGlzIGEgY29uY3JldGUgY2xhc3MgdGhhdCBleHRlbmRzIHRoZSBORy1SQU4KICAgICAgICAgICAgbm9kZSBvYmplY3QuIEluIFRvcG9sb2d5LCB5b3UgY2FuIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQgZGVsZXRlCiAgICAgICAgICAgIHRoZSBnTkItRFUgb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGNvbnRhaW5lciBkVXBMTU5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBpZGVudGlmaWVyIHVzZWQgYXMgcGFydCBvZiBQTSBFdmVudHMgZGF0YSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZ05CRFVJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBEVSB3aXRoaW4gYSBnTm9kZUIiOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEdOQkNVQ1BGdW5jdGlvbiB7CiAgICAgICAgZGVzY3JpcHRpb24gImdOb2RlQiBDZW50cmFsaXplZCBVbml0IENvbnRyb2wgUGxhbmUgKGdOQi1DVS1DUCkKCiAgICAgICAgICAgIFRoaXMgaXMgYSBsb2dpY2FsIG5vZGUgaG9zdGluZyB0aGUgUmFkaW8gUmVzb3VyY2UgQ29udHJvbCAoUlJDKSBhbmQKICAgICAgICAgICAgdGhlIGNvbnRyb2wgcGxhbmUgcGFydCBvZiB0aGUgUGFja2V0IERhdGEgQ29udmVyZ2VuY2UgUHJvdG9jb2wKICAgICAgICAgICAgKFBEQ1ApIG9mIHRoZSBnTm9kZUIgQ2VudHJhbGl6ZWQgVW5pdCAoZ05CLUNVKSBmb3IgYW4gRS1VVFJBTiBnTm9kZUIKICAgICAgICAgICAgKGVuLWdOQikgb3IgYSBnTm9kZUIgKGdOQikuIFRoZSBnTkItQ1UtQ1AgdGVybWluYXRlcyB0aGUgRTEKICAgICAgICAgICAgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTkItQ1UtVVAgYW5kIHRoZSBGMS1DIGludGVyZmFjZQogICAgICAgICAgICBjb25uZWN0ZWQgd2l0aCB0aGUgZ05vZGVCIERpc3RyaWJ1dGVkIFVuaXQgKGdOQi1EVSkuCgogICAgICAgICAgICBUaGUgZm9sbG93aW5nIGlzIHRydWUgZm9yIGEgZ05CLUNVLUNQOgogICAgICAgICAgICBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1EVSB0aHJvdWdoIHRoZSBGMS1DIGludGVyZmFjZS4gSXMgY29ubmVjdGVkCiAgICAgICAgICAgIHRvIHRoZSBnTkItQ1UtVVAgdGhyb3VnaCB0aGUgRTEgaW50ZXJmYWNlLiBPbmx5IG9uZSBnTkItQ1UtQ1AgaXMKICAgICAgICAgICAgY29ubmVjdGVkIHRvIG9uZSBnTkItRFUuIE9ubHkgb25lIGdOQi1DVS1DUCBpcyBjb25uZWN0ZWQgdG8gb25lCiAgICAgICAgICAgIGdOQi1DVS1VUC4gT25lIGdOQi1EVSBjYW4gYmUgY29ubmVjdGVkIHRvIG11bHRpcGxlIGdOQi1DVS1VUHMgdW5kZXIKICAgICAgICAgICAgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLk9uZSBnTkItQ1UtVVAgY2FuIGJlIGNvbm5lY3RlZCB0bwogICAgICAgICAgICBtdWx0aXBsZSBEVXMgdW5kZXIgdGhlIGNvbnRyb2wgb2YgdGhlIHNhbWUgZ05CLUNVLUNQLgoKICAgICAgICAgICAgTm90ZTogQSBnTkIgbWF5IGNvbnNpc3Qgb2YgYSBnTkItQ1UtQ1AsIG11bHRpcGxlIGdOQi1DVS1VUHMgYW5kCiAgICAgICAgICAgIG11bHRpcGxlIGdOQi1EVXMuIEEgZ05CLUNVLUNQIGlzIGEgY29uY3JldGUgY2xhc3MgdGhhdCBleHRlbmRzIHRoZQogICAgICAgICAgICBORy1SQU4gbm9kZSBvYmplY3QuIEluIFRvcG9sb2d5LCB5b3UgY2FuIGNyZWF0ZSwgcmVhZCwgdXBkYXRlLCBhbmQKICAgICAgICAgICAgZGVsZXRlIHRoZSBnTkItQ1UtQ1Agb2JqZWN0LiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZ05CQ1VOYW1lIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOYW1lIG9mIGdOb2RlQi1DVSI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIHBMTU5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBpZGVudGlmaWVyIHRvIGJlIHVzZWQgYXMgcGFydCBvZiBnbG9iYWwgUkFOCiAgICAgICAgICAgICAgICAgICAgbm9kZSBpZGVudGl0eSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBHTkJDVVVQRnVuY3Rpb24gewogICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUIgQ2VudHJhbGl6ZWQgVW5pdCBVc2VyIFBsYW5lIChnTkItQ1UtVVApCgogICAgICAgICAgICBBIGdOQi1DVS1VUCBpcyBhIGxvZ2ljYWwgbm9kZSBob3N0aW5nIHRoZSBVc2VyIFBsYW5lIHBhcnQgb2YgdGhlCiAgICAgICAgICAgIFBhY2tldCBEYXRhIENvbnZlcmdlbmNlLCBQcm90b2NvbCAoUERDUCkgb2YgdGhlIGdOb2RlQiBDZW50cmFsaXplZAogICAgICAgICAgICBVbml0IChnTkItQ1UpIGZvciBhbiBFLVVUUkFOIGdOb2RlQiAoZW4tZ05CKSwgYW5kIHRoZSBVc2VyIFBsYW5lCiAgICAgICAgICAgIHBhcnQgb2YgdGhlIFBEQ1AgcHJvdG9jb2wgYW5kIHRoZSBTZXJ2aWNlIERhdGEgQWRhcHRhdGlvbiBQcm90b2NvbAogICAgICAgICAgICAoU0RBUCkgb2YgdGhlIGdOQi1DVSBmb3IgYSBnTm9kZUIgKGdOQikuIFRoZSBnTkItQ1UtVVAgdGVybWluYXRlcwogICAgICAgICAgICB0aGUgRTEgaW50ZXJmYWNlIGNvbm5lY3RlZCB3aXRoIHRoZSBnTkItQ1UtQ1AgYW5kIHRoZSBGMS1VIGludGVyZmFjZQogICAgICAgICAgICBjb25uZWN0ZWQgd2l0aCB0aGUgZ05vZGVCIERpc3RyaWJ1dGVkIFVuaXQgKGdOQi1EVSkuCgogICAgICAgICAgICBUaGUgZm9sbG93aW5nIGlzIHRydWUgZm9yIGEgZ05CLUNVLVVQOgogICAgICAgICAgICBJcyBjb25uZWN0ZWQgdG8gdGhlIGdOQi1EVSB0aHJvdWdoIHRoZSBGMS1VIGludGVyZmFjZS4gSXMgY29ubmVjdGVkCiAgICAgICAgICAgIHRvIHRoZSBnTkItQ1UtQ1AgdGhyb3VnaCB0aGUgRTEgaW50ZXJmYWNlLiBPbmUgZ05CLUNVLVVQIGlzCiAgICAgICAgICAgIGNvbm5lY3RlZCB0byBvbmx5IG9uZSBnTkItQ1UtQ1AuIE9uZSBnTkItRFUgY2FuIGJlIGNvbm5lY3RlZCB0bwogICAgICAgICAgICBtdWx0aXBsZSBnTkItQ1UtVVBzIHVuZGVyIHRoZSBjb250cm9sIG9mIHRoZSBzYW1lIGdOQi1DVS1DUC4gT25lCiAgICAgICAgICAgIGdOQi1DVS1VUCBjYW4gYmUgY29ubmVjdGVkIHRvIG11bHRpcGxlIERVcyB1bmRlciB0aGUgY29udHJvbCBvZiB0aGUKICAgICAgICAgICAgc2FtZSBnTkItQ1UtQ1AuCgogICAgICAgICAgICBOb3RlOiBBIGdOQiBtYXkgY29uc2lzdCBvZiBhIGdOQi1DVS1DUCwgbXVsdGlwbGUgZ05CLUNVLVVQcyBhbmQKICAgICAgICAgICAgbXVsdGlwbGUgZ05CLURVcy4gQSBnTkItQ1UtVVAgaXMgYSBjb25jcmV0ZSBjbGFzcyB0aGF0IGV4dGVuZHMgdGhlCiAgICAgICAgICAgIE5HLVJBTiBub2RlIG9iamVjdC4gSW4gVG9wb2xvZ3ksIHlvdSBjYW4gY3JlYXRlLCByZWFkLCB1cGRhdGUsIGFuZAogICAgICAgICAgICBkZWxldGUgdGhlIGdOQi1DVS1VUCBvYmplY3QuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBnTkJJZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSWRlbnRpdHkgb2YgZ05vZGVCIHdpdGhpbiBhIFBMTU4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBnTkJJZExlbmd0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVuZ3RoIG9mIGdOQklkIGJpdCBzdHJpbmcgcmVwcmVzZW50YXRpb24iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IE5SQ2VsbENVIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyBhbiBOUiBDZWxsIGluIGdOb2RlQi1DVS4KCiAgICAgICAgICAgIDVHIE5SIGlzIGEgbmV3IHJhZGlvIGFjY2VzcyB0ZWNobm9sb2d5IChSQVQpIGRldmVsb3BlZCBieSAzR1BQIGZvcgogICAgICAgICAgICB0aGUgNUcgKGZpZnRoIGdlbmVyYXRpb24pIG1vYmlsZSBuZXR3b3JrLiBJdCBpcyBkZXNpZ25lZCB0byBiZSB0aGUKICAgICAgICAgICAgZ2xvYmFsIHN0YW5kYXJkIGZvciB0aGUgYWlyIGludGVyZmFjZSBvZiA1RyBuZXR3b3Jrcy4KCiAgICAgICAgICAgIDVHIE5SIGhhcyBzeW5jaHJvbml6YXRpb24gc2lnbmFsIHRoYXQgaXMga25vd24gYXMgUHJpbWFyeQogICAgICAgICAgICBTeW5jaHJvbml6YXRpb24gU2lnbmFsIChQU1MpIGFuZCBTZWNvbmRhcnkgU3luY2hyb25pemF0aW9uCiAgICAgICAgICAgIFNpZ25hbCAoU1NTKS4gVGhlc2Ugc2lnbmFscyBhcmUgc3BlY2lmaWMgdG8gTlIgcGh5c2ljYWwgbGF5ZXIgYW5kCiAgICAgICAgICAgIHByb3ZpZGUgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbiByZXF1aXJlZCBieSBVRSBmb3IgZG93bmxpbmsKICAgICAgICAgICAgc3luY2hyb25pemF0aW9uOiBQU1MgcHJvdmlkZXMgUmFkaW8gRnJhbWUgQm91bmRhcnkgKFBvc2l0aW9uIG9mIDFzdAogICAgICAgICAgICBTeW1ib2wgaW4gYSBSYWRpbyBmcmFtZSkgU1NTIHByb3ZpZGVzIFN1YmZyYW1lIEJvdW5kYXJ5IChQb3NpdGlvbiBvZgogICAgICAgICAgICAxc3QgU3ltYm9sIGluIGEgU3ViZnJhbWUpIFBoeXNpY2FsIExheWVyIENlbGwgSUQgKFBDSSkgaW5mb3JtYXRpb24KICAgICAgICAgICAgdXNpbmcgYm90aCBQU1MgYW5kIFNTUy4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIGNlbGxMb2NhbElkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJVc2VkIHRvZ2V0aGVyIHdpdGggZ05vZGVCIGlkZW50aWZpZXIgdG8gaWRlbnRpZnkgTlIKICAgICAgICAgICAgICAgICAgICBjZWxsIGluIFBMTU4uIFVzZWQgdG9nZXRoZXIgd2l0aCBnTkJJZCB0byBmb3JtIE5DSS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGFpbmVyIHBsbW5JZCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUExNTiBJRCBmb3IgTlIgQ0dJLiBJZiBlbXB0eSwKICAgICAgICAgICAgICAgICAgICBHTkJDVUNQRnVuY3Rpb246OnBMTU5JZCBpcyB1c2VkIGZvciBQTE1OIElEIGluIE5SIENHSSI7CiAgICAgICAgICAgICAgICB1c2VzIHR5cGVzM2dwcDpQTE1OSWQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgbkNJIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsIElkZW50aXR5IjsKICAgICAgICAgICAgICAgIHR5cGUgaW50NjQ7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgblJUQUMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKSI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTlJDZWxsRFUgewogICAgICAgIGRlc2NyaXB0aW9uICJSZXByZXNlbnRzIGFuIE5SIENlbGwgaW4gZ05vZGVCLURVLgoKICAgICAgICAgICAgNUcgTlIgaXMgYSBuZXcgcmFkaW8gYWNjZXNzIHRlY2hub2xvZ3kgKFJBVCkgZGV2ZWxvcGVkIGJ5IDNHUFAgZm9yCiAgICAgICAgICAgIHRoZSA1RyAoZmlmdGggZ2VuZXJhdGlvbikgbW9iaWxlIG5ldHdvcmsuIEl0IGlzIGRlc2lnbmVkIHRvIGJlIHRoZQogICAgICAgICAgICBnbG9iYWwgc3RhbmRhcmQgZm9yIHRoZSBhaXIgaW50ZXJmYWNlIG9mIDVHIG5ldHdvcmtzLgoKICAgICAgICAgICAgNUcgTlIgaGFzIHN5bmNocm9uaXphdGlvbiBzaWduYWwgdGhhdCBpcyBrbm93biBhcyBQcmltYXJ5CiAgICAgICAgICAgIFN5bmNocm9uaXphdGlvbiBzaWduYWwgKFBTUykgYW5kIFNlY29uZGFyeSBTeW5jaHJvbml6YXRpb24gc2lnbmFsCiAgICAgICAgICAgIChTU1MpLiBUaGVzZSBzaWduYWxzIGFyZSBzcGVjaWZpYyB0byBOUiBwaHlzaWNhbCBsYXllciBhbmQgcHJvdmlkZQogICAgICAgICAgICB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uIHJlcXVpcmVkIGJ5IFVFIGZvciBkb3dubGluawogICAgICAgICAgICBzeW5jaHJvbml6YXRpb246IFBTUyBwcm92aWRlcyBSYWRpbyBGcmFtZSBCb3VuZGFyeSAoUG9zaXRpb24gb2YgMXN0CiAgICAgICAgICAgIFN5bWJvbCBpbiBhIFJhZGlvIGZyYW1lKSBTU1MgcHJvdmlkZXMgU3ViZnJhbWUgQm91bmRhcnkgKFBvc2l0aW9uIG9mCiAgICAgICAgICAgIDFzdCBTeW1ib2wgaW4gYSBTdWJmcmFtZSkgUGh5c2ljYWwgTGF5ZXIgQ2VsbCBJRCAoUENJKSBpbmZvcm1hdGlvbgogICAgICAgICAgICB1c2luZyBib3RoIFBTUyBhbmQgU1NTLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgY2VsbExvY2FsSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlVzZWQgdG9nZXRoZXIgd2l0aCBnTm9kZUIgaWRlbnRpZmllciB0byBpZGVudGlmeSBOUgogICAgICAgICAgICAgICAgICAgIGNlbGwgaW4gUExNTi4gVXNlZCB0b2dldGhlciB3aXRoIGdOQklkIHRvIGZvcm0gTkNJLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIG5DSSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbCBJZGVudGl0eS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBuUlBDSSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIFBoeXNpY2FsIENlbGwgSWRlbnRpdHkgKFBDSSkgb2YgdGhlIE5SIGNlbGwuIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgblJUQUMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFRyYWNraW5nIEFyZWEgQ29kZSAoVEFDKS4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IEVOb2RlQkZ1bmN0aW9uIHsKICAgICAgICBkZXNjcmlwdGlvbiAiQW4gRXZvbHZlZCBOb2RlIEIgKGVOb2RlQikgaXMgdGhlIG9ubHkgbWFuZGF0b3J5IG5vZGUgaW4KICAgICAgICAgICAgdGhlIHJhZGlvIGFjY2VzcyBuZXR3b3JrIChSQU4pIG9mIExvbmctVGVybSBFdm9sdXRpb24gKExURSkuIFRoZQogICAgICAgICAgICBlTm9kZUIgaXMgYSBjb21wbGV4IGJhc2Ugc3RhdGlvbiB0aGF0IGhhbmRsZXMgcmFkaW8gY29tbXVuaWNhdGlvbnMKICAgICAgICAgICAgaW4gdGhlIGNlbGwgYW5kIGNhcnJpZXMgb3V0IHJhZGlvIHJlc291cmNlIG1hbmFnZW1lbnQgYW5kIGhhbmRvdmVyCiAgICAgICAgICAgIGRlY2lzaW9ucy4gVW5saWtlIDIvM0cgd2lyZWxlc3MgUkFOLCB0aGVyZSBpcyBubyBjZW50cmFsaXplZCByYWRpbwogICAgICAgICAgICBuZXR3b3JrIGNvbnRyb2xsZXIgaW4gTFRFLiBJdCBpcyB0aGUgaGFyZHdhcmUgdGhhdCBpcyBjb25uZWN0ZWQgdG8KICAgICAgICAgICAgdGhlIG1vYmlsZSBwaG9uZSBuZXR3b3JrIHRoYXQgY29tbXVuaWNhdGVzIGRpcmVjdGx5IHdpdGggbW9iaWxlCiAgICAgICAgICAgIGhhbmRzZXRzIChVc2VyIEVxdWlwbWVudCksIGxpa2UgYSBiYXNlIHRyYW5zY2VpdmVyIHN0YXRpb24gKEJUUykgaW4KICAgICAgICAgICAgR1NNIG5ldHdvcmtzLiBUaGlzIHNpbXBsaWZpZXMgdGhlIGFyY2hpdGVjdHVyZSBhbmQgYWxsb3dzIGxvd2VyCiAgICAgICAgICAgIHJlc3BvbnNlIHRpbWVzLiI7CgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7CiAgICAgICAgICAgIGxlYWYgZU5CSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgSUQgdGhhdCBmb3JtcyBwYXJ0IG9mIHRoZSBDZWxsIEdsb2JhbAogICAgICAgICAgICAgICAgICAgIElkZW50aXR5LCBhbmQgaXMgYWxzbyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBub2RlIG92ZXIgdGhlIFMxCiAgICAgICAgICAgICAgICAgICAgaW50ZXJmYWNlIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRhaW5lciBlTm9kZUJQbG1uSWQgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFTm9kZUIgUHVibGljIExhbmQgTW9iaWxlIE5ldHdvcmsgKFBMTU4pIElECiAgICAgICAgICAgICAgICAgICAgdGhhdCBmb3JtcyBwYXJ0IG9mIHRoZSBFTm9kZUIgR2xvYmFsIElEIHVzZWQgdG8gaWRlbnRpZnkgdGhlCiAgICAgICAgICAgICAgICAgICAgbm9kZSBvdmVyIHRoZSBTMSBpbnRlcmZhY2UuIE5vdGU6IFRoZSB2YWx1ZQogICAgICAgICAgICAgICAgICAgIChNQ0M9MDAxLCBNTkM9MDEpIGluZGljYXRlcyB0aGF0IHRoZSBQTE1OIGlzIG5vdCBpbml0aWF0ZWQuCiAgICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIGNhbiBub3QgYmUgdXNlZCBhcyBhIHZhbGlkIFBMTU4gSWRlbnRpdHkuIjsKCiAgICAgICAgICAgICAgICBsZWFmIG1jYyB7CiAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBNQ0MgcGFydCBvZiBhIFBMTU4gaWRlbnRpdHkgdXNlZCBpbiB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgcmFkaW8gbmV0d29yay4iOwogICAgICAgICAgICAgICAgICAgIHR5cGUgaW50MzIgewogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSAwLi45OTk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbGVhZiBtbmMgewogICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTU5DIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5IHVzZWQgaW4gdGhlCiAgICAgICAgICAgICAgICAgICAgICAgIHJhZGlvIG5ldHdvcmsuIjsKICAgICAgICAgICAgICAgICAgICB0eXBlIGludDMyIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgMC4uOTk5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxlYWYgbW5jTGVuZ3RoIHsKICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGxlbmd0aCBvZiB0aGUgTU5DIHBhcnQgb2YgYSBQTE1OIGlkZW50aXR5CiAgICAgICAgICAgICAgICAgICAgICAgIHVzZWQgaW4gdGhlIHJhZGlvIG5ldHdvcmsuIjsKICAgICAgICAgICAgICAgICAgICB0eXBlIGludDMyIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgMi4uMzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBFVXRyYW5DZWxsIHsKICAgICAgICBkZXNjcmlwdGlvbiAiUmVwcmVzZW50cyBhbiBGREQgb3IgVEREIEVVdHJhbkNlbGwgYW5kCiAgICAgICAgICAgICAgICAgICAgY29udGFpbnMgcGFyYW1ldGVycyBuZWVkZWQgYnkgdGhlIGNlbGwuCiAgICAgICAgICAgICAgICAgICAgSXQgYWxzbyBjb250YWlucyBwYXJhbWV0ZXJzIGZvciB0aGUKICAgICAgICAgICAgICAgICAgICBtYW5kYXRvcnkgY29tbW9uIGNoYW5uZWxzLiBBbiBFVVRSQU4gc3RhbmRzCiAgICAgICAgICAgICAgICAgICAgZm9yIEV2b2x2ZWQgVW5pdmVyc2FsIE1vYmlsZSBUZWxlY29tbXVuaWNhdGlvbnMKICAgICAgICAgICAgICAgICAgICBTeXN0ZW0gKFVNVFMpIFRlcnJlc3RyaWFsIFJhZGlvIEFjY2VzcyBOZXR3b3JrCiAgICAgICAgICAgICAgICAgICAgd2hpY2ggY29udGFpbnMgYW4gZU5vZGVCLiBUaGUgZU5vZGVCIGNvbmNyZXRlCiAgICAgICAgICAgICAgICAgICAgY2xhc3MgaXMgZXh0ZW5kZWQgZnJvbSB0aGUgRVVUUkFOIE5vZGUgYWJzdHJhY3QgY2xhc3MuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBjZWxsSWR7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUkJTIGludGVybmFsIElEIGF0dHJpYnV0ZSBmb3IgRVV0cmFuQ2VsbC4gTXVzdCBiZQogICAgICAgICAgICAgICAgICAgIHVuaXF1ZSBpbiB0aGUgUkJTLiBUb2dldGhlciB3aXRoIHRoZSBOb2RlIElEIGFuZCBQdWJsaWMKICAgICAgICAgICAgICAgICAgICBMYW5kIE1vYmlsZSBOZXR3b3JrIChQTE1OKSB0aGlzIGlzIGEgdW5pdmVyc2FsbHkgdW5pcXVlCiAgICAgICAgICAgICAgICAgICAgY2VsbCBJRCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVhcmZjbmRsIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUaGUgY2hhbm5lbCBudW1iZXIgZm9yIHRoZSBjZW50cmFsIGRvd25saW5rCiAgICAgICAgICAgICAgICAgICAgZnJlcXVlbmN5LiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGVhcmZjbnVsIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJDaGFubmVsIG51bWJlciBmb3IgdGhlIGNlbnRyYWwgdXBsaW5rIGZyZXF1ZW5jeSI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGRsQ2hhbm5lbEJhbmR3aWR0aCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVGhlIGRvd25saW5rIGNoYW5uZWwgYmFuZHdpZHRoIGluIHRoZSBGREQgY2VsbC4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBlYXJmY24gewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBFLVVUUkEgQWJzb2x1dGUgUmFkaW8gRnJlcXVlbmN5IENoYW5uZWwgTnVtYmVyCiAgICAgICAgICAgICAgICAgICAgKEVBUkZDTikgZm9yIHRoZSBUREQgY2VsbCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGNoYW5uZWxCYW5kd2lkdGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBjaGFubmVsIGJhbmR3aWR0aCBpbiB0aGUgVEREIGNlbGwuIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgdGFjIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJUcmFja2luZyBBcmVhIENvZGUgZm9yIHRoZSBFVXRyYW4gQ2VsbCI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGR1cGxleFR5cGUgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkluZGljYXRvciBvZiBFVXRyYW5DZWxsIHR5cGUsIEZERCBvciBUREQiOwogICAgICAgICAgICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgZW51bSBmZGQgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAwOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiRkREIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSB0ZGQgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAxOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiVEREIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgbGlzdCBOUlNlY3RvckNhcnJpZXIgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGUgTlIgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZSBhdHRyaWJ1dGVzIGZvcgogICAgICAgICAgICBkZWZpbmluZyB0aGUgbG9naWNhbCBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBjYXJyaWVyIChjZWxsKSBpbiBhCiAgICAgICAgICAgIHNlY3Rvci4gQSBzZWN0b3IgaXMgYSBjb3ZlcmFnZSBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbgogICAgICAgICAgICBoYXZpbmcgaXRzIG93biBhbnRlbm5hcywgcmFkaW8gcG9ydHMsIGFuZCBjb250cm9sIGNoYW5uZWxzLiBUaGUKICAgICAgICAgICAgY29uY2VwdCBvZiBzZWN0b3JzIHdhcyBkZXZlbG9wZWQgdG8gaW1wcm92ZSBjby1jaGFubmVsIGludGVyZmVyZW5jZQogICAgICAgICAgICBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zIHVzZSB0aHJlZSBzZWN0b3IKICAgICAgICAgICAgY2VsbHMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBhcmZjbkRMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBBYnNvbHV0ZSBSYWRpbyBGcmVxdWVuY3kgQ2hhbm5lbCBOdW1iZXIKICAgICAgICAgICAgICAgICAgICAoTlItQVJGQ04pIGZvciBkb3dubGluayI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZWFmIGFyZmNuVUwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIEFic29sdXRlIFJhZGlvIGZyZXF1ZW5jeSBDaGFubmVsIE51bWJlcgogICAgICAgICAgICAgICAgICAgIChOUi1BUkZDTikgZm9yIHVwbGluay4iOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBmcmVxdWVuY3lETCB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUkYgUmVmZXJlbmNlIEZyZXF1ZW5jeSBvZiBkb3dubGluayBjaGFubmVsIjsKICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYgZnJlcXVlbmN5VUwgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIlJGIFJlZmVyZW5jZSBGcmVxdWVuY3kgb2YgdXBsaW5rIGNoYW5uZWwiOwogICAgICAgICAgICAgICAgdHlwZSBpbnQzMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZiBiU0NoYW5uZWxCd0RMIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJCUyBDaGFubmVsIGJhbmR3aWR0aCBpbiBNSHogZm9yIGRvd25saW5rLiI7CiAgICAgICAgICAgICAgICB0eXBlIGludDMyOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgTFRFU2VjdG9yQ2FycmllciB7CiAgICAgICAgZGVzY3JpcHRpb24gIlRoZSBMVEUgU2VjdG9yIENhcnJpZXIgb2JqZWN0IHByb3ZpZGVzIHRoZSBhdHRyaWJ1dGVzIGZvcgogICAgICAgICAgICBkZWZpbmluZyB0aGUgbG9naWNhbCBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBjYXJyaWVyIChjZWxsKSBpbiBhCiAgICAgICAgICAgIHNlY3Rvci4gQSBzZWN0b3IgaXMgYSBjb3ZlcmFnZSBhcmVhIGFzc29jaWF0ZWQgd2l0aCBhIGJhc2Ugc3RhdGlvbgogICAgICAgICAgICBoYXZpbmcgaXRzIG93biBhbnRlbm5hcywgcmFkaW8gcG9ydHMsIGFuZCBjb250cm9sIGNoYW5uZWxzLiBUaGUKICAgICAgICAgICAgY29uY2VwdCBvZiBzZWN0b3JzIHdhcyBkZXZlbG9wZWQgdG8gaW1wcm92ZSBjby1jaGFubmVsIGludGVyZmVyZW5jZQogICAgICAgICAgICBpbiBjZWxsdWxhciBzeXN0ZW1zLCBhbmQgbW9zdCB3aXJlbGVzcyBzeXN0ZW1zIHVzZSB0aHJlZSBzZWN0b3IKICAgICAgICAgICAgY2VsbHMuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZiBzZWN0b3JDYXJyaWVyVHlwZSB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoZSBzZWN0b3IgY2FycmllcgogICAgICAgICAgICAgICAgICAgIG1vZGVsbGVkIGJ5IE1PIFNlY3RvckNhcnJpZXIgaXMgYSBkaWdpdGFsIHNlY3Rvci4iOwogICAgICAgICAgICAgICAgdHlwZSBlbnVtZXJhdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgZW51bSBub3JtYWxfc2VjdG9yIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgMDsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5vdCBhIGRpZ2l0YWwgc2VjdG9yIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSBsZWZ0X2RpZ2l0YWxfc2VjdG9yIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgMTsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxlZnQgZGlnaXRhbCBzZWN0b3IgZm9yIDJEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gcmlnaHRfZGlnaXRhbF9zZWN0b3IgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAyOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmlnaHQgZGlnaXRhbCBzZWN0b3IgZm9yIDJEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gbGVmdF9kaWdpdGFsX3NlY3Rvcl8zZHMgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSAzOwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGVmdCBkaWdpdGFsIHNlY3RvciBmb3IgM0RTIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW51bSByaWdodF9kaWdpdGFsX3NlY3Rvcl8zZHMgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA0OwogICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmlnaHQgZGlnaXRhbCBzZWN0b3IgZm9yIDNEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVudW0gbWlkZGxlX2RpZ2l0YWxfc2VjdG9yXzNkcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlIDU7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNaWRkbGUgZGlnaXRhbCBzZWN0b3IgZm9yIDNEUyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGxpc3QgQW50ZW5uYUNhcGFiaWxpdHkgewogICAgICAgIGRlc2NyaXB0aW9uICJUaGlzIE1PIHNlcnZlcyBhcyBhIG1hcHBpbmcgYmV0d2VlbiB0aGUgY2VsbCBhbmQgdGhlIFJCUwogICAgICAgICAgICBlcXVpcG1lbnQgdXNlZCB0byBwcm92aWRlIGNvdmVyYWdlIGluIGEgY2VydGFpbiBnZW9ncmFwaGljYWwgYXJlYS4KICAgICAgICAgICAgVGhlIE1PIGFsc28gY29udHJvbHMgdGhlIG1heGltdW0gb3V0cHV0IHBvd2VyIG9mIHRoZSBzZWN0b3IuIjsKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGNvbnRhaW5lciBhdHRyaWJ1dGVzIHsKICAgICAgICAgICAgbGVhZi1saXN0IGVVdHJhbkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgTFRFIGZyZXF1ZW5jeSBiYW5kcyB0aGF0IGFzc29jaWF0ZWQKICAgICAgICAgICAgICAgICAgICBoYXJkd2FyZSBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGVhZi1saXN0IGdlcmFuRnFCYW5kcyB7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiAiTGlzdCBvZiBHRVJBTiBmcmVxdWVuY3kgYmFuZHMgdGhhdCBhc3NvY2lhdGVkCiAgICAgICAgICAgICAgICAgICAgaGFyZHdhcmUgc3VwcG9ydHMiOwogICAgICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxlYWYtbGlzdCBuUkZxQmFuZHMgewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkxpc3Qgb2YgTlIgZnJlcXVlbmN5IGJhbmRzIGFzc29jaWF0ZWQgaGFyZHdhcmUKICAgICAgICAgICAgICAgICAgICBzdXBwb3J0cyI7CiAgICAgICAgICAgICAgICB0eXBlIHN0cmluZzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBsaXN0IFNlY3RvciB7CiAgICAgICAgZGVzY3JpcHRpb24gIkEgZ3JvdXAgb2YgY28tbG9jYXRlZCBDZWxscyB0aGF0IGhhdmUgYSBzaGFyZWQKICAgICAgICAgICAgY292ZXJhZ2UgYXJlYS4iOwoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgY29udGFpbmVyIGF0dHJpYnV0ZXMgewogICAgICAgICAgICBsZWFmIHNlY3RvcklkIHsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uICJVbml2ZXJzYWxseSB1bmlxdWUgSUQgZ2VuZXJhdGVkIGJ5IHRoZSBzZWN0b3IncwogICAgICAgICAgICAgICAgICAgIGRpc2NvdmVyeSBtZWNoYW5pc20uIjsKICAgICAgICAgICAgICAgIHR5cGUgdWludDY0OwogICAgICAgICAgICB9CgogICAgICAgICAgICB1c2VzIGdlbzpnZW8tbG9jYXRpb247CgogICAgICAgICAgICBsZWFmIGF6aW11dGggewogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gIkF2ZXJhZ2UgdmFsdWUgb2YgdGhlIGF6aW11dGhzIG9mIHRoZSBjZWxscwogICAgICAgICAgICAgICAgICAgIGNvbXByaXNpbmcgdGhlIHNlY3RvciwgZGV0ZXJtaW5lZCBkdXJpbmcgc2VjdG9yIGRpc2NvdmVyeS4iOwogICAgICAgICAgICAgICAgdHlwZSBkZWNpbWFsNjR7CiAgICAgICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB1bml0cyAiZGVncmVlcyI7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfRVVUUkFOQ0VMTCB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIEVVVFJBTiBDZWxsLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBFTm9kZUJGdW5jdGlvbjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBwcm92aWRlZC1ieS1lbm9kZWJGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCBwcm92aWRlZCBieSBlTm9kZUIgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEVVdHJhbkNlbGw7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5PREVCRlVOQ1RJT05fUFJPVklERVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZU5vZGVCIEZ1bmN0aW9uIHByb3ZpZGVzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHByb3ZpZGVkIGJ5IGVOb2RlQiBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTFRFU2VjdG9yQ2FycmllcjsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBHTkJEVUZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTERVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIENlbGwtRFUuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIEdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgcHJvdmlkZWQtYnktZ25iZHVGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLURVIHByb3ZpZGVkIGJ5IGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CRFVGVU5DVElPTl9QUk9WSURFU19OUlNFQ1RPUkNBUlJJRVIgeyAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBwcm92aWRlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLURVIEZ1bmN0aW9uIHByb3ZpZGVzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBHTkJEVUZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmR1RnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgU2VjdG9yIENhcnJpZXIgcHJvdmlkZWQgYnkgZ05vZGVCLURVIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUlNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgR05CQ1VDUEZVTkNUSU9OX1BST1ZJREVTX05SQ0VMTENVIHsgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgcHJvdmlkZWQtbnJDZWxsQ3UgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVQ1AgRnVuY3Rpb24gcHJvdmlkZXMgTlIgQ2VsbC1DVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgR05CQ1VDUEZ1bmN0aW9uOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIHByb3ZpZGVkLWJ5LWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBDZWxsLUNVIHByb3ZpZGVkIGJ5IGdOb2RlQi1DVUNQIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBOUkNlbGxDVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgICAgICBtYW5kYXRvcnkgdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBFVVRSQU5DRUxMX1VTRVNfTFRFU0VDVE9SQ0FSUklFUiB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IHVzZWQtbHRlU2VjdG9yQ2FycmllciB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJFVVRSQU4gQ2VsbCB1c2VzIExURSBTZWN0b3IgQ2Fycmllci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRVV0cmFuQ2VsbDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTFRFIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgRVVUUkFOIENlbGwuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBMVEVTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJMVEUgU2VjdG9yIENhcnJpZXIgdXNlcyBBbnRlbm5hIENhcGFiaWxpdHkuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIExURVNlY3RvckNhcnJpZXI7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYtbGlzdCB1c2VkLWJ5LWx0ZVNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTFRFIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBBbnRlbm5hQ2FwYWJpbGl0eTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KICAgIH0KCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE5SQ0VMTERVX1VTRVNfTlJTRUNUT1JDQVJSSUVSIHsgLy8gMC4uMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSB1c2VzIE5SIFNlY3RvciBDYXJyaWVyLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBOUkNlbGxEVTsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiB1c2VkLWJ5LW5yQ2VsbER1IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk5SIFNlY3RvciBDYXJyaWVyIHVzZWQgYnkgTlIgQ2VsbC1EVS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTlJTRUNUT1JDQVJSSUVSX1VTRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLjEKCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYgdXNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJOUiBTZWN0b3IgQ2FycmllciB1c2VzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgTlJTZWN0b3JDYXJyaWVyOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3QgdXNlZC1ieS1uclNlY3RvckNhcnJpZXIgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiQW50ZW5uYSBDYXBhYmlsaXR5IHVzZWQgYnkgTlIgU2VjdG9yIENhcnJpZXIuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEFudGVubmFDYXBhYmlsaXR5OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgU0VDVE9SX0dST1VQU19OUkNFTExEVSB7IC8vIDAuLjEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IGdyb3VwZWQtbnJDZWxsRHUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBOUiBDZWxsLURVLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBTZWN0b3I7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgZ3JvdXBlZC1ieS1zZWN0b3IgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTlIgQ2VsbC1EVSBncm91cGVkIGJ5IFNlY3Rvci4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgTlJDZWxsRFU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBTRUNUT1JfR1JPVVBTX0VVVFJBTkNFTEwgeyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWV1VHJhbkNlbGwgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBFVVRSQU4gQ2VsbC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgU2VjdG9yOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGdyb3VwZWQtYnktc2VjdG9yIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkVVVFJBTiBDZWxsIGdyb3VwZWQgYnkgU2VjdG9yLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBFVXRyYW5DZWxsOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQogICAgfQp9 +o-ran-smo-teiv-rel-equipment-ran urn:o-ran:smo-teiv-rel-equipment-ran REL_EQUIPMENT_RAN ["o-ran-smo-teiv-equipment", "o-ran-smo-teiv-ran"] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJlbC1lcXVpcG1lbnQtcmFuIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1yZWwtZXF1aXBtZW50LXJhbiI7CiAgICBwcmVmaXggb3ItdGVpdi1yZWwtZXF1aXByYW47CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsgcHJlZml4IG9yLXRlaXYtdHlwZXM7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7IHByZWZpeCBvci10ZWl2LXlleHQ7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtZXF1aXBtZW50IHsgcHJlZml4IG9yLXRlaXYtZXF1aXA7IH0KCiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtcmFuIHsgcHJlZml4IG9yLXRlaXYtcmFuOyB9CgogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7CiAgICBjb250YWN0ICJFcmljc3NvbiBmaXJzdCBsaW5lIHN1cHBvcnQgdmlhIGVtYWlsIjsKICAgIGRlc2NyaXB0aW9uCiAgICAiRXF1aXBtZW50IGFuZCBSQU4gdG9wb2xvZ3kgcmVsYXRpb24gbW9kZWwuCgogICAgQ29weXJpZ2h0IChjKSAyMDI0IEVyaWNzc29uIEFCLiBBbGwgcmlnaHRzIHJlc2VydmVkLgoKICAgIFRoaXMgbW9kZWwgY29udGFpbnMgdGhlIHRvcG9sb2d5IHJlbGF0aW9ucyBiZXR3ZWVuIEVxdWlwbWVudCBhbmQgUkFOLiI7CgogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsKICAgICAgICBkZXNjcmlwdGlvbiAiSW5pdGlhbCByZXZpc2lvbi4iOwogICAgICAgIG9yLXRlaXYteWV4dDpsYWJlbCAwLjMuMDsKICAgIH0KCiAgICBvci10ZWl2LXlleHQ6ZG9tYWluIFJFTF9FUVVJUE1FTlRfUkFOOwoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgQU5URU5OQU1PRFVMRV9TRVJWRVNfQU5URU5OQUNBUEFCSUxJVFkgeyAvLyAwLi5uIHRvIDAuLm0KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBzZXJ2aWNlZC1hbnRlbm5hQ2FwYWJpbGl0eSB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBbnRlbm5hIENhcGFiaWxpdHkgc2VydmljZWQgYnkgdGhpcyBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1lcXVpcDpBbnRlbm5hTW9kdWxlOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmLWxpc3Qgc2VydmluZy1hbnRlbm5hTW9kdWxlIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIHNlcnZlcyB0aGlzIEFudGVubmEgQ2FwYWJpbGl0eS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46QW50ZW5uYUNhcGFiaWxpdHk7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBTRUNUT1JfR1JPVVBTX0FOVEVOTkFNT0RVTEUgeyAvLyAwLi4xIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWFudGVubmFNb2R1bGUgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiU2VjdG9yIGdyb3VwcyBBbnRlbm5hIE1vZHVsZS4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1yYW46U2VjdG9yOwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIGdyb3VwZWQtYnktc2VjdG9yIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIkFudGVubmEgTW9kdWxlIGdyb3VwZWQgYnkgU2VjdG9yLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LWVxdWlwOkFudGVubmFNb2R1bGU7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CiAgICB9Cn0= +o-ran-smo-teiv-rel-oam-ran urn:o-ran:smo-teiv-rel-oam-ran REL_OAM_RAN ["o-ran-smo-teiv-oam", "o-ran-smo-teiv-ran"] 2024-05-24 bW9kdWxlIG8tcmFuLXNtby10ZWl2LXJlbC1vYW0tcmFuIHsKICAgIHlhbmctdmVyc2lvbiAxLjE7CiAgICBuYW1lc3BhY2UgInVybjpvLXJhbjpzbW8tdGVpdi1yZWwtb2FtLXJhbiI7CiAgICBwcmVmaXggb3ItdGVpdi1yZWwtb2FtcmFuOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCBvci10ZWl2LXR5cGVzOyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLWV4dGVuc2lvbnMgeyBwcmVmaXggb3ItdGVpdi15ZXh0OyB9CgogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LW9hbSB7IHByZWZpeCBvci10ZWl2LW9hbTsgfQoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1yYW4geyBwcmVmaXggb3ItdGVpdi1yYW47IH0KCiAgICBvcmdhbml6YXRpb24gIk9SQU4iOwogICAgY29udGFjdCAiVGhlIEF1dGhvcnMiOwogICAgZGVzY3JpcHRpb24KICAgICJSQU4gTyZNIHRvIExvZ2ljYWwgdG9wb2xvZ3kgbW9kZWwuCgogICAgVGhpcyBtb2RlbCBjb250YWlucyB0aGUgUkFOIE8mTSB0byBMb2dpY2FsIHRvcG9sb2d5IHJlbGF0aW9ucwoKICAgIENvcHlyaWdodCAoQykgMjAyNCBFcmljc3NvbgogICAgTW9kaWZpY2F0aW9ucyBDb3B5cmlnaHQgKEMpIDIwMjQgT3BlbkluZnJhIEZvdW5kYXRpb24gRXVyb3BlCgogICAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsKICAgIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4KICAgIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKICAgIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICAgIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywKICAgIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogICAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogICAgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgogICAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAiOwoKICAgIHJldmlzaW9uICIyMDI0LTA1LTI0IiB7CiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgb3ItdGVpdi15ZXh0OmRvbWFpbiBSRUxfT0FNX1JBTjsKCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIE1BTkFHRURFTEVNRU5UX01BTkFHRVNfRU5PREVCRlVOQ1RJT04geyAgIC8vIDEgdG8gMC4ubgoKICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOwogICAgICAgIGtleSBpZDsKCiAgICAgICAgbGVhZi1saXN0IG1hbmFnZWQtZW5vZGViRnVuY3Rpb24gewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiTWFuYWdlZCBFbGVtZW50IG1hbmFnZXMgZU5vZGVCIEZ1bmN0aW9uLiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBvci10ZWl2LW9hbTpNYW5hZ2VkRWxlbWVudDsKICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOwogICAgICAgIH0KCiAgICAgICAgbGVhZiBtYW5hZ2VkLWJ5LW1hbmFnZWRFbGVtZW50IHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gImVOb2RlQiBGdW5jdGlvbiBtYW5hZ2VkIGJ5IE1hbmFnZWQgRWxlbWVudC4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgb3ItdGVpdi1yYW46RU5vZGVCRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJEVUZVTkNUSU9OIHsgICAgLy8gMSB0byAwLi5uCgogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7CiAgICAgICAga2V5IGlkOwoKICAgICAgICBsZWFmLWxpc3QgbWFuYWdlZC1nbmJkdUZ1bmN0aW9uIHsKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1hbmFnZWQgRWxlbWVudCBtYW5hZ2VzIGdOb2RlQi1EVSBGdW5jdGlvbi4iOwogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgb3ItdGVpdi1vYW06TWFuYWdlZEVsZW1lbnQ7CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICB9CgogICAgICAgIGxlYWYgbWFuYWdlZC1ieS1tYW5hZ2VkRWxlbWVudCB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJnTm9kZUItRFUgRnVuY3Rpb24gbWFuYWdlZCBieSBNYW5hZ2VkIEVsZW1lbnQuIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIG9yLXRlaXYtcmFuOkdOQkRVRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVUNQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1Y3BGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtQ1AgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLUNQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVUNQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgTUFOQUdFREVMRU1FTlRfTUFOQUdFU19HTkJDVVVQRlVOQ1RJT04geyAgICAvLyAxIHRvIDAuLm4KCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsKICAgICAgICBrZXkgaWQ7CgogICAgICAgIGxlYWYtbGlzdCBtYW5hZ2VkLWduYmN1dXBGdW5jdGlvbiB7CiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJNYW5hZ2VkIEVsZW1lbnQgbWFuYWdlcyBnTm9kZUItQ1UtVVAgRnVuY3Rpb24uIjsKICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmFTaWRlIG9yLXRlaXYtb2FtOk1hbmFnZWRFbGVtZW50OwogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7CiAgICAgICAgfQoKICAgICAgICBsZWFmIG1hbmFnZWQtYnktbWFuYWdlZEVsZW1lbnQgewogICAgICAgICAgICBkZXNjcmlwdGlvbiAiZ05vZGVCLUNVLVVQIEZ1bmN0aW9uIG1hbmFnZWQgYnkgTWFuYWdlZCBFbGVtZW50LiI7CiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBvci10ZWl2LXJhbjpHTkJDVVVQRnVuY3Rpb247CiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsKICAgICAgICAgICAgbWFuZGF0b3J5IHRydWU7CiAgICAgICAgfQogICAgfQp9 \. -COPY ties_model.relationship_info("name", "aSideAssociationName", "aSideMOType", "aSideMinCardinality", "aSideMaxCardinality", "bSideAssociationName", "bSideMOType", "bSideMinCardinality", "bSideMaxCardinality", "associationKind", "relationshipDataLocation", "connectSameEntity", "moduleReferenceName") FROM stdin; -MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN managed-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt 1 1 managed-by-managedElementttttttttttttttttttttttttttttttttttttttt GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-ran -MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM deployed-as-cloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt 1 1 deployed-managedElementttttttttttttttttttttttttttttttttttttttttt CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-oam-to-cloud -MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN realised-by-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt 1 1 realised-managedElementttttttttttttttttttttttttttttttttttttttttt CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 1 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-cloud -MANAGEDELEMENT_MANAGES_ENODEBFUNCTION managed-enodebFunction ManagedElement 1 1 managed-by-managedElement ENodeBFunction 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-ran -MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION managed-gnbcucpFunction ManagedElement 1 1 managed-by-managedElement GNBCUCPFunction 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-ran -MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION managed-gnbcuupFunction ManagedElement 1 1 managed-by-managedElement GNBCUUPFunction 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-ran -MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication ManagedElement 1 1 realised-managedElement CloudNativeApplication 1 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-cloud -MANAGEDELEMENT_MANAGES_GNBDUFUNCTION managed-gnbduFunction ManagedElement 1 1 managed-by-managedElement GNBDUFunction 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-oam-to-ran -MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM deployed-as-cloudNativeSystem ManagedElement 1 1 deployed-managedElement CloudNativeSystem 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-oam-to-cloud -NODECLUSTER_LOCATED_AT_CLOUDSITE located-at-cloudSite NodeCluster 0 9223372036854775807 location-of-nodeCluster CloudSite 1 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-cloud -CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION comprised-cloudNativeApplication CloudNativeSystem 0 1 comprised-by-cloudNativeSystem CloudNativeApplication 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-cloud -CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE deployed-on-namespace CloudNativeApplication 0 9223372036854775807 deployed-cloudNativeApplication Namespace 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-cloud -CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE deployed-on-namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 0 9223372036854775807 deployed-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-cloud -NAMESPACE_DEPLOYED_ON_NODECLUSTER deployed-on-nodeCluster Namespace 0 9223372036854775807 deployed-namespace NodeCluster 1 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-cloud -SECTOR_GROUPS_EUTRANCELL grouped-euTranCell Sector 0 1 grouped-by-sector EUtranCell 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-equipment-to-ran -SECTOR_GROUPS_ANTENNAMODULE grouped-antennaModule Sector 0 1 grouped-by-sector AntennaModule 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-equipment-to-ran -SECTOR_GROUPS_NRCELLDU grouped-nrCellDu Sector 0 1 grouped-by-sector NRCellDU 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBCUUPFunction 0 9223372036854775807 realised-gnbcuupFunction CloudNativeApplication 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-cloud-to-ran -ENODEBFUNCTION_PROVIDES_EUTRANCELL provided-euTranCell ENodeBFunction 1 1 provided-by-enodebFunction EUtranCell 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER provided-lteSectorCarrier ENodeBFunction 1 1 provided-by-enodebFunction LTESectorCarrier 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE realised-by-physicalNetworkAppliance ENodeBFunction 0 9223372036854775807 realised-enodebFunction PhysicalNetworkAppliance 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-equipment-to-ran -NRCELLDU_USES_NRSECTORCARRIER used-nrSectorCarrier NRCellDU 0 1 used-by-nrCellDu NRSectorCarrier 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -LTESECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability LTESectorCarrier 0 1 used-by-lteSectorCarrier AntennaCapability 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-ran -GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBDUFunction 0 9223372036854775807 realised-gnbduFunction CloudNativeApplication 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-cloud-to-ran -GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER provided-nrSectorCarrier GNBDUFunction 1 1 provided-by-gnbduFunction NRSectorCarrier 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -GNBDUFUNCTION_PROVIDES_NRCELLDU provided-nrCellDu GNBDUFunction 1 1 provided-by-gnbduFunction NRCellDU 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN realised-by-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 0 9223372036854775807 realised-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-cloud-to-ran -GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU provided-nrCellDuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 1 1 provided-by-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -EUTRANCELL_USES_LTESECTORCARRIER used-lteSectorCarrier EUtranCell 0 1 used-by-euTranCell LTESectorCarrier 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -GNBCUCPFUNCTION_PROVIDES_NRCELLCU provided-nrCellCu GNBCUCPFunction 1 1 provided-by-gnbcucpFunction NRCellCU 0 9223372036854775807 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBCUCPFunction 0 9223372036854775807 realised-gnbcucpFunction CloudNativeApplication 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-cloud-to-ran -NRSECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability NRSectorCarrier 0 9223372036854775807 used-by-nrSectorCarrier AntennaCapability 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-ran -ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE realised-by-antennaModule AntennaCapability 0 9223372036854775807 realised-antennaCapability AntennaModule 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-equipment-to-ran -TESTENTITYA_PROVIDES_TESTENTITYB provided-testEntityB TestEntityA 0 2 provided-by-testEntityA TestEntityB 0 3 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-ran -TESTENTITYA_USES_TESTENTITYB used-TestEntityB TestEntityA 0 1 used-by-testEntityA TestEntityB 0 2 BI_DIRECTIONAL B_SIDE false o-ran-smo-teiv-ran -TESTENTITYA_GROUPS_TESTENTITYB grouped-testEntityB TestEntityA 0 2 grouped-by-testEntityA TestEntityB 0 9223372036854775807 BI_DIRECTIONAL RELATION false o-ran-smo-teiv-ran -ANTENNAMODULE_INSTALLED_AT_SITE installed-at-site AntennaModule 0 9223372036854775807 installed-antennaModule Site 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-equipment -PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE installed-at-site PhysicalNetworkAppliance 0 9223372036854775807 installed-physicalNetworkAppliance Site 0 1 BI_DIRECTIONAL A_SIDE false o-ran-smo-teiv-equipment -ANTENNAMODULE_REALISED_BY_ANTENNAMODULE realised-by-antennaModule AntennaModule 0 9223372036854775807 realised-antennaModule AntennaModule 0 9223372036854775807 BI_DIRECTIONAL RELATION true o-ran-smo-teiv-equipment -ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE realised-by-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0 1 realised-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0 9223372036854775807 BI_DIRECTIONAL RELATION true o-ran-smo-teiv-equipment -ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE deployed-on-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0 1 deployed-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0 1 BI_DIRECTIONAL RELATION true o-ran-smo-teiv-equipment + +COPY ties_model.entity_info("storedAt", "name", "moduleReferenceName") FROM stdin; +o-ran-smo-teiv-ran-oam_ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt o-ran-smo-teiv-ran-oam +o-ran-smo-teiv-ran-oam_ManagedElement ManagedElement o-ran-smo-teiv-ran-oam +o-ran-smo-teiv-ran-cloud_NodeCluster NodeCluster o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_CloudNativeSystem CloudNativeSystem o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_CloudNativeApplication CloudNativeApplication o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_CloudSite CloudSite o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-cloud_Namespace Namespace o-ran-smo-teiv-ran-cloud +o-ran-smo-teiv-ran-logical-to-equipment_Sector Sector o-ran-smo-teiv-ran-logical-to-equipment +o-ran-smo-teiv-ran-logical_GNBCUUPFunction GNBCUUPFunction o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_ENodeBFunction ENodeBFunction o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_NRCellDU NRCellDU o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_LTESectorCarrier LTESectorCarrier o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_GNBDUFunction GNBDUFunction o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_NRCellCU NRCellCU o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-equipment_AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-equipment +o-ran-smo-teiv-ran-logical_EUtranCell EUtranCell o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_GNBCUCPFunction GNBCUCPFunction o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_NRSectorCarrier NRSectorCarrier o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_AntennaCapability AntennaCapability o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_TestEntityB TestEntityB o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-logical_TestEntityA TestEntityA o-ran-smo-teiv-ran-logical +o-ran-smo-teiv-ran-equipment_Site Site o-ran-smo-teiv-ran-equipment +o-ran-smo-teiv-ran-equipment_AntennaModule AntennaModule o-ran-smo-teiv-ran-equipment +o-ran-smo-teiv-ran-equipment_PhysicalNetworkAppliance PhysicalNetworkAppliance o-ran-smo-teiv-ran-equipment +\. + +COPY ties_model.relationship_info("name", "aSideAssociationName", "aSideMOType", "aSideModule", "aSideMinCardinality", "aSideMaxCardinality", "bSideAssociationName", "bSideMOType", "bSideModule", "bSideMinCardinality", "bSideMaxCardinality", "associationKind", "relationshipDataLocation", "storedAt", "connectSameEntity", "moduleReferenceName") FROM stdin; +MANAGEDELEMENTTTTTTTTTTTTTTT_MANAGES_GNBDUFUNCTIONNNNNNNNNNNNNNN managed-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt o-ran-smo-teiv-ran-oam 1 1 managed-by-managedElementttttttttttttttttttttttttttttttttttttttt GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn false o-ran-smo-teiv-ran-oam-to-logical +MANAGEDELEMENTTTTTTTTTTT_DEPLOYED_AS_CLOUDNATIVESYSTEMMMMMMMMMMM deployed-as-cloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt o-ran-smo-teiv-ran-oam 1 1 deployed-managedElementttttttttttttttttttttttttttttttttttttttttt CloudNativeSystemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm o-ran-smo-teiv-ran-cloud 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-oam_ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt false o-ran-smo-teiv-ran-oam-to-cloud +MANAGEDELEMENTTTTTTTTT_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNN realised-by-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn ManagedElementtttttttttttttttttttttttttttttttttttttttttttttttttt o-ran-smo-teiv-ran-oam 1 1 realised-managedElementttttttttttttttttttttttttttttttttttttttttt CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-cloud 1 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-cloud_CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn false o-ran-smo-teiv-ran-oam-to-cloud +MANAGEDELEMENT_MANAGES_ENODEBFUNCTION managed-enodebFunction ManagedElement o-ran-smo-teiv-ran-oam 1 1 managed-by-managedElement ENodeBFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_ENodeBFunction false o-ran-smo-teiv-ran-oam-to-logical +MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION managed-gnbcucpFunction ManagedElement o-ran-smo-teiv-ran-oam 1 1 managed-by-managedElement GNBCUCPFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_GNBCUCPFunction false o-ran-smo-teiv-ran-oam-to-logical +MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION managed-gnbcuupFunction ManagedElement o-ran-smo-teiv-ran-oam 1 1 managed-by-managedElement GNBCUUPFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_GNBCUUPFunction false o-ran-smo-teiv-ran-oam-to-logical +MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication ManagedElement o-ran-smo-teiv-ran-oam 1 1 realised-managedElement CloudNativeApplication o-ran-smo-teiv-ran-cloud 1 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-cloud_CloudNativeApplication false o-ran-smo-teiv-ran-oam-to-cloud +MANAGEDELEMENT_MANAGES_GNBDUFUNCTION managed-gnbduFunction ManagedElement o-ran-smo-teiv-ran-oam 1 1 managed-by-managedElement GNBDUFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_GNBDUFunction false o-ran-smo-teiv-ran-oam-to-logical +MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM deployed-as-cloudNativeSystem ManagedElement o-ran-smo-teiv-ran-oam 1 1 deployed-managedElement CloudNativeSystem o-ran-smo-teiv-ran-cloud 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-oam_ManagedElement false o-ran-smo-teiv-ran-oam-to-cloud +NODECLUSTER_LOCATED_AT_CLOUDSITE located-at-cloudSite NodeCluster o-ran-smo-teiv-ran-cloud 0 9223372036854775807 location-of-nodeCluster CloudSite o-ran-smo-teiv-ran-cloud 1 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-cloud_NodeCluster false o-ran-smo-teiv-ran-cloud +CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION comprised-cloudNativeApplication CloudNativeSystem o-ran-smo-teiv-ran-cloud 0 1 comprised-by-cloudNativeSystem CloudNativeApplication o-ran-smo-teiv-ran-cloud 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-cloud_CloudNativeApplication false o-ran-smo-teiv-ran-cloud +CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE deployed-on-namespace CloudNativeApplication o-ran-smo-teiv-ran-cloud 0 9223372036854775807 deployed-cloudNativeApplication Namespace o-ran-smo-teiv-ran-cloud 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-cloud_CloudNativeApplication false o-ran-smo-teiv-ran-cloud +CLOUDNATIVEAPPLICATIONNNNNNNNNNN_DEPLOYED_ON_NAMESPACEEEEEEEEEEE deployed-on-namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-cloud 0 9223372036854775807 deployed-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn Namespaceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-cloud 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-cloud_CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn false o-ran-smo-teiv-ran-cloud +NAMESPACE_DEPLOYED_ON_NODECLUSTER deployed-on-nodeCluster Namespace o-ran-smo-teiv-ran-cloud 0 9223372036854775807 deployed-namespace NodeCluster o-ran-smo-teiv-ran-cloud 1 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-cloud_Namespace false o-ran-smo-teiv-ran-cloud +SECTOR_GROUPS_EUTRANCELL grouped-euTranCell Sector o-ran-smo-teiv-ran-logical-to-equipment 0 1 grouped-by-sector EUtranCell o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_EUtranCell false o-ran-smo-teiv-ran-logical-to-equipment +SECTOR_GROUPS_ANTENNAMODULE grouped-antennaModule Sector o-ran-smo-teiv-ran-logical-to-equipment 0 1 grouped-by-sector AntennaModule o-ran-smo-teiv-ran-equipment 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-equipment_AntennaModule false o-ran-smo-teiv-ran-logical-to-equipment +SECTOR_GROUPS_NRCELLDU grouped-nrCellDu Sector o-ran-smo-teiv-ran-logical-to-equipment 0 1 grouped-by-sector NRCellDU o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRCellDU false o-ran-smo-teiv-ran-logical-to-equipment +GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBCUUPFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-gnbcuupFunction CloudNativeApplication o-ran-smo-teiv-ran-cloud 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical-to-cloud_GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION false o-ran-smo-teiv-ran-logical-to-cloud +ENODEBFUNCTION_PROVIDES_EUTRANCELL provided-euTranCell ENodeBFunction o-ran-smo-teiv-ran-logical 1 1 provided-by-enodebFunction EUtranCell o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_EUtranCell false o-ran-smo-teiv-ran-logical +ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER provided-lteSectorCarrier ENodeBFunction o-ran-smo-teiv-ran-logical 1 1 provided-by-enodebFunction LTESectorCarrier o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_LTESectorCarrier false o-ran-smo-teiv-ran-logical +ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE realised-by-physicalNetworkAppliance ENodeBFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-enodebFunction PhysicalNetworkAppliance o-ran-smo-teiv-ran-equipment 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-logical_ENodeBFunction false o-ran-smo-teiv-ran-logical-to-equipment +NRCELLDU_USES_NRSECTORCARRIER used-nrSectorCarrier NRCellDU o-ran-smo-teiv-ran-logical 0 1 used-by-nrCellDu NRSectorCarrier o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRSectorCarrier false o-ran-smo-teiv-ran-logical +LTESECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability LTESectorCarrier o-ran-smo-teiv-ran-logical 0 1 used-by-lteSectorCarrier AntennaCapability o-ran-smo-teiv-ran-logical 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-logical_LTESectorCarrier false o-ran-smo-teiv-ran-logical +GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBDUFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-gnbduFunction CloudNativeApplication o-ran-smo-teiv-ran-cloud 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical-to-cloud_GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION false o-ran-smo-teiv-ran-logical-to-cloud +GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER provided-nrSectorCarrier GNBDUFunction o-ran-smo-teiv-ran-logical 1 1 provided-by-gnbduFunction NRSectorCarrier o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRSectorCarrier false o-ran-smo-teiv-ran-logical +GNBDUFUNCTION_PROVIDES_NRCELLDU provided-nrCellDu GNBDUFunction o-ran-smo-teiv-ran-logical 1 1 provided-by-gnbduFunction NRCellDU o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRCellDU false o-ran-smo-teiv-ran-logical +GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN realised-by-cloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn CloudNativeApplicationnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-cloud 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical-to-cloud_GNBDUFUNCTIONNNNNNNNN_REALISED_BY_CLOUDNATIVEAPPLICATIONNNNNNNNN false o-ran-smo-teiv-ran-logical-to-cloud +GNBDUFUNCTIONNNNNNNNNNNNNNUUU_PROVIDES_NRCELLDUUUUUUUUUUUUUUUUUU provided-nrCellDuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu GNBDUFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn o-ran-smo-teiv-ran-logical 1 1 provided-by-gnbduFunctionnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRCellDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU false o-ran-smo-teiv-ran-logical +EUTRANCELL_USES_LTESECTORCARRIER used-lteSectorCarrier EUtranCell o-ran-smo-teiv-ran-logical 0 1 used-by-euTranCell LTESectorCarrier o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_LTESectorCarrier false o-ran-smo-teiv-ran-logical +GNBCUCPFUNCTION_PROVIDES_NRCELLCU provided-nrCellCu GNBCUCPFunction o-ran-smo-teiv-ran-logical 1 1 provided-by-gnbcucpFunction NRCellCU o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_NRCellCU false o-ran-smo-teiv-ran-logical +GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION realised-by-cloudNativeApplication GNBCUCPFunction o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-gnbcucpFunction CloudNativeApplication o-ran-smo-teiv-ran-cloud 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical-to-cloud_GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION false o-ran-smo-teiv-ran-logical-to-cloud +NRSECTORCARRIER_USES_ANTENNACAPABILITY used-antennaCapability NRSectorCarrier o-ran-smo-teiv-ran-logical 0 9223372036854775807 used-by-nrSectorCarrier AntennaCapability o-ran-smo-teiv-ran-logical 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-logical_NRSectorCarrier false o-ran-smo-teiv-ran-logical +ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE realised-by-antennaModule AntennaCapability o-ran-smo-teiv-ran-logical 0 9223372036854775807 realised-antennaCapability AntennaModule o-ran-smo-teiv-ran-equipment 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical-to-equipment_ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE false o-ran-smo-teiv-ran-logical-to-equipment +TESTENTITYA_PROVIDES_TESTENTITYB provided-testEntityB TestEntityA o-ran-smo-teiv-ran-logical 0 2 provided-by-testEntityA TestEntityB o-ran-smo-teiv-ran-logical 0 3 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical_TESTENTITYA_PROVIDES_TESTENTITYB false o-ran-smo-teiv-ran-logical +TESTENTITYA_USES_TESTENTITYB used-TestEntityB TestEntityA o-ran-smo-teiv-ran-logical 0 1 used-by-testEntityA TestEntityB o-ran-smo-teiv-ran-logical 0 2 BI_DIRECTIONAL B_SIDE o-ran-smo-teiv-ran-logical_TestEntityB false o-ran-smo-teiv-ran-logical +TESTENTITYA_GROUPS_TESTENTITYB grouped-testEntityB TestEntityA o-ran-smo-teiv-ran-logical 0 2 grouped-by-testEntityA TestEntityB o-ran-smo-teiv-ran-logical 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-logical_TESTENTITYA_GROUPS_TESTENTITYB false o-ran-smo-teiv-ran-logical +ANTENNAMODULE_INSTALLED_AT_SITE installed-at-site AntennaModule o-ran-smo-teiv-ran-equipment 0 9223372036854775807 installed-antennaModule Site o-ran-smo-teiv-ran-equipment 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-equipment_AntennaModule false o-ran-smo-teiv-ran-equipment +PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE installed-at-site PhysicalNetworkAppliance o-ran-smo-teiv-ran-equipment 0 9223372036854775807 installed-physicalNetworkAppliance Site o-ran-smo-teiv-ran-equipment 0 1 BI_DIRECTIONAL A_SIDE o-ran-smo-teiv-ran-equipment_PhysicalNetworkAppliance false o-ran-smo-teiv-ran-equipment +ANTENNAMODULE_REALISED_BY_ANTENNAMODULE realised-by-antennaModule AntennaModule o-ran-smo-teiv-ran-equipment 0 9223372036854775807 realised-antennaModule AntennaModule o-ran-smo-teiv-ran-equipment 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-equipment_ANTENNAMODULE_REALISED_BY_ANTENNAMODULE true o-ran-smo-teiv-ran-equipment +ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE realised-by-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-equipment 0 1 realised-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-equipment 0 9223372036854775807 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-equipment_ANTENNAMODULEEEEEEEEEEEE_REALISED_BY_ANTENNAMODULEEEEEEEEEEEEEEE true o-ran-smo-teiv-ran-equipment +ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE deployed-on-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-equipment 0 1 deployed-antennaModule AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee o-ran-smo-teiv-ran-equipment 0 1 BI_DIRECTIONAL RELATION o-ran-smo-teiv-ran-equipment_ANTENNAMODULEEEEEEEEEEEE_DEPLOYED_ON_ANTENNAMODULEEEEEEEEEEEEEEE true o-ran-smo-teiv-ran-equipment \. ; + +COMMIT; diff --git a/teiv/src/test/resources/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql b/teiv/src/test/resources/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql new file mode 100644 index 0000000..9c6050f --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/02_init-oran-smo-teiv-consumer-data-v1.sql @@ -0,0 +1,48 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +CREATE SCHEMA IF NOT EXISTS ties_consumer_data; + +CREATE TABLE IF NOT EXISTS ties_consumer_data."module_reference" ( + "name" VARCHAR(511) PRIMARY KEY, + "namespace" VARCHAR(511), + "revision" VARCHAR(511), + "content" TEXT, + "ownerAppId" VARCHAR(511), + "status" VARCHAR(127) +); + +CREATE TABLE IF NOT EXISTS ties_consumer_data."classifiers" ( + "name" VARCHAR(511) PRIMARY KEY, + "moduleReferenceName" VARCHAR(511) NOT NULL, + FOREIGN KEY ("moduleReferenceName") REFERENCES ties_consumer_data."module_reference" ("name") ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS ties_consumer_data."decorators" ( + "name" VARCHAR(511) PRIMARY KEY, + "dataType" VARCHAR(511) NOT NULL, + "moduleReferenceName" VARCHAR(511) NOT NULL, + FOREIGN KEY ("moduleReferenceName") REFERENCES ties_consumer_data."module_reference" ("name") ON DELETE CASCADE +); + +COMMIT; diff --git a/teiv/src/test/resources/pgsqlschema/consumer-data-v1.sql b/teiv/src/test/resources/pgsqlschema/consumer-data-v1.sql new file mode 100644 index 0000000..fd70b75 --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/consumer-data-v1.sql @@ -0,0 +1,42 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +COPY ties_consumer_data."module_reference"("name", "namespace", "revision", "content", "ownerAppId", "status") FROM stdin; +test-app-module urn:o-ran:test-app-module 2024-05-24 bW9kdWxlIHRlc3QtYXBwLW1vZHVsZSB7CgogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOnRlc3QtYXBwLW1vZHVsZSI7CiAgICBwcmVmaXggbW9kdWxlOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCB0ZXN0OyB9CiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IG9yLXRlaXYteWV4dDsgfQoKICAgIHJldmlzaW9uICIyMDI0LTA2LTEwIiB7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICBJbml0aWFsIHJldmlzaW9uLjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgYXVnbWVudCAvdGVzdDpkZWNvcmF0b3JzIHsKICAgICAgICBsZWFmIGxvY2F0aW9uIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgfQogICAgICAgIGxlYWYgdmVuZG9yIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgfQogICAgfQoKICAgIGlkZW50aXR5IE91dGRvb3IgewogICAgICAgIGJhc2UgdGVzdDpjbGFzc2lmaWVyczsKICAgIH0KCiAgICBpZGVudGl0eSBSdXJhbCB7CiAgICAgICAgYmFzZSB0ZXN0OmNsYXNzaWZpZXJzOwogICAgfQoKICAgIGlkZW50aXR5IFdlZWtlbmQgewogICAgICAgIGJhc2UgdGVzdDpjbGFzc2lmaWVyczsKICAgIH0KCn0K APP IN_USAGE +test-app-for-deletion-module urn:o-ran:test-app-for-deletion-module 2024-05-24 bW9kdWxlIHRlc3QtYXBwLW1vZHVsZSB7CgogICAgeWFuZy12ZXJzaW9uIDEuMTsKICAgIG5hbWVzcGFjZSAidXJuOnRlc3QtYXBwLW1vZHVsZSI7CiAgICBwcmVmaXggbW9kdWxlOwoKICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy10eXBlcyB7IHByZWZpeCB0ZXN0OyB9CiAgICBpbXBvcnQgby1yYW4tc21vLXRlaXYtY29tbW9uLXlhbmctZXh0ZW5zaW9ucyB7cHJlZml4IG9yLXRlaXYteWV4dDsgfQoKICAgIHJldmlzaW9uICIyMDI0LTA2LTEwIiB7CiAgICAgICAgZGVzY3JpcHRpb24KICAgICAgICBJbml0aWFsIHJldmlzaW9uLjsKICAgICAgICBvci10ZWl2LXlleHQ6bGFiZWwgMC4zLjA7CiAgICB9CgogICAgYXVnbWVudCAvdGVzdDpkZWNvcmF0b3JzIHsKICAgICAgICBsZWFmIGxvY2F0aW9uIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgfQogICAgICAgIGxlYWYgdmVuZG9yIHsKICAgICAgICAgICAgdHlwZSBzdHJpbmc7CiAgICAgICAgfQogICAgfQoKICAgIGlkZW50aXR5IE91dGRvb3IgewogICAgICAgIGJhc2UgdGVzdDpjbGFzc2lmaWVyczsKICAgIH0KCiAgICBpZGVudGl0eSBSdXJhbCB7CiAgICAgICAgYmFzZSB0ZXN0OmNsYXNzaWZpZXJzOwogICAgfQoKICAgIGlkZW50aXR5IFdlZWtlbmQgewogICAgICAgIGJhc2UgdGVzdDpjbGFzc2lmaWVyczsKICAgIH0KCn0K APP IN_USAGE +\. + +COPY ties_consumer_data."decorators" ("name", "dataType", "moduleReferenceName" ) FROM stdin; +test-app-module:textdata TEXT test-app-module +test-app-module:intdata INT test-app-module +\. + +COPY ties_consumer_data."classifiers" ("name", "moduleReferenceName" ) FROM stdin; +test-app-module:Indoor test-app-module +test-app-module:Outdoor test-app-module +test-app-module:Rural test-app-module +test-app-module:Weekday test-app-module +test-app-module:Weekend test-app-module +\. + +COMMIT; \ No newline at end of file diff --git a/teiv/src/test/resources/data/data-deprecated.sql b/teiv/src/test/resources/pgsqlschema/data-deprecated.sql similarity index 100% rename from teiv/src/test/resources/data/data-deprecated.sql rename to teiv/src/test/resources/pgsqlschema/data-deprecated.sql diff --git a/teiv/src/test/resources/pgsqlschema/data-v1.sql b/teiv/src/test/resources/pgsqlschema/data-v1.sql new file mode 100644 index 0000000..1fd360c --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/data-v1.sql @@ -0,0 +1,322 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +COPY ties_data."o-ran-smo-teiv-oam_ManagedElement" ("id", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10", "urn:cmHandle:72FDA73D085F138FECC974CB91F1450E"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13", "urn:cmHandle:E5196035D0B49A65B00EAA392B4EE155"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14", "urn:cmHandle:D67C0BD04FA613BBFD176B24B68FD6A4"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16", "urn:cmHandle:453431CC154F900606657D584700827A"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28", "urn:cmHandle:30C68865AF2F353F202056CB1921D418"] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_Sector" ("id", "geo-location", "sectorId", "azimuth", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +Sector=1 POINT(59.4019881 17.9419888) 1 1.1 [] [] {} +Sector=2 POINT(60.4019881 18.9419888) 2 2.2 [] [] {} +Sector=3 POINT(61.4019881 19.9419888) 3 3.3 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_AntennaCapability" ("id", "eUtranFqBands", "geranFqBands", "nRFqBands", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1 ["123","456","789"] ["123","4564","789"] ["123","456","789"] ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1 ["123","456","789"] ["123","4564","789"] ["123","456","789"] ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-equipment_AntennaModule" ("id", "antennaBeamWidth", "antennaModelNumber", "electricalAntennaTilt", "geo-location", "mechanicalAntennaBearing", "mechanicalAntennaTilt", "positionWithinSector", "totalTilt", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_installed-at-site", "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_CD_sourceIds_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_CD_classifiers_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_CD_decorators_ANTENNAMODULE_INSTALLED_AT_SITE", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_ANTENNAMODULE", "REL_CD_sourceIds_SECTOR_GROUPS_ANTENNAMODULE", "REL_CD_classifiers_SECTOR_GROUPS_ANTENNAMODULE", "REL_CD_decorators_SECTOR_GROUPS_ANTENNAMODULE") FROM stdin; +urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A \N 5 11 POINT(39.4019881 67.9419888) 6 0 7 -900 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1", "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1", "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,Equipment=1,AntennaUnitGroup=1,AntennaNearUnit=1,RetSubUnit=1", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} \N \N [] [] {} Sector=2 urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=44F4F4FC906E9A7525065E4565246F7469CBD11FC7752C61EA6D74776845900AFF472DCAACA1F66443490B6CE0DD9AC9A5E1467022118599F6B4C6EC63400512 [] [] {} +urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7 \N 5 11 POINT(49.4019881 68.9419888) 6 0 7 -900 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1", "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaUnit=1,AntennaSubunit=1", "urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,Equipment=1,AntennaUnitGroup=1,AntennaNearUnit=1,RetSubUnit=1", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} \N \N [] [] {} Sector=2 urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_ANTENNAMODULE=CEEC51BE136D671D2101C09FEDD8A1D95E1E177A4818E9FC0D6E63E610BC8FE26FC9C729A1E58AD43D70472F4CD54403E25CB1E5D2BBA66966625C21435C4A78 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_GNBCUCPFunction" ("id", "gNBCUName", "gNBId", "gNBIdLength", "pLMNId", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUCPFunction=9 gnbcucp-9 9 1 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUCPFunction=9", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=0F7F3F3CEC7B3CDA05A7B7D2874D1EF39EBDAA18AD7D6F43CF219C087510114C59C6B78EC21F8E9C6F19B5F1999FBBA2DF8C3DDF76F416C874508303F0DA4AB4 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUCPFunction=10 gnbcucp-10 10 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUCPFunction=10", "urn:cmHandle:72FDA73D085F138FECC974CB91F1450E"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=7053BF6EEB9769084BB91850C356BF20E3C9D6AD8F0D7212911DC827AD1B4D42AEDA0C43FD5715C94E14334EF49FA09405A976451B777B442BBF397DE89528A4 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBCUCPFunction=13 gnbcucp-13 13 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBCUCPFunction=13", "urn:cmHandle:E5196035D0B49A65B00EAA392B4EE155"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=C88ACE9CD7BA7E56FD059C027DA8E4D0ED0A3E13F9E358D5F4A66EE004FC3767A9D20B0512661B6D2F5F82F106725C04C5DC8826D990DECB4D5AD571BE402BE0 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBCUCPFunction=14 gnbcucp-14 14 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBCUCPFunction=14", "urn:cmHandle:D67C0BD04FA613BBFD176B24B68FD6A4"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=F23FADEDC45AE38DBC567C57FC4DD5D61D239B0BEF3C93DD54DF85545E6D0C8B9B26A1D3911B56A3F8C2EB148A4F276D1EBAF7EE2D2E35C8B37F008F572DF7B6 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBCUCPFunction=16 gnbcucp-16 16 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBCUCPFunction=16", "urn:cmHandle:453431CC154F900606657D584700827A"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=5ECE0941DDBC9B4DEE8492333129A0AB80720CB6005A80B54C4D9247029A41FA42DB6D2C709F71D7ED5D82F5EA90CE2C0B553AC1BD860D8A6DFA218E2E790F1C [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBCUCPFunction=19 gnbcucp-19 19 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBCUCPFunction=19", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=63EA5A9F77FE5DED61CF6DC30233AB17A57D6E04283365D7C1976FF646961FAAF1889BBA618029EA10DA8761F8DAA643B707B602D4E61898A2B5259AA0118887 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBCUCPFunction=28 gnbcucp-28 28 2 {"mcc":"01","mnc":"234"} ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBCUCPFunction=28", "urn:cmHandle:30C68865AF2F353F202056CB1921D418"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION=CD564BF182FD6DE77816BA69F25B664374AD02D642DF05FF8991E1009E7E09C50E92F6858A1E1B025CFDA933AB769B8C68FBAE0DBBAA140AE321DC55AED6C2A3 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_GNBCUUPFunction" ("id", "gNBId", "gNBIdLength", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9 9 1 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBCUUPFunction=9", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=5255F37093F8EB3763CE5F017DFC1E162B44FC9DF6E13744C04DC1832C5E754AB7BE440DBE1187EE8EEE42FD04E652BB8148655C6F977B1FFDDA54FE87C6411A [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUUPFunction=10 10 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBCUUPFunction=10", "urn:cmHandle:72FDA73D085F138FECC974CB91F1450E"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=80D3B4C44B4F0BEFC7660AF0A4E91F89C8108DA814B09728F848C0C5C10E2D956A73FBC85EB2AE0A7EA4D95308A606856603B53C8C2669A50BCB58B9FC87D7F2 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBCUUPFunction=13 13 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBCUUPFunction=13", "urn:cmHandle:E5196035D0B49A65B00EAA392B4EE155"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=29DE1D3B8DA9C9FA1201C36F74FEBE14493F7C674E47E1FFCB6AADEED8EABB0460770EC21E7AC8EEBBB057ABC0E31269AB5C92D941E9BA53877164918C6EFB30 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBCUUPFunction=14 14 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBCUUPFunction=14", "urn:cmHandle:D67C0BD04FA613BBFD176B24B68FD6A4"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=4C571BDD5DF9B297C1B249D0242EB9DDC77052BB0A33E62DB851809A075259EE3A0C354FA3978276BD5EE0BBB8CFDBF19F7C3C7017F828B9A2EBAD020E7FDF98 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBCUUPFunction=16 16 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBCUUPFunction=16", "urn:cmHandle:453431CC154F900606657D584700827A"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=DD5E12CB8D14C89E1C199BDABBCC71908F76AB04FE8FD7F7334A9A403B5BE0D8BB5DA69B4258C7AF4834BF2D3E00B6D5C263AD38A83A22E7EC673ACE1CAF0CF2 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBCUUPFunction=19 19 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBCUUPFunction=19", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=2AF48E294918A4EE0E3E7C783A70841E1DEEF72CDD43FE3CD1DF6531CCA06203B574BE02553254220A637632AECB719951DAE2A3D0487D24EA1A090843563603 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBCUUPFunction=28 28 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBCUUPFunction=28", "urn:cmHandle:30C68865AF2F353F202056CB1921D418"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION=140E8C8C56B1E717CD992D3FF0C61C04C1633E1FEF17ABB92A9A17C53E18CFAF5D72C4C71415E0026C99671657FB3EC1BD394174DD306261ADA8A6CDF4D42748 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_GNBDUFunction" ("id", "dUpLMNId", "gNBDUId", "gNBId", "gNBIdLength", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 {"mcc":"123","mnc":"82"} \N 9 1 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] ["test-app-module:Indoor","test-app-module:Weekend"] {"test-app-module:textdata":"ORAN"} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=9243B48F7D6A6CF471226915C74CF5FE4BDA6FA3CF7D897473007B46DF7FC50230BD6B8B4256116A6AFBF4D822CF9379EB56DE9490C1C0B54238263F2574B426 [] ["test-app-module:Indoor","test-app-module:Weekend"] {"test-app-module:textdata":"ORAN"} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10 {"mcc":"456","mnc":"83"} \N 10 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10,GNBDUFunction=10", "urn:cmHandle:72FDA73D085F138FECC974CB91F1450E"] [] {"test-app-module:textdata":"Budapest","test-app-module:intdata":123} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=10 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=661A89AD3C2702233CD9E96E97E738C05C35EC5FDF32DC78D149B773726350067315B72448D004C938BCD0263F0C4BCCC8A5F9CDD145B9B740983D1523664328 [] ["test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Budapest","test-app-module:intdata":123} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13 {"mcc":"789","mnc":"84"} \N 13 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13,GNBDUFunction=13", "urn:cmHandle:E5196035D0B49A65B00EAA392B4EE155"] ["test-app-module:Indoor"] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":456} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=13 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=DD9259A1B57FF2BB9DEC77C29DBFA4A5C49960D80622F603809ACA47E786DDD5C7ABD267D554A7C796477A9B2E02E072A8E682E4ED38F331BFB6DC3827CE4DB7 [] [] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":456} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14 {"mcc":"123","mnc":"85"} \N 14 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14,GNBDUFunction=14", "urn:cmHandle:D67C0BD04FA613BBFD176B24B68FD6A4"] ["test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":123} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=14 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6F7BFBD3DA2A9A592084C75242210A33C9DCF10CFCD53B761A6ACCD385132921679EC3C16394A4DEEE5883712C9719511388230151BA84FBF209DFCFB639E2EA [] [] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":123} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16 {"mcc":"456","mnc":"86"} 16 16 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16,GNBDUFunction=16", "urn:cmHandle:453431CC154F900606657D584700827A"] ["test-app-module:Indoor","test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":123} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=16 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=D67357F682531C7B068486313B0FDAC3E719A166229520196FB9CE917E0236754226A5BCBF7BB7240E516D7ED3FEA852855EC3F121DD4BAFEC5646F2A37F57EE [] ["test-app-module:Indoor","test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Stockholm","test-app-module:intdata":123} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19 {"mcc":"789","mnc":"87"} \N 19 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=6BD25E5C8FB7842F69010736253CC47F43535D7238E9E9A03E8092E8C019C83270DE47C96EF1049C40B83A130F9F129AE93B9C8538B6B004AE89BD0A098E48DD [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBDUFunction=28 {"mcc":"123","mnc":"88"} \N 28 2 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28,GNBDUFunction=28", "urn:cmHandle:30C68865AF2F353F202056CB1921D418"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=28 urn:o-ran:smo:teiv:sha512:MANAGEDELEMENT_MANAGES_GNBDUFUNCTION=ADD4A82DFBAF0409FA9D3C929A09314088627B447C733429D4EE7AAE2FFAEE4894F90826B6814B63431EC07140783C7861E463C5AF8330E29469D704675EAB43 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_NRCellDU" ("id", "cellLocalId", "nCI", "nRPCI", "nRTAC", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRCELLDU", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_NRCELLDU", "REL_CD_sourceIds_SECTOR_GROUPS_NRCELLDU", "REL_CD_classifiers_SECTOR_GROUPS_NRCELLDU", "REL_CD_decorators_SECTOR_GROUPS_NRCELLDU") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1 1 1 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=4E40BE000AFEA418CE1B9ED9E21D38DA51772175BD498BE825D9EA362F9B7393C36AB72F6FDEE702439143D578268A2E84719A9352C8EA70F847B7B7664E047C [] [] {} Sector=2 urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=4BBE73F685A98EF799968ACFE76F376D795F4CC3B56A6B867642048CDF4C1B8E323430EA7C6C38E4031FB891158763CC5459A8704E1A9FBFBD53CE8AD23BF463 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2 2 2 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=78ECC09D4832328976EF0F9C19699EE05D98E3837368D386AE39AD027543494AC620086BD2A7403DACFAA7B474B3DEBD313E0906F1EDE7FA2B584E16542A706A [] [] {} Sector=2 urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=46AAB2CC5388BECD7B2180C89EEFA64B9A3BC197B614B57FD4BD9ADACE2475A89E16BA04291DE1674FAF2925483E23B8EDCAD4EE98759A9C08E2677CD88F4C43 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3 3 3 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=714C1B73945C298CAA03FE0D800053CDD1C571BBF375DC647B9F23FDA861CEB369832A3593BB1AA4B8A7245AD187ED24ADDF6FB147130827CDC17BA8370C4838 [] [] {} Sector=2 urn:o-ran:smo:teiv:sha512:SECTOR_GROUPS_NRCELLDU=F892571703F0E20A37F3950818DEFA9991ACF35828EEEBD3E43404218F947E1F522258A1F31F4C82A53E7E60D9E1A7AC7AC4219A0D9DD0D8FD192BC73BBB5101 [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91 91 91 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=91", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} \N \N [] [] {} \N \N [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=92 92 92 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=92", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=DDECCEFB8831FA4EB21B121BA35EAB07ED8D841B5A38580C5F3AD11E66FE73D2FC42E823C6C73288860C7562B610C3D07B6C39FD386171A3BE622096F4B3D006 [] [] {} \N \N [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=93 93 93 789 456 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19,NRCellDU=93", "urn:cmHandle:03661FA2E41EF3D12CAAD5954CD985AC"] ["test-app-module:Rural"] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,GNBDUFunction=19 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRCELLDU=7723E5D5B3332E0890EAA620C77A6A47065E15A2EA28AD83F3B3CFEA5A7E3BB5965AE78890F1BF000EAA89BF8DE209E506192BF5EA6871426603ED76CBFAF088 [] [] {} \N \N [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_NRSectorCarrier" ("id", "arfcnDL", "arfcnUL", "bSChannelBwDL", "frequencyDL", "frequencyUL", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_CD_sourceIds_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_CD_classifiers_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_CD_decorators_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_FK_used-by-nrCellDu", "REL_ID_NRCELLDU_USES_NRSECTORCARRIER", "REL_CD_sourceIds_NRCELLDU_USES_NRSECTORCARRIER", "REL_CD_classifiers_NRCELLDU_USES_NRSECTORCARRIER", "REL_CD_decorators_NRCELLDU_USES_NRSECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_sourceIds_NRSECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_classifiers_NRSECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_decorators_NRSECTORCARRIER_USES_ANTENNACAPABILITY") FROM stdin; +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=1 507000 507000 10000 2535000 2535000 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=1", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER=BE61426CAEA457C85D8B551A1A75BFA157BBCE6F143110661C4C9D406A7AAF22D8522515CE924CFB3A9E54E68588A45D3A51065BD24ADBA62CC0FDA761AEE2FC [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=1 urn:o-ran:smo:teiv:sha512:NRCELLDU_USES_NRSECTORCARRIER=7B9425BBD6977FEA6C180F6078CFBAEBE65400223B29E0EFA4F38424FAD66C690806778909177ECF1457CAC18E5BCF6FA4F24E3ECE524C89DE68108708D6D876 [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1 urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=11EDFC31E2BE240D3CB15DB1A3FA3B78C828524BC8FCA3365A615129A61A627C21DA8EBF6DD788CDBDEC668344D1F79A371749083D6AE04DDDD57CB4FA8C3ECB [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=2 507000 507000 10000 2535000 2535000 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=2", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER=C0E73797DB4599AB9ECACFC1FFE3543C92926070ECFBE77E7C15BA99DAFBB1D69352533D3DE5EB2D3D3CC84DAD51B242CB0FC594FF9E8B73C3B42106B0F9AF46 [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=2 urn:o-ran:smo:teiv:sha512:NRCELLDU_USES_NRSECTORCARRIER=2F87CE31F38D38B993786E3D75D253984DA2842F71504958AAF052D0728B309C73BB3132D6BEA011748BB0B94F489725DB5765AB5366702B812D5C76A772BD9C [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1 urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=27DF07D016FE349EC565DE2FB09303EE7D8700346624046F79D8DAC176E7FA221E918E3030758B51931C430919E14FD7D16720460F6E1585000C72874A1641DA [] [] {} +urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=3 507000 507000 10000 2535000 2535000 ["urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRSectorCarrier=3", "urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9 urn:o-ran:smo:teiv:sha512:GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER=BD87BC547A6731B2905A989EBA493810C74258337C49BBB288F4F55734D28B4E40D9C719EC3564348253905BD93EC78EB7C88F2297FF20778911635E94800F74 [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,GNBDUFunction=9,NRCellDU=3 urn:o-ran:smo:teiv:sha512:NRCELLDU_USES_NRSECTORCARRIER=950ED4540349F9859CEA9E47884A28CD567BDD2505A3C5335C8851A7AADF2AF65542157BB42D607EE3847E4223D76DE88B90762D0590E48693822FD6DCAE60CD [] [] {} urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1 urn:o-ran:smo:teiv:sha512:NRSECTORCARRIER_USES_ANTENNACAPABILITY=1B891FCC4F5479BC71127ED2EB43EA26AC3452F8C47792786373442C10BBC408FE5B779BF1CF732C81220803342F4FB969E348F9C5CEEDEC78F9764E186C633F [] [] {} +\. + +COPY ties_data."CFC235E0404703D1E4454647DF8AAE2C193DB402" ("id", "aSide_AntennaModule", "bSide_AntennaCapability", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +urn:o-ran:smo:teiv:sha512:ANTENNAMODULE_SERVES_ANTENNACAPABILITY=ABD52B030DF1169F9F41C898913EF30F7BB5741F53352F482310B280C90AC569B7D31D52A2BB41F1F0099AE1EDD56CACF0B285D145A5584D376DD45DED1E2D65 urn:o-ran:smo:teiv:sha512:AntennaModule=308D6602D2FE1C923DF176A0F30688B1810DFA7BC4AD5B8050BF9E27361ECA86E86B47B8582DC28E8CE92EB81822DE248845E87094557A953FD9F15BA508B03A urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=9,NodeSupport=1,SectorEquipmentFunction=1 [] [] {} +urn:o-ran:smo:teiv:sha512:ANTENNAMODULE_SERVES_ANTENNACAPABILITY=8940999E2069725B463052BC35572FDB888C7B734459EE78A01B9F91E2607D87356425BC8EFF0B1C9057D852A4D3F9E1B09479D32FEE68C65EF2821B65F7BD80 urn:o-ran:smo:teiv:sha512:AntennaModule=971FCD28D02B78DDD982611639A0957140339C5522EAAF3FBACA1B8308CF7B0A870CFA80AE04E259805B2A2CB95E263261309883B4D4BF50183FA17AFBA47EA7 urn:3gpp:dn:SubNetwork=Europe,SubNetwork=Hungary,MeContext=1,ManagedElement=19,NodeSupport=1,SectorEquipmentFunction=1 [] [] {} +\. + +COPY ties_data."o-ran-smo-teiv-ran_ENodeBFunction" ("id", "eNBId", "eNodeBPlmnId", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "REL_CD_sourceIds_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION") FROM stdin; +\. + +COPY ties_data."o-ran-smo-teiv-ran_EUtranCell" ("id", "cellId", "channelBandwidth", "dlChannelBandwidth", "duplexType", "earfcn", "earfcndl", "earfcnul", "tac", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL", "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_EUTRANCELL", "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_EUTRANCELL", "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_EUTRANCELL", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_EUTRANCELL", "REL_CD_sourceIds_SECTOR_GROUPS_EUTRANCELL", "REL_CD_classifiers_SECTOR_GROUPS_EUTRANCELL", "REL_CD_decorators_SECTOR_GROUPS_EUTRANCELL") FROM stdin; +\. + +COPY ties_data."o-ran-smo-teiv-ran_LTESectorCarrier" ("id", "sectorCarrierType", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_CD_sourceIds_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_CD_classifiers_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_CD_decorators_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_FK_used-by-euTranCell", "REL_ID_EUTRANCELL_USES_LTESECTORCARRIER", "REL_CD_sourceIds_EUTRANCELL_USES_LTESECTORCARRIER", "REL_CD_classifiers_EUTRANCELL_USES_LTESECTORCARRIER", "REL_CD_decorators_EUTRANCELL_USES_LTESECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_sourceIds_LTESECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_classifiers_LTESECTORCARRIER_USES_ANTENNACAPABILITY", "REL_CD_decorators_LTESECTORCARRIER_USES_ANTENNACAPABILITY") FROM stdin; +\. + +COPY ties_data."o-ran-smo-teiv-ran_NRCellCU" ("id", "cellLocalId", "nCI", "nRTAC", "plmnId", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-gnbcucpFunction", "REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU", "REL_CD_sourceIds_GNBCUCPFUNCTION_PROVIDES_NRCELLCU", "REL_CD_classifiers_GNBCUCPFUNCTION_PROVIDES_NRCELLCU", "REL_CD_decorators_GNBCUCPFUNCTION_PROVIDES_NRCELLCU") FROM stdin; +\. + +COPY ties_data."o-ran-smo-teiv-equipment_Site" ("id", "geo-location", "name", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +\. + +-- Test specific entries -- + +CREATE TABLE IF NOT EXISTS ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ( + "id" TEXT, + "6446B2D4BE5E367FB0396383C4BDEF42D51CF74F" TEXT, + "F03B534AFF0872651FED60C54AB56BEDADAB94B5" BIGINT, + "333177AA699C0DE6399503171DCF48FB396322B0" INTEGER, + "027B1A8019C6DEF04558B90D9D8B52253B82FEC6" BIGINT, + "478D043D81678134EF1C8BFB073A70F882C4AF12" DECIMAL, + "8252D18D44F633831557076D827993C45278024D" jsonb, + "68C48305AB6C3A30DD927F5D38562379374A4B31" jsonb, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_provided-by-entityTypeA" TEXT, + "REL_ID_F64052A4F8BB3CC533EC15BBFB5E224F600735B0" TEXT, + "REL_CD_F26C39EC1F710F3096BE0588F6783A03A378516A" jsonb, + "REL_CD_E2C3D598A06EA38133E23C1756ED58A66FE21386" jsonb, + "REL_CD_92559ED73C761B860682582A040E745ECEC194D5" jsonb +); + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "REL_CD_F26C39EC1F710F3096BE0588F6783A03A378516A" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "REL_CD_E2C3D598A06EA38133E23C1756ED58A66FE21386" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ALTER COLUMN "REL_CD_92559ED73C761B860682582A040E745ECEC194D5" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ( + "id" TEXT, + "aSide_EntityTypeA" TEXT, + "bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ( + "id" TEXT, + "aSide_C812C285BEFA4EC42026AB075D9C65200A00F815" TEXT, + "bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb +); + +ALTER TABLE ONLY ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +CREATE TABLE IF NOT EXISTS ties_data."test-built-in-module_EntityTypeA" ( + "id" TEXT, + "CD_sourceIds" jsonb, + "CD_classifiers" jsonb, + "CD_decorators" jsonb, + "REL_FK_B7E43411C5C5079D49856E74A9FA63BD20C522C5" TEXT, + "REL_ID_31A5B55158140557F09AE15589A8B8038416689B" TEXT, + "REL_CD_AB6BDADE3F6C750C9FDB6CAD6059C4CBCE67236C" jsonb, + "REL_CD_75B161E740A96ADBAE6F08D4F85684ECC29049B9" jsonb, + "REL_CD_6F7211CAF505AECF9A565BC7A4AF56E7032CCC54" jsonb, + "REL_FK_A86937FEBD025CFDF6EE5BC386B4C569EB2652DA" TEXT, + "REL_ID_A974AD6DD8C4CA281D45693D3A61AE98FEE82845" TEXT, + "REL_CD_3B43F80D423BF8F96A2906643B7B4712604FC28B" jsonb, + "REL_CD_74A44B167FDF37D6C8E79B5033FEF8BC384C881A" jsonb, + "REL_CD_F5B24D9A7273119D4D1519473D9EC88CB407E5CA" jsonb +); + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "CD_sourceIds" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "CD_classifiers" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "CD_decorators" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_AB6BDADE3F6C750C9FDB6CAD6059C4CBCE67236C" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_75B161E740A96ADBAE6F08D4F85684ECC29049B9" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_6F7211CAF505AECF9A565BC7A4AF56E7032CCC54" SET DEFAULT '{}'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_3B43F80D423BF8F96A2906643B7B4712604FC28B" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_74A44B167FDF37D6C8E79B5033FEF8BC384C881A" SET DEFAULT '[]'; + +ALTER TABLE ONLY ties_data."test-built-in-module_EntityTypeA" ALTER COLUMN "REL_CD_F5B24D9A7273119D4D1519473D9EC88CB407E5CA" SET DEFAULT '{}'; + +SELECT ties_data.create_constraint_if_not_exists( + '10B9F515756871D3EF6558FAF1F112BAE207945D', + 'PK_7A421D526B36AA9EEF17964BC27011A12FF80DBB', + 'ALTER TABLE ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ADD CONSTRAINT "PK_7A421D526B36AA9EEF17964BC27011A12FF80DBB" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + '54110F8D085BBBA7BB6DE5CE71B511562090F7EE', + 'PK_4C48AAFA2160D74F9D13364AA2BE4FDB8A60689D', + 'ALTER TABLE ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ADD CONSTRAINT "PK_4C48AAFA2160D74F9D13364AA2BE4FDB8A60689D" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'FB1E124031A12CD85D3335194B39B193723A0490', + 'PK_020B03AED5787D1B43ABBD9F2C26B494ADDBC7CD', + 'ALTER TABLE ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ADD CONSTRAINT "PK_020B03AED5787D1B43ABBD9F2C26B494ADDBC7CD" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'test-built-in-module_EntityTypeA', + 'PK_test-built-in-module_EntityTypeA_id', + 'ALTER TABLE ties_data."test-built-in-module_EntityTypeA" ADD CONSTRAINT "PK_test-built-in-module_EntityTypeA_id" PRIMARY KEY ("id");' +); + +SELECT ties_data.create_constraint_if_not_exists( + '10B9F515756871D3EF6558FAF1F112BAE207945D', + 'FK_B0923C0CCED6CF47CFF759FFE1B810D6CA10D228', + 'ALTER TABLE ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ADD CONSTRAINT "FK_B0923C0CCED6CF47CFF759FFE1B810D6CA10D228" FOREIGN KEY ("REL_FK_provided-by-entityTypeA") REFERENCES ties_data."test-built-in-module_EntityTypeA" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + '10B9F515756871D3EF6558FAF1F112BAE207945D', + 'UNIQUE_B1C2FC9A96300B2BE45785DE60E152D8E85FBE14', + 'ALTER TABLE ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ADD CONSTRAINT "UNIQUE_B1C2FC9A96300B2BE45785DE60E152D8E85FBE14" UNIQUE ("REL_ID_F64052A4F8BB3CC533EC15BBFB5E224F600735B0");' +); + +SELECT ties_data.create_constraint_if_not_exists( + '54110F8D085BBBA7BB6DE5CE71B511562090F7EE', + 'FK_2839E6FFDF7F3DF2687DAC3E57082AD6B22E9B30', + 'ALTER TABLE ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ADD CONSTRAINT "FK_2839E6FFDF7F3DF2687DAC3E57082AD6B22E9B30" FOREIGN KEY ("aSide_EntityTypeA") REFERENCES ties_data."test-built-in-module_EntityTypeA" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + '54110F8D085BBBA7BB6DE5CE71B511562090F7EE', + 'FK_33B5669A341584011D9A73FB491FF2242A158057', + 'ALTER TABLE ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ADD CONSTRAINT "FK_33B5669A341584011D9A73FB491FF2242A158057" FOREIGN KEY ("bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515") REFERENCES ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" (id) ON DELETE CASCADE;' +); + + +SELECT ties_data.create_constraint_if_not_exists( + 'FB1E124031A12CD85D3335194B39B193723A0490', + 'FK_2A5C84A2226EE0FCAAA513CC5AF4CD78DDDAF49F', + 'ALTER TABLE ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ADD CONSTRAINT "FK_2A5C84A2226EE0FCAAA513CC5AF4CD78DDDAF49F" FOREIGN KEY ("aSide_C812C285BEFA4EC42026AB075D9C65200A00F815") REFERENCES ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'FB1E124031A12CD85D3335194B39B193723A0490', + 'FK_FBFE10B6F165A8EC2086B8DEAFA238E0DD6643F5', + 'ALTER TABLE ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ADD CONSTRAINT "FK_FBFE10B6F165A8EC2086B8DEAFA238E0DD6643F5" FOREIGN KEY ("bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515") REFERENCES ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'test-built-in-module_EntityTypeA', + 'FK_02592FFA6AFD7EAC7AFAD936E3CD50708E4533E0', + 'ALTER TABLE ties_data."test-built-in-module_EntityTypeA" ADD CONSTRAINT "FK_02592FFA6AFD7EAC7AFAD936E3CD50708E4533E0" FOREIGN KEY ("REL_FK_B7E43411C5C5079D49856E74A9FA63BD20C522C5") REFERENCES ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'test-built-in-module_EntityTypeA', + 'UNIQUE_7715FF94E14F99CE4994ABBD8C2583CBA9EAE5BD', + 'ALTER TABLE ties_data."test-built-in-module_EntityTypeA" ADD CONSTRAINT "UNIQUE_7715FF94E14F99CE4994ABBD8C2583CBA9EAE5BD" UNIQUE ("REL_ID_31A5B55158140557F09AE15589A8B8038416689B");' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'test-built-in-module_EntityTypeA', + 'FK_5CD9BCFA08278DA0BF902BAFBCFCDFCE4FF25FEF', + 'ALTER TABLE ties_data."test-built-in-module_EntityTypeA" ADD CONSTRAINT "FK_5CD9BCFA08278DA0BF902BAFBCFCDFCE4FF25FEF" FOREIGN KEY ("REL_FK_A86937FEBD025CFDF6EE5BC386B4C569EB2652DA") REFERENCES ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" (id) ON DELETE CASCADE;' +); + +SELECT ties_data.create_constraint_if_not_exists( + 'test-built-in-module_EntityTypeA', + 'UNIQUE_67DB5E4BC34AB83BDC069A5CAF73B57967D5C2D9', + 'ALTER TABLE ties_data."test-built-in-module_EntityTypeA" ADD CONSTRAINT "UNIQUE_67DB5E4BC34AB83BDC069A5CAF73B57967D5C2D9" UNIQUE ("REL_ID_A974AD6DD8C4CA281D45693D3A61AE98FEE82845");' +); + +COPY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ("id", "6446B2D4BE5E367FB0396383C4BDEF42D51CF74F", "F03B534AFF0872651FED60C54AB56BEDADAB94B5", "333177AA699C0DE6399503171DCF48FB396322B0", "027B1A8019C6DEF04558B90D9D8B52253B82FEC6", "478D043D81678134EF1C8BFB073A70F882C4AF12", "8252D18D44F633831557076D827993C45278024D", "68C48305AB6C3A30DD927F5D38562379374A4B31", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +LongEntityType1 someStringValue 9223372036854775807 2147483647 -9223372036854775807 1.1 ["1000", "2000"] {"mcc":"01","mnc":"234"} [] [] {} +\. + +COPY ties_data."test-built-in-module_EntityTypeA" ("id", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_B7E43411C5C5079D49856E74A9FA63BD20C522C5", "REL_ID_31A5B55158140557F09AE15589A8B8038416689B", "REL_CD_AB6BDADE3F6C750C9FDB6CAD6059C4CBCE67236C", "REL_CD_75B161E740A96ADBAE6F08D4F85684ECC29049B9", "REL_CD_6F7211CAF505AECF9A565BC7A4AF56E7032CCC54", "REL_FK_A86937FEBD025CFDF6EE5BC386B4C569EB2652DA", "REL_ID_A974AD6DD8C4CA281D45693D3A61AE98FEE82845", "REL_CD_3B43F80D423BF8F96A2906643B7B4712604FC28B", "REL_CD_74A44B167FDF37D6C8E79B5033FEF8BC384C881A", "REL_CD_F5B24D9A7273119D4D1519473D9EC88CB407E5CA") FROM stdin; +EntityType1 [] [] {} \N \N [] [] {} LongEntityType1 RelId_OneToOne_EntityType1_LongEntityType1 [] [] {} +EntityType2 [] [] {} LongEntityType1 Rel_ManyToOne_EntityType2_LongEntityType1 [] [] {} \N \N [] [] {} +\. + +COPY ties_data."10B9F515756871D3EF6558FAF1F112BAE207945D" ("id", "6446B2D4BE5E367FB0396383C4BDEF42D51CF74F", "F03B534AFF0872651FED60C54AB56BEDADAB94B5", "333177AA699C0DE6399503171DCF48FB396322B0", "027B1A8019C6DEF04558B90D9D8B52253B82FEC6", "478D043D81678134EF1C8BFB073A70F882C4AF12", "8252D18D44F633831557076D827993C45278024D", "68C48305AB6C3A30DD927F5D38562379374A4B31", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_FK_provided-by-entityTypeA", "REL_ID_F64052A4F8BB3CC533EC15BBFB5E224F600735B0", "REL_CD_F26C39EC1F710F3096BE0588F6783A03A378516A", "REL_CD_E2C3D598A06EA38133E23C1756ED58A66FE21386", "REL_CD_92559ED73C761B860682582A040E745ECEC194D5") FROM stdin; +LongEntityType2 \N \N \N \N \N \N \N [] [] {} EntityType2 Rel_OneToMany_EntityType2_LongEntityType2 [] [] {} +LongEntityType3 \N \N \N \N \N \N \N [] [] {} \N \N [] [] {} +\. + +COPY ties_data."54110F8D085BBBA7BB6DE5CE71B511562090F7EE" ("id", "aSide_EntityTypeA", "bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +Rel_ManyToMany_EntityType1_LongEntityType1 EntityType1 LongEntityType1 [] [] {} +\. + +COPY ties_data."FB1E124031A12CD85D3335194B39B193723A0490" ("id", "aSide_C812C285BEFA4EC42026AB075D9C65200A00F815", "bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515", "CD_sourceIds", "CD_classifiers", "CD_decorators") FROM stdin; +Rel_OneToOne_SameEntity_LongEntityType1_LongEntityType2 LongEntityType1 LongEntityType2 ["urn:cmHandle:C4388D6BB970EC663F88B46CC14F8616"] ["test-app-module:Weekday"] {"test-app-module:textdata":"ORAN","test-app-module:intdata":123} +Rel_OneToOne_SameEntity_LongEntityType2_LongEntityType3 LongEntityType2 LongEntityType3 ["urn:cmHandle:C4388D6BB970EC663F88B46CC14F8617"] ["test-app-module:Weekend"] {"test-app-module:textdata":"ORAN","test-app-module:intdata":234} +\. + +COMMIT; + diff --git a/teiv/src/test/resources/data/data.sql b/teiv/src/test/resources/pgsqlschema/data.sql similarity index 62% rename from teiv/src/test/resources/data/data.sql rename to teiv/src/test/resources/pgsqlschema/data.sql index a9dd18a..49dc28b 100644 --- a/teiv/src/test/resources/data/data.sql +++ b/teiv/src/test/resources/pgsqlschema/data.sql @@ -19,14 +19,15 @@ -- ============LICENSE_END========================================================= -- -COPY ties_data."CloudNativeSystem" ("id", "name", "REL_FK_deployed-managedElement" ) FROM stdin; + +COPY ties_data."163276fa439cdfccabb80f7acacb6fa638e8d314" ("id", "name", "REL_FK_deployed-managedElement" ) FROM stdin; \. -COPY ties_data."003B7CAE0FA8C3C54BE1BAD8BB9A50985A2EA03F" ("id", "name", "REL_FK_C2F5EC33C0760F653CE7263A49C0B697FCA2D542" ) FROM stdin; +COPY ties_data."ef701af8e1445ed5d377664ba1d3d1c645e31639" ("id", "name", "REL_FK_C2F5EC33C0760F653CE7263A49C0B697FCA2D542" ) FROM stdin; C4E311A55666726FD9FE25CA572AFAF9 Example Cloud Native System/1 \N \. -COPY ties_data."ManagedElement" ("id", "cmId", "fdn", "REL_FK_deployed-as-cloudNativeSystem", "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-oam_ManagedElement" ("id", "cmId", "fdn", "REL_FK_deployed-as-cloudNativeSystem", "REL_ID_MANAGEDELEMENT_DEPLOYED_AS_CLOUDNATIVESYSTEM" ) FROM stdin; DA1039E77700A9EEFFA280049ECE9227 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=9 \N \N 6F02817AFE4D53237DB235EBE5378613 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=10 \N \N 27500EB447000209EE6E3CA1B31FBA92 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=13 \N \N @@ -36,7 +37,7 @@ DC86CA7724113F4C0DF42BFEAA17FD53 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubN E64371CD4D12ED0CED200DD3A7591784 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=28 \N \N \. -COPY ties_data."1EF2A41C34A961CD8AE603E020B7B8B57345267F" ("id", "cmId", "fdn", "REL_FK_26958E3A529C4C8B68A29FDA906F8CD290F66078", "REL_ID_B7945BFD83380F3E12CF99F2B0F838F364027F92" ) FROM stdin; +COPY ties_data."fa2dceaf53e045c136ce9db9bc5faae65a29fa4d" ("id", "cmId", "fdn", "REL_FK_26958E3A529C4C8B68A29FDA906F8CD290F66078", "REL_ID_B7945BFD83380F3E12CF99F2B0F838F364027F92" ) FROM stdin; 45EF31D8A1FD624D7276390A1215BFC3 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=1 C4E311A55666726FD9FE25CA572AFAF9 urn:base64:TWFuYWdlZEVsZW1lbnQ6NDVFRjMxRDhBMUZENjI0RDcyNzYzOTBBMTIxNUJGQzM6REVQTE9ZRURfQVM6Q2xvdWROYXRpdmVTeXN0ZW06QzRFMzExQTU1NjY2NzI2RkQ5RkUyNUNBNTcyQUZBRjk= DA1039E77700A9EEFFA280049ECE9227 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=9 \N \N 6F02817AFE4D53237DB235EBE5378613 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=10 \N \N @@ -47,73 +48,73 @@ DC86CA7724113F4C0DF42BFEAA17FD53 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubN E64371CD4D12ED0CED200DD3A7591784 \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/ManagedElement=28 \N \N \. -COPY ties_data."CloudSite" ("id", "geo-location", "name" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-cloud_CloudSite" ("id", "geo-location", "name" ) FROM stdin; 16EE17AE89DF11B69E94B3F6827C2C0E POINT(59.4019881 17.9419888) ORAN \. -COPY ties_data."NodeCluster" ("id", "name", "REL_FK_located-at-cloudSite", "REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-cloud_NodeCluster" ("id", "name", "REL_FK_located-at-cloudSite", "REL_ID_NODECLUSTER_LOCATED_AT_CLOUDSITE" ) FROM stdin; 015C2DDBD7AC722B34ED6A20EDEEB9C3 Example NodeCluster/45 16EE17AE89DF11B69E94B3F6827C2C0E urn:base64:Tm9kZUNsdXN0ZXI6MDE1QzJEREJEN0FDNzIyQjM0RUQ2QTIwRURFRUI5QzM6TE9DQVRFRF9BVDpDbG91ZFNpdGU6MTZFRTE3QUU4OURGMTFCNjlFOTRCM0Y2ODI3QzJDMEU= \. -COPY ties_data."Namespace" ("id", "name", "REL_FK_deployed-on-nodeCluster", "REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-cloud_Namespace" ("id", "name", "REL_FK_deployed-on-nodeCluster", "REL_ID_NAMESPACE_DEPLOYED_ON_NODECLUSTER" ) FROM stdin; 1C02E96B2AAE036C7AE404BC38C308E0 Example Namespace/1 \N \N \. -COPY ties_data."78682DB1FFA2533BA45F8E4FAA5596E1A98479FC" ("id", "name" ) FROM stdin; +COPY ties_data."bc563e4310b0538e6bdd35f52684160af5b23671" ("id", "name" ) FROM stdin; 1C02E96B2AAE036C7AE404BC38C308E0 Example Namespace/1 \. -COPY ties_data."CloudNativeApplication" ("id", "name", "REL_FK_realised-managedElement", "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "REL_FK_comprised-by-cloudNativeSystem", "REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", "REL_FK_deployed-on-namespace", "REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" ) FROM stdin; +COPY ties_data."e01fcb87ad2c34ce66c34420255e25aaca270e5e" ("id", "name", "REL_FK_realised-managedElement", "REL_ID_MANAGEDELEMENT_REALISED_BY_CLOUDNATIVEAPPLICATION", "REL_FK_comprised-by-cloudNativeSystem", "REL_ID_CLOUDNATIVESYSTEM_COMPRISES_CLOUDNATIVEAPPLICATION", "REL_FK_deployed-on-namespace", "REL_ID_CLOUDNATIVEAPPLICATION_DEPLOYED_ON_NAMESPACE" ) FROM stdin; AD42D90497E93D276215DF6D3B899E17 Cloud Native CUUPApp/8 \N \N \N \N \N \N 719BD5C7CD8A939D76A83DA95DA45C01 Example Cloud App/9 \N \N \N \N 1C02E96B2AAE036C7AE404BC38C308E0 urn:base64:Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA= 416F31E6EB09055326621F4919D35BFF Example Cloud App/10 \N \N \N \N \N \N C549905CF3CC890CE5746C5E10ACF00D Example Cloud App/19 \N \N \N \N \N \N \. -COPY ties_data."25978231183BE3B9ADD7DBE6C77F5E59696CDE5F" ("id", "name", "REL_FK_AB87B417CCD05C332DDD0C60F0C6AB41D38B05E5", "REL_ID_FC2F6A5A12917357B548C83F4B0C1AD58FA61413", "REL_FK_8C98B70070BBD11F90F192DDA3ECF6302390E956", "REL_ID_AFBF10D23507AD3B6408947D2A9AF8465BA7B08C" ) FROM stdin; +COPY ties_data."5f8facd51b2bbddc90d9dee9be697907441892d0" ("id", "name", "REL_FK_AB87B417CCD05C332DDD0C60F0C6AB41D38B05E5", "REL_ID_FC2F6A5A12917357B548C83F4B0C1AD58FA61413", "REL_FK_8C98B70070BBD11F90F192DDA3ECF6302390E956", "REL_ID_AFBF10D23507AD3B6408947D2A9AF8465BA7B08C" ) FROM stdin; AD42D90497E93D276215DF6D3B899E17 Cloud Native CUUPApp/8 \N \N \N \N 719BD5C7CD8A939D76A83DA95DA45C01 Example Cloud App/9 \N \N 1C02E96B2AAE036C7AE404BC38C308E0 urn:base64:Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo3MTlCRDVDN0NEOEE5MzlENzZBODNEQTk1REE0NUMwMTpERVBMT1lFRF9PTjpOYW1lc3BhY2U6MUMwMkU5NkIyQUFFMDM2QzdBRTQwNEJDMzhDMzA4RTA= 416F31E6EB09055326621F4919D35BFF Example Cloud App/10 6F02817AFE4D53237DB235EBE5378613 urn:base64:TWFuYWdlZEVsZW1lbnQ6NkYwMjgxN0FGRTRENTMyMzdEQjIzNUVCRTUzNzg2MTM6UkVBTElTRURfQlk6Q2xvdWROYXRpdmVBcHBsaWNhdGlvbjo0MTZGMzFFNkVCMDkwNTUzMjY2MjFGNDkxOUQzNUJGRg== \N \N C549905CF3CC890CE5746C5E10ACF00D Example Cloud App/19 \N \N \N \N \. -COPY ties_data."Sector" ("id", "geo-location", "sectorId", "azimuth" ) FROM stdin; +COPY ties_data."22174a23af5d5a96143c83ddfa78654df0acb697" ("id", "geo-location", "sectorId", "azimuth" ) FROM stdin; 2F445AA5744FA3D230FD6838531F1407 POINT(59.4019881 17.9419888) 1 1 F5128C172A70C4FCD4739650B06DE9E2 POINT(59.4019881 17.9419888) 2 2 ADB1BAAC878C0BEEFE3175C60F44BB1D POINT(59.4019881 17.9419888) 4 3 \. -COPY ties_data."GNBCUCPFunction" ("id", "pLMNId", "cmId", "fdn", "gNBCUName", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" ) FROM stdin; +COPY ties_data."c4a425179d3089b5288fdf059079d0ea26977f0f" ("id", "pLMNId", "cmId", "fdn", "gNBCUName", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUCPFUNCTION" ) FROM stdin; \. -COPY ties_data."GNBCUUPFunction" ("id", "cmId", "fdn", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" ) FROM stdin; -BFEEAC2CE60273CB0A78319CC201A7FE \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBCUUPFunction=8 1 8 E64371CD4D12ED0CED200DD3A7591784 urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU= +COPY ties_data."8fe520ccd54b8f72ef7b2d3061264ddc2481e4eb" ("id", "cmId", "fdn", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBCUUPFUNCTION" ) FROM stdin; +BFEEAC2CE60273CB0A78319CC201A7FE \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBCUUPFunction=8 1 8 E64371CD4D12ED0CED200DD3A7591784 urn:base64:TWFuYWdlZEVsZW1lbnQ6RTY0MzcxQ0Q0RDEyRUQwQ0VEMjAwREQzQTc1OTE3ODQ6TUFOQUdFUzpHTkJDVVVQRnVuY3Rpb246QkZFRUFDMkNFNjAyNzNDQjBBNzgzMTlDQzIwMUE3RkU= ["gnbcucp-gnbcuup-model:Weekend", "gnbcucp-gnbcuup-model:Weekday"] {"gnbcucp-gnbcuup-model:metadata": "value1", "gnbcucp-gnbcuup-model:meta": "value2"} \. -COPY ties_data."GNBDUFunction" ("id", "gNBDUId", "cmId", "fdn", "dUpLMNId", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "CD_sourceIds" ) FROM stdin; -D3215E08570BE58339C7463626B50E37 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=9 {"mcc":"456","mnc":"82"} 1 9 DA1039E77700A9EEFFA280049ECE9227 urn:base64:TWFuYWdlZEVsZW1lbnQ6REExMDM5RTc3NzAwQTlFRUZGQTI4MDA0OUVDRTkyMjc6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOkQzMjE1RTA4NTcwQkU1ODMzOUM3NDYzNjI2QjUwRTM3 [] -1050570EBB1315E1AE7A9FD5E1400A00 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=10 {"mcc":"456","mnc":"82"} 2 10 6F02817AFE4D53237DB235EBE5378613 urn:base64:TWFuYWdlZEVsZW1lbnQ6NkYwMjgxN0FGRTRENTMyMzdEQjIzNUVCRTUzNzg2MTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjEwNTA1NzBFQkIxMzE1RTFBRTdBOUZENUUxNDAwQTAw [] -25E690E22BDA90B9C4FEE1F083CBA597 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=13 {"mcc":"456","mnc":"82"} 2 13 27500EB447000209EE6E3CA1B31FBA92 urn:base64:TWFuYWdlZEVsZW1lbnQ6Mjc1MDBFQjQ0NzAwMDIwOUVFNkUzQ0ExQjMxRkJBOTI6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjI1RTY5MEUyMkJEQTkwQjlDNEZFRTFGMDgzQ0JBNTk3 [] -5A3085C3400C3096E2ED2321452766B1 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=14 {"mcc":"456","mnc":"82"} 2 14 06222D277EE209CD8DCA1FE61CE752E6 urn:base64:TWFuYWdlZEVsZW1lbnQ6MDYyMjJEMjc3RUUyMDlDRDhEQ0ExRkU2MUNFNzUyRTY6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBMzA4NUMzNDAwQzMwOTZFMkVEMjMyMTQ1Mjc2NkIx [] -5A548EA9D166341776CA0695837E55D8 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16 {"mcc":"456","mnc":"82"} 2 16 DC86CA7724113F4C0DF42BFEAA17FD53 urn:base64:TWFuYWdlZEVsZW1lbnQ6REM4NkNBNzcyNDExM0Y0QzBERjQyQkZFQUExN0ZENTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBNTQ4RUE5RDE2NjM0MTc3NkNBMDY5NTgzN0U1NUQ4 ["urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16","urn:cmHandle:/395221E080CCF0FD1924103B15873814"] -4CFF136200A2DE36205A13559C55DB2A \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=19 {"mcc":"456","mnc":"82"} 2 19 8D51EFC759166044DACBCA63C4EDFC51 urn:base64:TWFuYWdlZEVsZW1lbnQ6OEQ1MUVGQzc1OTE2NjA0NERBQ0JDQTYzQzRFREZDNTE6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjRDRkYxMzYyMDBBMkRFMzYyMDVBMTM1NTlDNTVEQjJB [] +COPY ties_data."o-ran-smo-teiv-ran-logical_GNBDUFunction" ("id", "gNBDUId", "cmId", "fdn", "dUpLMNId", "gNBIdLength", "gNBId", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "CD_sourceIds", "CD_classifiers", "CD_decorators", "REL_CD_classifiers_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION", "REL_CD_decorators_MANAGEDELEMENT_MANAGES_GNBDUFUNCTION" ) FROM stdin; +D3215E08570BE58339C7463626B50E37 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=9 {"mcc":{"mcca":"123","mccb":{"mccba":123}},"mcb":["a123","b123","c012"],"mnc":"82"} 1 9 DA1039E77700A9EEFFA280049ECE9227 urn:base64:TWFuYWdlZEVsZW1lbnQ6REExMDM5RTc3NzAwQTlFRUZGQTI4MDA0OUVDRTkyMjc6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOkQzMjE1RTA4NTcwQkU1ODMzOUM3NDYzNjI2QjUwRTM3 [] [] {} [] {} +1050570EBB1315E1AE7A9FD5E1400A00 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=10 {"mcc":{"mcca":"234","mccb":{"mccba":234}},"mcb":["a123","b123","c012"],"mnc":"82"} 2 10 6F02817AFE4D53237DB235EBE5378613 urn:base64:TWFuYWdlZEVsZW1lbnQ6NkYwMjgxN0FGRTRENTMyMzdEQjIzNUVCRTUzNzg2MTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjEwNTA1NzBFQkIxMzE1RTFBRTdBOUZENUUxNDAwQTAw [] [] {} [] {} +25E690E22BDA90B9C4FEE1F083CBA597 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=13 {"mcc":{"mcca":"345","mccb":{"mccba":345}},"mcb":["a123","b123","c012"],"mnc":"82"} 2 13 27500EB447000209EE6E3CA1B31FBA92 urn:base64:TWFuYWdlZEVsZW1lbnQ6Mjc1MDBFQjQ0NzAwMDIwOUVFNkUzQ0ExQjMxRkJBOTI6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjI1RTY5MEUyMkJEQTkwQjlDNEZFRTFGMDgzQ0JBNTk3 [] [] {} [] {} +5A3085C3400C3096E2ED2321452766B1 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=14 {"mcc":{"mcca":"456","mccb":{"mccba":456}},"mcb":["a123","b123","c012"],"mnc":"82"} 2 14 06222D277EE209CD8DCA1FE61CE752E6 urn:base64:TWFuYWdlZEVsZW1lbnQ6MDYyMjJEMjc3RUUyMDlDRDhEQ0ExRkU2MUNFNzUyRTY6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBMzA4NUMzNDAwQzMwOTZFMkVEMjMyMTQ1Mjc2NkIx [] [] {} [] {} +5A548EA9D166341776CA0695837E55D8 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16 {"mcc":{"mcca":"567","mccb":{"mccba":567}},"mcb":["a123","b123","c012"],"mnc":"82"} 2 16 DC86CA7724113F4C0DF42BFEAA17FD53 urn:base64:TWFuYWdlZEVsZW1lbnQ6REM4NkNBNzcyNDExM0Y0QzBERjQyQkZFQUExN0ZENTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBNTQ4RUE5RDE2NjM0MTc3NkNBMDY5NTgzN0U1NUQ4 ["urn:3gpp:dn:/SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16","urn:cmHandle:/395221E080CCF0FD1924103B15873814"] ["test-app-module:Indoor","test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Stockholm", "test-app-module:data":"test"} ["test-app-module:Indoor","test-app-module:Rural","test-app-module:Weekend"] {"test-app-module:textdata":"Stockholm", "test-app-module:data":"test"} +4CFF136200A2DE36205A13559C55DB2A \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=19 {"mcc":{"mcca":"678","mccb":{"mccba":678}},"mcb":["a123","b123","c012"],"mnc":"82"} 2 19 8D51EFC759166044DACBCA63C4EDFC51 urn:base64:TWFuYWdlZEVsZW1lbnQ6OEQ1MUVGQzc1OTE2NjA0NERBQ0JDQTYzQzRFREZDNTE6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjRDRkYxMzYyMDBBMkRFMzYyMDVBMTM1NTlDNTVEQjJB [] [] {} [] {} \. -COPY ties_data."7D7AACEBB0E4E4732835BA4BFE708DDD3738962D" ("id", "gNBDUId", "cmId", "3786A6CA64C9422F9E7FC35B7B039F345BBDDA65", "dUpLMNId", "gNBIdLength", "gNBId", "REL_FK_48B14FA5B787C6398AD1DE5EE670AD0D2A2CB36F", "REL_ID_BDE0B6C74D14AC109D29A08D80E92D4D0DCAEB0B" ) FROM stdin; +COPY ties_data."3fdb9cd7557edf559a0e4de88df220e7545884b5" ("id", "gNBDUId", "cmId", "3786A6CA64C9422F9E7FC35B7B039F345BBDDA65", "dUpLMNId", "gNBIdLength", "gNBId", "REL_FK_48B14FA5B787C6398AD1DE5EE670AD0D2A2CB36F", "REL_ID_BDE0B6C74D14AC109D29A08D80E92D4D0DCAEB0B" ) FROM stdin; D3215E08570BE58339C7463626B50E37 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=9 {"mcc":"456","mnc":"82"} 1 9 DA1039E77700A9EEFFA280049ECE9227 urn:base64:TWFuYWdlZEVsZW1lbnQ6REExMDM5RTc3NzAwQTlFRUZGQTI4MDA0OUVDRTkyMjc6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOkQzMjE1RTA4NTcwQkU1ODMzOUM3NDYzNjI2QjUwRTM3 1050570EBB1315E1AE7A9FD5E1400A00 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=10 {"mcc":"456","mnc":"82"} 2 10 6F02817AFE4D53237DB235EBE5378613 urn:base64:TWFuYWdlZEVsZW1lbnQ6NkYwMjgxN0FGRTRENTMyMzdEQjIzNUVCRTUzNzg2MTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjEwNTA1NzBFQkIxMzE1RTFBRTdBOUZENUUxNDAwQTAw 25E690E22BDA90B9C4FEE1F083CBA597 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=13 {"mcc":"456","mnc":"82"} 2 13 27500EB447000209EE6E3CA1B31FBA92 urn:base64:TWFuYWdlZEVsZW1lbnQ6Mjc1MDBFQjQ0NzAwMDIwOUVFNkUzQ0ExQjMxRkJBOTI6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjI1RTY5MEUyMkJEQTkwQjlDNEZFRTFGMDgzQ0JBNTk3 5A3085C3400C3096E2ED2321452766B1 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=14 {"mcc":"456","mnc":"82"} 2 14 06222D277EE209CD8DCA1FE61CE752E6 urn:base64:TWFuYWdlZEVsZW1lbnQ6MDYyMjJEMjc3RUUyMDlDRDhEQ0ExRkU2MUNFNzUyRTY6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBMzA4NUMzNDAwQzMwOTZFMkVEMjMyMTQ1Mjc2NkIx -5A548EA9D166341776CA0695837E55D8 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16 {"mcc":"456","mnc":"82"} 2 16 DC86CA7724113F4C0DF42BFEAA17FD53 urn:base64:TWFuYWdlZEVsZW1lbnQ6REM4NkNBNzcyNDExM0Y0QzBERjQyQkZFQUExN0ZENTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBNTQ4RUE5RDE2NjM0MTc3NkNBMDY5NTgzN0U1NUQ4 +5A548EA9D166341776CA0695837E55D8 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=16 {"mcc":"456","mnc":"82"} 2 16 DC86CA7724113F4C0DF42BFEAA17FD53 urn:base64:TWFuYWdlZEVsZW1lbnQ6REM4NkNBNzcyNDExM0Y0QzBERjQyQkZFQUExN0ZENTM6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjVBNTQ4RUE5RDE2NjM0MTc3NkNBMDY5NTgzN0U1NUD4 4CFF136200A2DE36205A13559C55DB2A \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/GNBDUFunction=19 {"mcc":"456","mnc":"82"} 2 19 8D51EFC759166044DACBCA63C4EDFC51 urn:base64:TWFuYWdlZEVsZW1lbnQ6OEQ1MUVGQzc1OTE2NjA0NERBQ0JDQTYzQzRFREZDNTE6TUFOQUdFUzpHTkJEVUZ1bmN0aW9uOjRDRkYxMzYyMDBBMkRFMzYyMDVBMTM1NTlDNTVEQjJB \. -COPY ties_data."AntennaCapability" ("id", "nRFqBands", "eUtranFqBands", "cmId", "fdn", "geranFqBands", "REL_FK_used-by-lteSectorCarrier" ) FROM stdin; +COPY ties_data."88f1bd76c7a935fb505cf235e6819f46c55ec98a" ("id", "nRFqBands", "eUtranFqBands", "cmId", "fdn", "geranFqBands", "REL_FK_used-by-lteSectorCarrier" ) FROM stdin; 5835F77BE9D4E102316BD59195F6370B ["123","456","789"] ["123","4564","789"] \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaCapability=1 ["123","456","789"] \N A77B237A541B2D3225B4B61D3098E4AA ["123","456","789"] ["123","4564","789"] \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaCapability=3 ["123","456","789"] \N \. -COPY ties_data."NRCellDU" ("id", "nRPCI", "cmId", "cellLocalId", "fdn", "nCI", "nRTAC", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_NRCELLDU", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-logical_NRCellDU" ("id", "nRPCI", "cmId", "cellLocalId", "fdn", "nCI", "nRTAC", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_NRCELLDU", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRCELLDU" ) FROM stdin; 98C3A4591A37718E1330F0294E23B62A 789 \N 1 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=1 1 456 F5128C172A70C4FCD4739650B06DE9E2 urn:base64:U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ== D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ== F9546E82313AC1D5E690DCD7BE55606F 789 \N 2 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=2 2 456 F5128C172A70C4FCD4739650B06DE9E2 urn:base64:U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTpGOTU0NkU4MjMxM0FDMUQ1RTY5MERDRDdCRTU1NjA2Rg== D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpGOTU0NkU4MjMxM0FDMUQ1RTY5MERDRDdCRTU1NjA2Rg== B480427E8A0C0B8D994E437784BB382F 789 \N 3 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=3 3 456 F5128C172A70C4FCD4739650B06DE9E2 urn:base64:U2VjdG9yOkY1MTI4QzE3MkE3MEM0RkNENDczOTY1MEIwNkRFOUUyOkdST1VQUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg== D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg== @@ -122,7 +123,7 @@ B480427E8A0C0B8D994E437784BB382F 789 \N 3 SubNetwork=SolarSystem/SubNetwork=Eart B3B0A1939EFCA654A37005B6A7F24BD7 789 \N 93 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=93 93 456 \N \N 4CFF136200A2DE36205A13559C55DB2A urn:base64:R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTpCM0IwQTE5MzlFRkNBNjU0QTM3MDA1QjZBN0YyNEJENw== \. -COPY ties_data."50AC08AB775076E74FC4891954F1D99D3D293ACC" ("id", "nRPCI", "cmId", "020335B0F627C169E24167748C38FE756FB34AE2", "fdn", "nCI", "nRTAC", "REL_FK_609963BFEE15FF824280FBE201313C3CDACDDDCE", "REL_ID_040FC8B06B420BA5708AF4798102D1E65FB4DC61" ) FROM stdin; +COPY ties_data."300672c8a708d6af0b9af2f9accdff5e6e005721" ("id", "nRPCI", "cmId", "020335B0F627C169E24167748C38FE756FB34AE2", "fdn", "nCI", "nRTAC", "REL_FK_609963BFEE15FF824280FBE201313C3CDACDDDCE", "REL_ID_040FC8B06B420BA5708AF4798102D1E65FB4DC61" ) FROM stdin; 98C3A4591A37718E1330F0294E23B62A 789 \N 1 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=1 1 456 D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTo5OEMzQTQ1OTFBMzc3MThFMTMzMEYwMjk0RTIzQjYyQQ== F9546E82313AC1D5E690DCD7BE55606F 789 \N 2 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=2 2 456 D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpGOTU0NkU4MjMxM0FDMUQ1RTY5MERDRDdCRTU1NjA2Rg== B480427E8A0C0B8D994E437784BB382F 789 \N 3 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=3 3 456 D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUkNlbGxEVTpCNDgwNDI3RThBMEMwQjhEOTk0RTQzNzc4NEJCMzgyRg== @@ -132,86 +133,75 @@ B3B0A1939EFCA654A37005B6A7F24BD7 789 \N 93 SubNetwork=SolarSystem/SubNetwork=Ear F26F279E91D0941DB4F646E707EA403A 789 \N 94 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRCellDU=94 94 456 4CFF136200A2DE36205A13559C55DB2A urn:base64:R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpQUk9WSURFUzpOUkNlbGxEVTpGMjZGMjc5RTkxRDA5NDFEQjRGNjQ2RTcwN0VBNDAzQQ== \. -COPY ties_data."NRSectorCarrier" ("id", "fdn", "frequencyUL", "cmId", "essScLocalId", "arfcnUL", "frequencyDL", "arfcnDL", "REL_FK_used-by-nrCellDu", "REL_ID_NRCELLDU_USES_NRSECTORCARRIER", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY" ) FROM stdin; -E49D942C16E0364E1E0788138916D70C SubNetwork=SolarSyst3em/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRSectorCarrier=3 20 \N 20 3 20 20 B480427E8A0C0B8D994E437784BB382F urn:base64:TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM= D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM= A77B237A541B2D3225B4B61D3098E4AA urn:base64:TlJTZWN0b3JDYXJyaWVyOkU0OUQ5NDJDMTZFMDM2NEUxRTA3ODgxMzg5MTZENzBDOlVTRVM6QW50ZW5uYUNhcGFiaWxpdHk6QTc3QjIzN0E1NDFCMkQzMjI1QjRCNjFEMzA5OEU0QUE= +COPY ties_data."39a335dca201ef99ae06f4ffd1908b534f8c6c39" ("id", "fdn", "frequencyUL", "cmId", "essScLocalId", "arfcnUL", "frequencyDL", "arfcnDL", "REL_FK_used-by-nrCellDu", "REL_ID_NRCELLDU_USES_NRSECTORCARRIER", "REL_FK_provided-by-gnbduFunction", "REL_ID_GNBDUFUNCTION_PROVIDES_NRSECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_NRSECTORCARRIER_USES_ANTENNACAPABILITY", "CD_classifiers", "CD_decorators" ) FROM stdin; +E49D942C16E0364E1E0788138916D70C SubNetwork=SolarSyst3em/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/NRSectorCarrier=3 20 \N 20 3 20 20 B480427E8A0C0B8D994E437784BB382F urn:base64:TlJDZWxsRFU6QjQ4MDQyN0U4QTBDMEI4RDk5NEU0Mzc3ODRCQjM4MkY6VVNFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM= D3215E08570BE58339C7463626B50E37 urn:base64:R05CRFVGdW5jdGlvbjpEMzIxNUUwODU3MEJFNTgzMzlDNzQ2MzYyNkI1MEUzNzpQUk9WSURFUzpOUlNlY3RvckNhcnJpZXI6RTQ5RDk0MkMxNkUwMzY0RTFFMDc4ODEzODkxNkQ3MEM= A77B237A541B2D3225B4B61D3098E4AA urn:base64:TlJTZWN0b3JDYXJyaWVyOkU0OUQ5NDJDMTZFMDM2NEUxRTA3ODgxMzg5MTZENzBDOlVTRVM6QW50ZW5uYUNhcGFiaWxpdHk6QTc3QjIzN0E1NDFCMkQzMjI1QjRCNjFEMzA5OEU0QUE= ["gnbcucp-gnbcuup-model:Weekend", "gnbcucp-gnbcuup-model:Weekday"] {"gnbcucp-gnbcuup-model:metadata": "value1", "gnbcucp-gnbcuup-model:meta": "value2"} \. -COPY ties_data."AntennaModule" ("id", "mechanicalAntennaTilt", "fdn", "cmId", "antennaModelNumber", "totalTilt", "mechanicalAntennaBearing", "positionWithinSector", "electricalAntennaTilt", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_ANTENNAMODULE", "REL_FK_installed-at-site", "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" ) FROM stdin; -278A05C67D47D117C2DC5BDF5E00AE70 123 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModule=1 \N ['123-abc'] 45 123 ['123', '456', '789'] 1 ADB1BAAC878C0BEEFE3175C60F44BB1D urn:base64:U2VjdG9yOkFEQjFCQUFDODc4QzBCRUVGRTMxNzVDNjBGNDRCQjFEOkdST1VQUzpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcw \N \N -279A05C67D47D117C2DC5BDF5E00AE70 456 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModule=2 \N ['123-xyz'] 45 123 ['123', '456', '789'] 1 \N \N \N \N +COPY ties_data."f8caf5ebe876c3001d67efe06e4d83abf0babe31" ("id", "mechanicalAntennaTilt", "antennaBeamWidth", "geo-location", "fdn", "cmId", "antennaModelNumber", "totalTilt", "mechanicalAntennaBearing", "positionWithinSector", "electricalAntennaTilt", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_ANTENNAMODULE", "REL_FK_installed-at-site", "REL_ID_ANTENNAMODULE_INSTALLED_AT_SITE" ) FROM stdin; +278A05C67D47D117C2DC5BDF5E00AE70 123 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModule=1 \N ['123-abc'] 45 123 ['123', '456', '789'] 1 ADB1BAAC878C0BEEFE3175C60F44BB1D urn:base64:U2VjdG9yOkFEQjFCQUFDODc4QzBCRUVGRTMxNzVDNjBGNDRCQjFEOkdST1VQUzpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcw \N \N +279A05C67D47D117C2DC5BDF5E00AE70 456 \N \N SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModule=2 \N ['123-xyz'] 45 123 ['123', '456', '789'] 1 \N \N \N \N \. -COPY ties_data."B69D3E92CA22CE61B921AE61BD3CF031791CF714" ("id", "fdn" ) FROM stdin; +COPY ties_data."341622dca4e0350289717b52df5883edc3fa0280" ("id", "fdn" ) FROM stdin; 378A05C67D47D117C2DC5BDF5E00AE70 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=11 379A05C67D47D117C2DC5BDF5E00AE70 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=12 478A05C67D47D117C2DC5BDF5E00AE70 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=21 479A05C67D47D117C2DC5BDF5E00AE70 SubNetwork=SolarSystem/SubNetwork=Earth/SubNetwork=Europe/SubNetwork=Hungary/AntennaModuleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=22 \. -COPY ties_data."ENodeBFunction" ("id", "eNBId", "cmId", "eNodeBPlmnId", "fdn", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "REL_FK_realised-by-physicalNetworkAppliance", "REL_ID_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-logical_ENodeBFunction" ("id", "eNBId", "cmId", "eNodeBPlmnId", "fdn", "REL_FK_managed-by-managedElement", "REL_ID_MANAGEDELEMENT_MANAGES_ENODEBFUNCTION", "REL_FK_realised-by-physicalNetworkAppliance", "REL_ID_ENODEBFUNCTION_REALISED_BY_PHYSICALNETWORKAPPLIANCE" ) FROM stdin; \. -COPY ties_data."EUtranCell" ("id", "cellId", "cmId", "earfcn", "duplexType", "tac", "fdn", "earfcndl", "earfcnul", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_EUTRANCELL", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-logical_EUtranCell" ("id", "cellId", "cmId", "earfcn", "duplexType", "tac", "fdn", "earfcndl", "earfcnul", "REL_FK_grouped-by-sector", "REL_ID_SECTOR_GROUPS_EUTRANCELL", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_EUTRANCELL" ) FROM stdin; \. -COPY ties_data."LTESectorCarrier" ("id", "fdn", "cmId", "sectorCarrierType", "essScLocalId", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY", "REL_FK_used-by-euTranCell", "REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" ) FROM stdin; +COPY ties_data."c88307168935f02fdecc084ea5040bb9db16c701" ("id", "fdn", "cmId", "sectorCarrierType", "essScLocalId", "REL_FK_provided-by-enodebFunction", "REL_ID_ENODEBFUNCTION_PROVIDES_LTESECTORCARRIER", "REL_FK_used-antennaCapability", "REL_ID_LTESECTORCARRIER_USES_ANTENNACAPABILITY", "REL_FK_used-by-euTranCell", "REL_ID_EUTRANCELL_USES_LTESECTORCARRIER" ) FROM stdin; \. -COPY ties_data."NRCellCU" ("id", "fdn", "cmId", "plmnId", "nCI", "cellLocalId", "nRTAC", "REL_FK_provided-by-gnbcucpFunction", "REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-logical_NRCellCU" ("id", "fdn", "cmId", "plmnId", "nCI", "cellLocalId", "nRTAC", "REL_FK_provided-by-gnbcucpFunction", "REL_ID_GNBCUCPFUNCTION_PROVIDES_NRCELLCU" ) FROM stdin; \. -COPY ties_data."PhysicalNetworkAppliance" ("id", "geo-location", "cmId", "name", "type", "REL_FK_installed-at-site", "REL_ID_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" ) FROM stdin; +COPY ties_data."57a20807ab3f39c86b0b5bf9a819e0881353fa1e" ("id", "geo-location", "cmId", "name", "type", "REL_FK_installed-at-site", "REL_ID_PHYSICALNETWORKAPPLIANCE_INSTALLED_AT_SITE" ) FROM stdin; \. -COPY ties_data."Site" ("id", "geo-location", "cmId", "name" ) FROM stdin; +COPY ties_data."o-ran-smo-teiv-ran-equipment_Site" ("id", "geo-location", "cmId", "name" ) FROM stdin; \. -COPY ties_data."GNBCUCPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ("id", "aSide_GNBCUCPFunction", "bSide_CloudNativeApplication" ) FROM stdin; +COPY ties_data."7cd7062ea24531b2f48e4f2fdc51eaf0b82f88c7" ("id", "aSide_GNBCUCPFunction", "bSide_CloudNativeApplication" ) FROM stdin; \. -COPY ties_data."GNBCUUPFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ("id", "aSide_GNBCUUPFunction", "bSide_CloudNativeApplication" ) FROM stdin; -urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc= BFEEAC2CE60273CB0A78319CC201A7FE AD42D90497E93D276215DF6D3B899E17 +COPY ties_data."70a4a84bca01ea022ab24d8cb82422c572922675" ("id", "aSide_GNBCUUPFunction", "bSide_CloudNativeApplication", "CD_classifiers", "CD_decorators" ) FROM stdin; +urn:base64:R05CQ1VVUEZ1bmN0aW9uOkJGRUVBQzJDRTYwMjczQ0IwQTc4MzE5Q0MyMDFBN0ZFOlJFQUxJU0VEX0JZOkNsb3VkTmF0aXZlQXBwbGljYXRpb246QUQ0MkQ5MDQ5N0U5M0QyNzYyMTVERjZEM0I4OTlFMTc= BFEEAC2CE60273CB0A78319CC201A7FE AD42D90497E93D276215DF6D3B899E17 ["gnbcucp-gnbcuup-model:Weekend", "gnbcucp-gnbcuup-model:Weekday"] {"gnbcucp-gnbcuup-model:metadata": "value1", "gnbcucp-gnbcuup-model:meta": "value2"} \. -COPY ties_data."GNBDUFUNCTION_REALISED_BY_CLOUDNATIVEAPPLICATION" ("id", "aSide_GNBDUFunction", "bSide_CloudNativeApplication" ) FROM stdin; +COPY ties_data."10484f157f490eb5b27e40dbfaf4d5f2be17c57c" ("id", "aSide_GNBDUFunction", "bSide_CloudNativeApplication" ) FROM stdin; urn:base64:R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE 4CFF136200A2DE36205A13559C55DB2A C549905CF3CC890CE5746C5E10ACF00D \. -COPY ties_data."AC201B3A42917A9A983A1E3683B67C38C50630FC" ("id", "aSide_B0FD0521695A211BFF76F413A31F28CBA32E57ED", "bSide_84EF1134719BB6FCF33A94FF770311FC722BCF41" ) FROM stdin; +COPY ties_data."f86057a8762a50b1c7fb07af9d5c001bffaefd15" ("id", "aSide_B0FD0521695A211BFF76F413A31F28CBA32E57ED", "bSide_84EF1134719BB6FCF33A94FF770311FC722BCF41" ) FROM stdin; urn:base64:R05CRFVGdW5jdGlvbjo0Q0ZGMTM2MjAwQTJERTM2MjA1QTEzNTU5QzU1REIyQTpSRUFMSVNFRF9CWTpDbG91ZE5hdGl2ZUFwcGxpY2F0aW9uOkM1NDk5MDVDRjNDQzg5MENFNTc0NkM1RTEwQUNGMDBE 4CFF136200A2DE36205A13559C55DB2A C549905CF3CC890CE5746C5E10ACF00D \. -COPY ties_data."ANTENNACAPABILITY_REALISED_BY_ANTENNAMODULE" ("id", "aSide_AntennaCapability", "bSide_AntennaModule" ) FROM stdin; +COPY ties_data."5b8a47d4a8297a0a1d31e091af06e26d25ef6caf" ("id", "aSide_AntennaCapability", "bSide_AntennaModule" ) FROM stdin; \. -COPY ties_data."ANTENNAMODULE_REALISED_BY_ANTENNAMODULE" ("id", "aSide_AntennaModule", "bSide_AntennaModule" ) FROM stdin; +COPY ties_data."5123d0adfb7b4a04e7f2e5e1783f476ed5cf76f6" ("id", "aSide_AntennaModule", "bSide_AntennaModule" ) FROM stdin; urn:base64:QW50ZW5uYU1vZHVsZToyNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjI3OEEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg== 278A05C67D47D117C2DC5BDF5E00AE70 279A05C67D47D117C2DC5BDF5E00AE70 \. -COPY ties_data."B9B76FD20FF23B2A41C82CB5EDF6FA25B6AC2BC6" ("id", "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C", "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" ) FROM stdin; +COPY ties_data."cd39d44beed963d50df42cd301e63d288f911c97" ("id", "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C", "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" ) FROM stdin; urn:base64:QW50ZW5uYU1vZHVsZTozNzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpSRUFMSVNFRF9CWTpBbnRlbm5hTW9kdWxlOjM3OUEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg== 378A05C67D47D117C2DC5BDF5E00AE70 379A05C67D47D117C2DC5BDF5E00AE70 \. -COPY ties_data."C35AE10CFF62DEDC5E3FC3C40E47373B10800818" ("id", "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C", "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" ) FROM stdin; +COPY ties_data."c6f3a3396e9165e886da928c5fe1382fb20dc850" ("id", "aSide_2A2D3374BF907674FA1905478E30ACB8882DC03C", "bSide_EE6DD4A2CFD743779BBCBFC18FC296EF6D72EB1E" ) FROM stdin; urn:base64:QW50ZW5uYU1vZHVsZTo0NzhBMDVDNjdENDdEMTE3QzJEQzVCREY1RTAwQUU3MDpERVBMT1lFRF9CWTpBbnRlbm5hTW9kdWxlOjQ3OUEwNUM2N0Q0N0QxMTdDMkRDNUJERjVFMDBBRTcwCg== 478A05C67D47D117C2DC5BDF5E00AE70 479A05C67D47D117C2DC5BDF5E00AE70 \. -COPY ties_model.module_reference("name", "includedModules", "content", "ownerAppId", "status") FROM stdin; -gnbdu-function-model [] Z25kYnUtZnVuY3Rpb24tbW9kZWwgeWFuZyBtb2RlbCBmaWxlCg== ADDITIONAL_MODULE IN_USAGE -gnbcucp-gnbcuup-model [] Z25iY3VjcC1nbmJjdXVwLW1vZGVsIHlhbmcgbW9kZWwgZmlsZQo= ADDITIONAL_MODULE IN_USAGE -gnbcucp-gnbcuup-old-model [] Z25iY3VjcC1nbmJjdXVwLW1vZGVsIHlhbmcgbW9kZWwgZmlsZQo= ADDITIONAL_MODULE DEPRECATED -\. - -COPY ties_model.decorators ("name", "dataType", "moduleReferenceName" ) FROM stdin; -gnbdu-function-model:location TEXT gnbdu-function-model -gnbcucp-gnbcuup-model:metadata JSONB gnbcucp-gnbcuup-model -gnbcucp-gnbcuup-old-model:metadata JSONB gnbcucp-gnbcuup-old-model -\. - -COPY ties_model.classifiers ("name", "moduleReferenceName" ) FROM stdin; -gnbdu-function-model:Rural gnbdu-function-model -gnbcucp-gnbcuup-model:Weekend gnbcucp-gnbcuup-model -gnbcucp-gnbcuup-old-model:Weekend gnbcucp-gnbcuup-old-model +COPY ties_model.module_reference("name", "namespace", "domain", "includedModules", "revision", "content") FROM stdin; +gnbdu-function-model \N \N [] 2024-05-02 Z25kYnUtZnVuY3Rpb24tbW9kZWwgeWFuZyBtb2RlbCBmaWxlCg== +gnbcucp-gnbcuup-model \N \N [] 2024-05-02 Z25iY3VjcC1nbmJjdXVwLW1vZGVsIHlhbmcgbW9kZWwgZmlsZQo= +gnbcucp-gnbcuup-old-model \N \N [] 2024-05-02 Z25iY3VjcC1nbmJjdXVwLW1vZGVsIHlhbmcgbW9kZWwgZmlsZQo= +module-rapp-module \N \N [] 2024-05-01 dGVzdE1vZHVsZQo= \. ; \ No newline at end of file diff --git a/teiv/src/test/resources/pgsqlschema/model.sql b/teiv/src/test/resources/pgsqlschema/model.sql new file mode 100644 index 0000000..335817f --- /dev/null +++ b/teiv/src/test/resources/pgsqlschema/model.sql @@ -0,0 +1,91 @@ +-- +-- ============LICENSE_START======================================================= +-- Copyright (C) 2024 Ericsson +-- Modifications Copyright (C) 2024 OpenInfra Foundation Europe +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- SPDX-License-Identifier: Apache-2.0 +-- ============LICENSE_END========================================================= +-- + +BEGIN; + +COPY ties_model.hash_info("name", "hashedValue", "type") FROM stdin; +FK_test-built-in-module_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_aSide_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters FK_2A5C84A2226EE0FCAAA513CC5AF4CD78DDDAF49F CONSTRAINT +FK_test-built-in-module_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_bSide_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters FK_FBFE10B6F165A8EC2086B8DEAFA238E0DD6643F5 CONSTRAINT +FK_test-built-in-module_ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_aSide_EntityTypeA FK_2839E6FFDF7F3DF2687DAC3E57082AD6B22E9B30 CONSTRAINT +FK_test-built-in-module_ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_bSide_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters FK_33B5669A341584011D9A73FB491FF2242A158057 CONSTRAINT +FK_test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters_REL_FK_provided-by-entityTypeA FK_B0923C0CCED6CF47CFF759FFE1B810D6CA10D228 CONSTRAINT +FK_test-built-in-module_EntityTypeA_REL_FK_grouped-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters FK_02592FFA6AFD7EAC7AFAD936E3CD50708E4533E0 CONSTRAINT +FK_test-built-in-module_EntityTypeA_REL_FK_used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters FK_5CD9BCFA08278DA0BF902BAFBCFCDFCE4FF25FEF CONSTRAINT +PK_test-built-in-module_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_id PK_020B03AED5787D1B43ABBD9F2C26B494ADDBC7CD CONSTRAINT +PK_test-built-in-module_ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_id PK_4C48AAFA2160D74F9D13364AA2BE4FDB8A60689D CONSTRAINT +PK_test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters_id PK_7A421D526B36AA9EEF17964BC27011A12FF80DBB CONSTRAINT +PK_test-built-in-module_EntityTypeA_id PK_test-built-in-module_EntityTypeA_id CONSTRAINT +REL_CD_classifiers_ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_75B161E740A96ADBAE6F08D4F85684ECC29049B9 COLUMN +REL_CD_classifiers_ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_E2C3D598A06EA38133E23C1756ED58A66FE21386 COLUMN +REL_CD_classifiers_ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_74A44B167FDF37D6C8E79B5033FEF8BC384C881A COLUMN +REL_CD_decorators_ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_6F7211CAF505AECF9A565BC7A4AF56E7032CCC54 COLUMN +REL_CD_decorators_ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_92559ED73C761B860682582A040E745ECEC194D5 COLUMN +REL_CD_decorators_ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_F5B24D9A7273119D4D1519473D9EC88CB407E5CA COLUMN +REL_CD_sourceIds_ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_AB6BDADE3F6C750C9FDB6CAD6059C4CBCE67236C COLUMN +REL_CD_sourceIds_ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_F26C39EC1F710F3096BE0588F6783A03A378516A COLUMN +REL_CD_sourceIds_ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_CD_3B43F80D423BF8F96A2906643B7B4712604FC28B COLUMN +REL_FK_grouped-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters REL_FK_B7E43411C5C5079D49856E74A9FA63BD20C522C5 COLUMN +REL_FK_provided-by-entityTypeA REL_FK_provided-by-entityTypeA COLUMN +REL_FK_used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters REL_FK_A86937FEBD025CFDF6EE5BC386B4C569EB2652DA COLUMN +REL_ID_ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_ID_31A5B55158140557F09AE15589A8B8038416689B COLUMN +REL_ID_ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_ID_F64052A4F8BB3CC533EC15BBFB5E224F600735B0 COLUMN +REL_ID_ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS REL_ID_A974AD6DD8C4CA281D45693D3A61AE98FEE82845 COLUMN +UNIQUE_test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters_REL_ID_ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS UNIQUE_B1C2FC9A96300B2BE45785DE60E152D8E85FBE14 CONSTRAINT +UNIQUE_test-built-in-module_EntityTypeA_REL_ID_ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS UNIQUE_7715FF94E14F99CE4994ABBD8C2583CBA9EAE5BD CONSTRAINT +UNIQUE_test-built-in-module_EntityTypeA_REL_ID_ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS UNIQUE_67DB5E4BC34AB83BDC069A5CAF73B57967D5C2D9 CONSTRAINT +aSide_EntityTypeA aSide_EntityTypeA COLUMN +aSide_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters aSide_C812C285BEFA4EC42026AB075D9C65200A00F815 COLUMN +attributeA1WithAttributeNameLengthLongerThanSixtyThreeCharacters 6446B2D4BE5E367FB0396383C4BDEF42D51CF74F COLUMN +attributeA2WithAttributeNameLengthLongerThanSixtyThreeCharacters F03B534AFF0872651FED60C54AB56BEDADAB94B5 COLUMN +attributeA3WithAttributeNameLengthLongerThanSixtyThreeCharacters 333177AA699C0DE6399503171DCF48FB396322B0 COLUMN +attributeA4WithAttributeNameLengthLongerThanSixtyThreeCharacters 027B1A8019C6DEF04558B90D9D8B52253B82FEC6 COLUMN +attributeA5WithAttributeNameLengthLongerThanSixtyThreeCharacters 478D043D81678134EF1C8BFB073A70F882C4AF12 COLUMN +attributeA6WithAttributeNameLengthLongerThanSixtyThreeCharacters 8252D18D44F633831557076D827993C45278024D COLUMN +attributeA7WithAttributeNameLengthLongerThanSixtyThreeCharacters 68C48305AB6C3A30DD927F5D38562379374A4B31 COLUMN +bSide_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters bSide_A85CE100A012A71EF2ABA306BABE484AC2AAE515 COLUMN +test-built-in-module_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS FB1E124031A12CD85D3335194B39B193723A0490 TABLE +test-built-in-module_ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS 54110F8D085BBBA7BB6DE5CE71B511562090F7EE TABLE +test-built-in-module_EntityTypeA test-built-in-module_EntityTypeA TABLE +test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters 10B9F515756871D3EF6558FAF1F112BAE207945D TABLE +\. + +COPY ties_model.module_reference("name", "namespace", "domain", "includedModules", "revision", "content") FROM stdin; +test-existing-rapp-module \N \N [] 2024-05-02 dGVzdA== +test-module-for-deletion \N \N [] 2024-05-02 dGVzdA== +test-module-in-deleting-state \N \N [] 2024-05-02 dGVzdA== +module-rapp-module \N \N [] 2024-05-01 dGVzdE1vZHVsZQo= +test-built-in-module test-built-in-namespace TEST [] 2024-05-24 bW9kdWxlIHRlc3QtYnVpbHQtaW4tbW9kdWxlIHsNCiAgICB5YW5nLXZlcnNpb24gMS4xOw0KICAgIG5hbWVzcGFjZSAidGVzdC1idWlsdC1pbi1uYW1lc3BhY2UiOw0KDQogICAgaW1wb3J0IG8tcmFuLXNtby10ZWl2LWNvbW1vbi15YW5nLXR5cGVzIHsgcHJlZml4IG9yLXRlaXYtdHlwZXM7IH0NCg0KICAgIGltcG9ydCBvLXJhbi1zbW8tdGVpdi1jb21tb24teWFuZy1leHRlbnNpb25zIHsgcHJlZml4IG9yLXRlaXYteWV4dDsgfQ0KDQogICAgaW1wb3J0IF8zZ3BwLWNvbW1vbi15YW5nLXR5cGVzIHsgcHJlZml4IHR5cGVzM2dwcDsgfQ0KDQogICAgaW1wb3J0IGlldGYtZ2VvLWxvY2F0aW9uIHsNCiAgICAgICAgcHJlZml4IGdlbzsNCiAgICAgICAgcmVmZXJlbmNlICJSRkMgOTE3OTogQSBZQU5HIEdyb3VwaW5nIGZvciBHZW9ncmFwaGljIExvY2F0aW9ucyI7DQogICAgfQ0KDQogICAgb3JnYW5pemF0aW9uICJFcmljc3NvbiBBQiI7DQogICAgY29udGFjdCAiRXJpY3Nzb24gZmlyc3QgbGluZSBzdXBwb3J0IHZpYSBlbWFpbCI7DQogICAgZGVzY3JpcHRpb24NCiAgICAiVGVzdCB0b3BvbG9neSBtb2RlbC4iOw0KDQogICAgcmV2aXNpb24gIjIwMjQtMDUtMjQiIHsNCiAgICAgICAgZGVzY3JpcHRpb24gIkluaXRpYWwgcmV2aXNpb24uIjsNCiAgICAgICAgb3ItdGVpdi15ZXh0OmxhYmVsIDAuMy4wOw0KICAgIH0NCg0KICAgIG9yLXRlaXYteWV4dDpkb21haW4gVEVTVDsNCg0KICAgIGxpc3QgRW50aXR5VHlwZUEgew0KDQogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7DQogICAgICAgIGtleSBpZDsNCg0KICAgIH0NCg0KICAgIGxpc3QgRW50aXR5VHlwZUFXaXRoRW50aXR5VHlwZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnMgew0KDQogICAgICAgIHVzZXMgb3ItdGVpdi10eXBlczpUb3BfR3JwX1R5cGU7DQogICAgICAgIGtleSBpZDsNCg0KICAgICAgICBjb250YWluZXIgYXR0cmlidXRlcyB7DQogICAgICAgICAgICBsZWFmIGF0dHJpYnV0ZUExV2l0aEF0dHJpYnV0ZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnMgew0KICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBsZWFmIGF0dHJpYnV0ZUEyV2l0aEF0dHJpYnV0ZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnMgew0KICAgICAgICAgICAgICAgIHR5cGUgdWludDMyOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBsZWFmIGF0dHJpYnV0ZUEzV2l0aEF0dHJpYnV0ZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnMgew0KICAgICAgICAgICAgICAgIHR5cGUgaW50MzI7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGxlYWYgYXR0cmlidXRlQTRXaXRoQXR0cmlidXRlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVycyB7DQogICAgICAgICAgICAgICAgdHlwZSBpbnQ2NDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgbGVhZiBhdHRyaWJ1dGVBNVdpdGhBdHRyaWJ1dGVOYW1lTGVuZ3RoTG9uZ2VyVGhhblNpeHR5VGhyZWVDaGFyYWN0ZXJzIHsNCiAgICAgICAgICAgICAgICB0eXBlIGRlY2ltYWw2NHsNCiAgICAgICAgICAgICAgICAgICAgZnJhY3Rpb24tZGlnaXRzIDY7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIHVuaXRzICJkZWdyZWVzIjsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgbGVhZi1saXN0IGF0dHJpYnV0ZUE2V2l0aEF0dHJpYnV0ZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnMgew0KICAgICAgICAgICAgICAgIHR5cGUgc3RyaW5nOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBjb250YWluZXIgYXR0cmlidXRlQTdXaXRoQXR0cmlidXRlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVycyB7DQogICAgICAgICAgICAgICAgdXNlcyB0eXBlczNncHA6UExNTklkOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBFTlRJVFlUWVBFQV9VU0VTX0VOVElUWVRZUEVBV0lUSEVOVElUWVRZUEVOQU1FTEVOR1RITE9OR0VSVEhBTlNJWFRZVEhSRUVDSEFSQUNURVJTIHsgLy8gMC4uMSB0byAwLi4xDQoNCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsNCiAgICAgICAga2V5IGlkOw0KDQogICAgICAgIGxlYWYgdXNlZC1lbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVycyB7DQogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRW50aXR5VHlwZUE7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgfQ0KDQogICAgICAgIGxlYWYgdXNlZC1ieS1lbnRpdHlUeXBlQSB7DQogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgRW50aXR5VHlwZUFXaXRoRW50aXR5VHlwZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnM7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgfQ0KICAgIH0NCg0KICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5USVRZVFlQRUFfUFJPVklERVNfRU5USVRZVFlQRUFXSVRIRU5USVRZVFlQRU5BTUVMRU5HVEhMT05HRVJUSEFOU0lYVFlUSFJFRUNIQVJBQ1RFUlMgeyAvLyAwLi4xIHRvIDAuLm4NCg0KICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IHByb3ZpZGVkLWVudGl0eVR5cGVBV2l0aEVudGl0eVR5cGVOYW1lTGVuZ3RoTG9uZ2VyVGhhblNpeHR5VGhyZWVDaGFyYWN0ZXJzIHsNCiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBFbnRpdHlUeXBlQTsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICB9DQoNCiAgICAgICAgbGVhZiBwcm92aWRlZC1ieS1lbnRpdHlUeXBlQSB7DQogICAgICAgICAgICBvci10ZWl2LXlleHQ6YlNpZGUgRW50aXR5VHlwZUFXaXRoRW50aXR5VHlwZU5hbWVMZW5ndGhMb25nZXJUaGFuU2l4dHlUaHJlZUNoYXJhY3RlcnM7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgfQ0KICAgIH0NCg0KICAgIG9yLXRlaXYteWV4dDpiaURpcmVjdGlvbmFsVG9wb2xvZ3lSZWxhdGlvbnNoaXAgRU5USVRZVFlQRUFfR1JPVVBTX0VOVElUWVRZUEVBV0lUSEVOVElUWVRZUEVOQU1FTEVOR1RITE9OR0VSVEhBTlNJWFRZVEhSRUVDSEFSQUNURVJTIHsgLy8gMC4ubiB0byAwLi4xDQoNCiAgICAgICAgdXNlcyBvci10ZWl2LXR5cGVzOlRvcF9HcnBfVHlwZTsNCiAgICAgICAga2V5IGlkOw0KDQogICAgICAgIGxlYWYgZ3JvdXBlZC1lbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVycyB7DQogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRW50aXR5VHlwZUE7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgfQ0KDQogICAgICAgIGxlYWYtbGlzdCBncm91cGVkLWJ5LWVudGl0eVR5cGVBIHsNCiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBFbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVyczsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICB9DQogICAgfQ0KDQogICAgb3ItdGVpdi15ZXh0OmJpRGlyZWN0aW9uYWxUb3BvbG9neVJlbGF0aW9uc2hpcCBFTlRJVFlUWVBFQV9JTlNUQUxMRURfQVRfRU5USVRZVFlQRUFXSVRIRU5USVRZVFlQRU5BTUVMRU5HVEhMT05HRVJUSEFOU0lYVFlUSFJFRUNIQVJBQ1RFUlMgeyAvLyAwLi5uIHRvIDAuLm0NCg0KICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZi1saXN0IGluc3RhbGxlZC1hdC1lbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVycyB7DQogICAgICAgICAgICBvci10ZWl2LXlleHQ6YVNpZGUgRW50aXR5VHlwZUE7DQogICAgICAgICAgICB0eXBlIGluc3RhbmNlLWlkZW50aWZpZXI7DQogICAgICAgfQ0KDQogICAgICAgIGxlYWYtbGlzdCBpbnN0YWxsZWQtZW50aXR5VHlwZUEgew0KICAgICAgICAgICAgb3ItdGVpdi15ZXh0OmJTaWRlIEVudGl0eVR5cGVBV2l0aEVudGl0eVR5cGVOYW1lTGVuZ3RoTG9uZ2VyVGhhblNpeHR5VGhyZWVDaGFyYWN0ZXJzOw0KICAgICAgICAgICAgdHlwZSBpbnN0YW5jZS1pZGVudGlmaWVyOw0KICAgICAgIH0NCiAgICB9DQoNCiAgICBvci10ZWl2LXlleHQ6YmlEaXJlY3Rpb25hbFRvcG9sb2d5UmVsYXRpb25zaGlwIEVOVElUWVRZUEVBV0lUSEVOVElUWVRZUEVOQU1FTEVOR1RITE9OR0VSVEhBTlNJWFRZVEhSRUVDSEFSQUNURVJTX1VTRVNfRU5USVRZVFlQRUFXSVRIRU5USVRZVFlQRU5BTUVMRU5HVEhMT05HRVJUSEFOU0lYVFlUSFJFRUNIQVJBQ1RFUlMgeyAvLyAwLi4xIHRvIDAuLjENCg0KICAgICAgICB1c2VzIG9yLXRlaXYtdHlwZXM6VG9wX0dycF9UeXBlOw0KICAgICAgICBrZXkgaWQ7DQoNCiAgICAgICAgbGVhZiB1c2VkLWVudGl0eVR5cGVBV2l0aEVudGl0eVR5cGVOYW1lTGVuZ3RoTG9uZ2VyVGhhblNpeHR5VGhyZWVDaGFyYWN0ZXJzIHsNCiAgICAgICAgICAgIG9yLXRlaXYteWV4dDphU2lkZSBFbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVyczsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICB9DQoNCiAgICAgICAgbGVhZiB1c2VkLWJ5LWVudGl0eVR5cGVBV2l0aEVudGl0eVR5cGVOYW1lTGVuZ3RoTG9uZ2VyVGhhblNpeHR5VGhyZWVDaGFyYWN0ZXJzIHsNCiAgICAgICAgICAgIG9yLXRlaXYteWV4dDpiU2lkZSBFbnRpdHlUeXBlQVdpdGhFbnRpdHlUeXBlTmFtZUxlbmd0aExvbmdlclRoYW5TaXh0eVRocmVlQ2hhcmFjdGVyczsNCiAgICAgICAgICAgIHR5cGUgaW5zdGFuY2UtaWRlbnRpZmllcjsNCiAgICAgICB9DQogICAgfQ0KfQ== +\. + +COPY ties_model.entity_info("storedAt", "name", "moduleReferenceName") FROM stdin; +test-built-in-module_EntityTypeA EntityTypeA test-built-in-module +test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module +\. + +COPY ties_model.relationship_info("name", "aSideAssociationName", "aSideMOType", "aSideModule", "aSideMinCardinality", "aSideMaxCardinality", "bSideAssociationName", "bSideMOType", "bSideModule", "bSideMinCardinality", "bSideMaxCardinality", "associationKind", "connectSameEntity", "relationshipDataLocation", "storedAt", "moduleReferenceName") FROM stdin; +ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 1 used-by-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 1 BI_DIRECTIONAL true RELATION test-built-in-module_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS test-built-in-module +ENTITYTYPEA_GROUPS_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS grouped-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeA test-built-in-module 0 9223372036854775807 grouped-by-entityTypeA EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 1 BI_DIRECTIONAL false A_SIDE test-built-in-module_EntityTypeA test-built-in-module +ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS installed-at-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeA test-built-in-module 0 9223372036854775807 installed-entityTypeA EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 9223372036854775807 BI_DIRECTIONAL false RELATION test-built-in-module_ENTITYTYPEA_INSTALLED_AT_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS test-built-in-module +ENTITYTYPEA_PROVIDES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS provided-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeA test-built-in-module 0 1 provided-by-entityTypeA EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 9223372036854775807 BI_DIRECTIONAL false B_SIDE test-built-in-module_EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module +ENTITYTYPEA_USES_ENTITYTYPEAWITHENTITYTYPENAMELENGTHLONGERTHANSIXTYTHREECHARACTERS used-entityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters EntityTypeA test-built-in-module 0 1 used-by-entityTypeA EntityTypeAWithEntityTypeNameLengthLongerThanSixtyThreeCharacters test-built-in-module 0 1 BI_DIRECTIONAL false A_SIDE test-built-in-module_EntityTypeA test-built-in-module +\. + +COMMIT; \ No newline at end of file -- 2.16.6